È una vecchia domanda ma una cosa ha bisogno di chiarimenti.
Mentre le risposte di Carl Norum e dogbane sono corrette, l'ipotesi è di cambiare lo script per farlo funzionare.
Quello che vorrei sottolineare è che non c'è bisogno di cambiare il copione:
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
Funziona se si richiama in modo diverso:
./fdtest 3>&1 4>&1
che significa per reindirizzare i descrittori di file 3 e 4 a 1 (che è l'output standard).
Il punto è che lo script è perfettamente bene nel voler scrivere descrittori diversi solo 1 e 2 (stdout e stderr) se tali descrittori sono forniti dal processo genitore.
Il vostro esempio è in realtà molto interessante perché questo script può scrivere a 4 diversi file:
./fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
Ora avete l'output in 4 file separati:
$ for f in file*; do echo $f:; cat $f; done
file1.txt:
This
file2.txt:
is
file3.txt:
a
file4.txt:
test.
Che cosa è più interessante su di esso è che il tuo programma non deve avere permessi di scrittura per quei file, perché in realtà non li apre.
Per esempio, quando ho eseguito sudo -s
di cambiare utente di root, creare una directory come root, e provare a eseguire il seguente comando come il mio utente normale (RSP nel mio caso) come questo:
# su rsp -c '../fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt'
ottengo un errore:
bash: file1.txt: Permission denied
Ma se faccio il reindirizzamento al di fuori di su
:
# su rsp -c '../fdtest' >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
(si noti la differenza tra apici) funziona e ottengo:
# ls -alp
total 56
drwxr-xr-x 2 root root 4096 Jun 23 15:05 ./
drwxrwxr-x 3 rsp rsp 4096 Jun 23 15:01 ../
-rw-r--r-- 1 root root 5 Jun 23 15:05 file1.txt
-rw-r--r-- 1 root root 39 Jun 23 15:05 file2.txt
-rw-r--r-- 1 root root 2 Jun 23 15:05 file3.txt
-rw-r--r-- 1 root root 6 Jun 23 15:05 file4.txt
che sono 4 file di proprietà di root in una directory di proprietà di root - anche se lo script non aveva autorizzazioni per creare quei file.
Un altro esempio potrebbe essere utilizzare chroot jail o un contenitore ed eseguire un programma all'interno del quale non avrebbe accesso a quei file anche se è stato eseguito come root e reindirizza ancora quei descrittori esternamente dove è necessario, senza fornire effettivamente l'accesso all'intero file system o qualsiasi altra cosa a questo script.
Il punto è che hai scoperto un meccanismo molto interessante e utile. Non è necessario aprire tutti i file all'interno del tuo script come suggerito in altre risposte. A volte è utile reindirizzarli durante l'invocazione dello script.
Insomma, questo:
echo "This"
è in realtà equivale a:
echo "This" >&1
e l'esecuzione del programma come:
./program >file.txt
è lo stesso:
./program 1>file.txt
Il numero 1 è solo un numero predefinito ed è stdout.
Ma anche questo programma:
#!/bin/bash
echo "This"
può produrre un errore "descrittore". Come? Quando eseguito come:
./fdtest2 >&-
L'output sarà:
./fdtest2: line 2: echo: write error: Bad file descriptor
Aggiungendo >&-
(che è lo stesso come 1>&-
) significa chiudere l'uscita standard. Aggiungere 2>&-
significherebbe chiudere lo stderr.
Si può anche fare una cosa più complicata.Lo script originale:
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
quando eseguito con un semplice:
./fdtest
stampe:
This
is
./fdtest: line 4: 3: Bad file descriptor
./fdtest: line 5: 4: Bad file descriptor
ma si può fare descrittori 3 e 4 di lavoro, ma il numero 1 sicuro eseguendo:
./fdtest 3>&1 4>&1 1>&-
Uscite:
./fdtest: line 2: echo: write error: Bad file descriptor
is
a
test.
Se si desidera descrittori sia 1 e 2 non riescono, correre in questo modo:
./fdtest 3>&1 4>&1 1>&- 2>&-
si ottiene:
a
test.
Perché? Non è successo nulla? Ha fatto ma senza stderr (numero descrittore di file 2) non hai visto i messaggi di errore!
Penso che sia molto utile sperimentare in questo modo per avere un'idea di come funzionano i descrittori e il loro reindirizzamento.
Il tuo script è davvero un esempio molto interessante - e sostengo che lo non si è rotto affatto, lo stavi solo usando male! :)
Questo è quello che sto cercando! Quindi ho bisogno di specificare un file da usare come spazio di archiviazione temporaneo con il comando exec, e poi chiuderli quando ho finito? Scusate, sono un po 'confuso con il comando exec, non lo uso molto. – Trcx
sì, ma non è temporaneo. Il file esisterà anche dopo il completamento del programma. – dogbane
Che potrebbe funzionare bene allora, sto provando a portare alcuni script per essere compatibili con lo scheduler di crontab, ma sto avendo problemi visto che cron non consente il piping di stdout negli script. – Trcx