bash: Qualche problema nell'uso di read <<< “$ VARIABLE” su una partizione root di sola lettura. Qualche soluzione alternativa conosciuta?


11

Solo per coincidenza ho dovuto usare il mio script ATA-ID-to-device-name (trovato qui: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) su una partizione di sola lettura / . Nel caso in cui tu sia curioso, era una console di ripristino di Ubuntu che ti consentirà di accedere alla tua /partizione, ma la monterà di sola lettura per impostazione predefinita. Sono contento di questo, perché altrimenti non avrei probabilmente mai scoperto che il mio script si comporta in modo strano su un sistema R / O a causa di una linea specifica, questa:

IFS=: read HostMain HostMid HostSub <<< "$HostFull"

Questo non funziona se non c'è permesso di scrittura. Non avrei pensato che avrebbe fallito, però. Ma a quanto pare l' <<<operatore non richiede di scrivere qualche file temporaneo da qualche parte.

Ma c'è un modo per aggirare la creazione di un file temporaneo o esiste un modo per specificare dove è scritto il file? Nella console di ripristino di Ubuntu, c'è --- stranamente --- permesso di scrivere sulla /rundirectory, quindi sarebbe, se potessi in qualche modo "dire" readdi scrivere il file temporaneo in un altro posto del solito.


2
@gniourf_gniourf No, "aprire un descrittore di file" non sarebbe un problema (perché dovrebbe?), e /dev/fdnon ha nulla a che fare con questo. <<<è però il colpevole, perché crea un file temporaneo (che deve essere scritto da qualche parte).
Gilles 'SO- smetti di essere malvagio' il

Risposte:


8

Un array potrebbe eseguire l'analisi della stringa senza la necessità di un file temporale. Non dimenticare di disattivare il globbing.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f

2
o anche senza IFS, se stai sicuro che non ci sono spazi a $HostFullcome così: Hosts=( ${HostFull//:/ } ). O anche se ci sono spazi: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(o qualcosa di simile, mi sto confondendo :D).
gniourf_gniourf

Hai ragione, mentre mostri che l'espansione dei parametri è un
affare

4

Sono d'accordo con @gniourf_gniourf, probabilmente hai bisogno dell'accesso in scrittura ma non dei descrittori di file, molto probabilmente un file.

È possibile verificarlo tracciando l'esecuzione del comando nella partizione di sola lettura.

{ strace -p "$$" & sleep 1; read var1 <<< "hi"; sleep 1; kill "$1"; }

Quanto sopra verrà eseguito stracesulla shell Bash (processo $$). Dorme quindi per 1 secondo, quindi esegue il readda HERE STRING. Ho messo la corda "hi"in questa posizione. Io poi sleepper un altro secondo e poi killil strace.

Esempio

Durante l'analisi di questo output noterai che un file viene aperto come O_WRONLY, che è per la scrittura in un file.

open("/tmp/sh-thd-4137571604", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

Sopra possiamo vedere su quale file viene scritto dalla tua sequenza di comandi.


1
Non "creare i descrittori di file" (non ha alcun senso). Per creare il file . Non è readche apre un file per la scrittura (sarebbe sciocco), è <<<.
Gilles 'SO- smetti di essere malvagio' il

@Gilles - grazie, non ho capito bene cosa mi stesse dicendo. Pulito il A.
slm

Grazie mille! Una tecnica molto bella, che potrebbe anche aiutarmi più volte in futuro con problemi simili. Tuttavia, una cosa mi sta preoccupando, ed è il fatto che /tmpè un percorso hardcoded . E probabilmente l'hai indovinato, /tmp è già lì, ma anche di sola lettura! E dal momento che lavorando su quella console di ripristino mi avrò effettuato l'accesso al mio file system live , non avrei voluto rovinare lì tramite il collegamento simbolico o altro (nemmeno mentre mi trovavo in quella console).
syntaxerror,

3

Trovo i parametri posizionali molto utili per questo tipo di attività. È generalmente portabile anche su tutte le shell e non costa fork né file temporanei.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub

Un buon approccio! Grazie. Inoltre, mi piace il fatto che non richiede strumenti esterni (che comunque non ci aspettiamo di trovare in quegli ambienti con restrizioni). L'unica cosa che potrebbe causare qualche problema è il $1, $2, $3roba: ricordo che in uno script, questo di solito riposare per un argomento passato allo script stesso . - E mentre ci siamo: se IFS è pensato per essere uno spazio, * IFS = * non farà in questa sintassi; dovrai specificare IFS = '' esplicitamente.
syntaxerror,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.