C'est une vieille question mais une chose doit être clarifiée .
Bien que les réponses de Carl Norum et dogbane soient correctes, l'hypothèse est de modifiez votre script pour le faire fonctionner .
Ce que j'aimerais souligner, c'est que vous n'avez pas besoin de changer le script :
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
Cela fonctionne si vous l'invoquez différemment :
./fdtest 3>&1 4>&1
ce qui signifie rediriger les descripteurs de fichiers 3 et 4 vers 1 (qui est la sortie standard).
Le fait est que le script est parfaitement bien. en voulant écrire sur des descripteurs autres que les 1 et 2 (stdout et stderr) si ces descripteurs sont fournis par le processus parent .
Votre exemple est en fait assez intéressant car ce script peut écrire dans 4 fichiers différents :
./fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
Maintenant vous avez la sortie dans 4 fichiers séparés :
$ for f in file*; do echo $f:; cat $f; done
file1.txt:
This
file2.txt:
is
file3.txt:
a
file4.txt:
test.
Qu'est-ce que plus intéressant est que votre programme n'a pas besoin d'avoir les droits d'écriture pour ces fichiers, car il ne les ouvre pas.
Par exemple, lorsque je lance sudo -s
pour changer l'utilisateur en Root, créer un répertoire en tant que Root, et essayer d'exécuter la commande suivante en tant qu'utilisateur normal (rsp dans mon cas) comme ceci :
# su rsp -c '../fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt'
Je reçois une erreur :
bash: file1.txt: Permission denied
Mais si je fais la redirection en dehors de su
:
# su rsp -c '../fdtest' >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
(notez la différence entre les guillemets simples) ça marche et je reçois :
# 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
qui sont 4 fichiers appartenant à Root dans un répertoire appartenant à Root - même si le script n'avait pas de permissions pour créer ces fichiers.
Un autre exemple serait d'utiliser chroot jail ou un conteneur et d'exécuter un programme à l'intérieur où il n'aurait pas accès à ces fichiers même s'il était exécuté en tant que Root et de toujours rediriger ces descripteurs vers l'extérieur où vous en avez besoin, sans réellement donner accès à l'ensemble du système de fichiers ou à quoi que ce soit d'autre à ce script.
Le fait est que vous avez découvert un mécanisme très intéressant et utile . Vous n'avez pas besoin d'ouvrir tous les fichiers à l'intérieur de votre script comme cela a été suggéré dans d'autres réponses. Il est parfois utile de les rediriger pendant l'invocation du script.
En résumé ça :
echo "This"
est en fait équivalent à :
echo "This" >&1
et en exécutant le programme en tant que :
./program >file.txt
est la même chose que :
./program 1>file.txt
Le nombre 1 est juste un nombre par défaut et c'est stdout.
Mais même ce programme :
#!/bin/bash
echo "This"
peut produire une erreur "Bad descriptor". Comment ? Lorsqu'il est exécuté en tant que :
./fdtest2 >&-
La sortie sera :
./fdtest2: line 2: echo: write error: Bad file descriptor
Ajout de >&-
(ce qui est identique à 1>&-
) signifie la fermeture de la sortie standard. Ajout de 2>&-
signifierait fermer le stderr.
Vous pouvez même faire une chose plus compliquée . Votre script original :
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
lorsqu'il est exécuté avec juste :
./fdtest
des empreintes :
This
is
./fdtest: line 4: 3: Bad file descriptor
./fdtest: line 5: 4: Bad file descriptor
Mais vous pouvez faire en sorte que les descripteurs 3 et 4 fonctionnent, mais que le numéro 1 échoue en courant :
./fdtest 3>&1 4>&1 1>&-
Il sort :
./fdtest: line 2: echo: write error: Bad file descriptor
is
a
test.
Si vous voulez que les descripteurs 1 et 2 échouent, exécutez-le comme ceci :
./fdtest 3>&1 4>&1 1>&- 2>&-
Vous obtenez :
a
test.
Pourquoi ? Rien n'a échoué ? Il a fait mais sans stderr (descripteur de fichier numéro 2) vous n'avez pas vu les messages d'erreur !
Je pense qu'il est très utile d'expérimenter de cette manière pour avoir une idée de la façon dont les descripteurs et leur redirection fonctionnent.
Votre script est un exemple très intéressant en effet - et je soutiens que il n'est pas du tout cassé, vous l'avez juste mal utilisé ! :)