Quand j'exécute le type type
command, cela me donne un résultat à la sortie standard.
Donc, maintenant j'essaie cette command:
type type > abc.txt
Il redirige la sortie standard vers abc.txt
. Donc, si cette command s'exécute sur le même process (bash lui-même), alors le descripteur de file 1 pointe vers abc.txt
. Après cela, chaque fois que j'utilise une command, ces résultats devraient aller au file abc.txt
, car le descripteur de file 1 pointe vers abc.txt
.
Cependant, les résultats vont toujours à la sortie standard. Cela signifie-t-il que les shell-ins s'exécutent sous un process fourchu?
Le descripteur de file 1
représente stdout
, le stream de sortie standard. Lorsque la redirection de sortie est utilisée dans le type type > abc.txt
, le shell ouvre le file abc.txt
pour l'écriture et le descripteur de file 1
est modifié de sorte qu'il pointe vers le file ouvert au lieu du terminal.
Cependant, cette redirection ne s'applique qu'à la command en cours d'exécution, de sorte que cela n'implique pas que la command s'exécute dans un process (ou un sous-shell) fourchu.
Si vous souhaitez que la redirection persiste, vous pouvez utiliser le shell exec
embedded pour modifier les descripteurs de file, par exemple pour redirect la sortie standard pour les commands successives, exécutez la command suivante.
exec >abc.txt
Soyez prudent en exécutant ceci car votre session shell sera difficile à utiliser si toutes les sorties de la command sont redirigées vers un file au lieu de votre terminal. Vous pouvez restaurer le descripteur de file stdout
sur le périphérique de sortie du terminal en le redirigeant vers le même périphérique pointé par stderr
(descripteur de file 2
):
exec >&2
Pour plus de détails, voir:
Normalement, pour redirect une command, tout ce que le shell doit faire est de fourrer un process enfant, de faire la redirection dans l'enfant uniquement (les descripteurs de files parents ne sont pas affectés) puis d'exécuter la command le parent attend juste l'enfant).
Pour les commands embeddedes (ou commands composées, ou fonctions …), il n'y a ni fork ni exec. Cependant, après la fin d'une command embeddede redirigée, les descripteurs de files reviennent à leur état antérieur.
Pour ce faire, le shell enregistre juste une copy du descripteur de file redirigé vers un autre descripteur de file avant d'effectuer la redirection, marque ce descripteur de file avec l'indicateur O_CLOEXEC (dans le cas où le builtin finit par exécuter une command comme eval
ou command
) lorsque le builtin returnne, le shell restaure le descripteur de file.
Vous pouvez voir que si vous exécutez par exemple:
strace sh -c 'echo test > /dev/null; :'
Vous verrez (seules les inputs pertinentes sont incluses):
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
: ouvre le file à redirect vers. fcntl(1, F_DUPFD, 10) = 10
: duplique le stdout original au premier fd> = 10 (ici 10) disponible. fcntl(10, F_SETFD, FD_CLOEXEC) = 0
: définissez le drapeau O_CLOEXEC dessus dup2(3, 1) = 1
: rend le file redirigé stdout close(3) = 0
: n'est plus nécessaire write(1, "test\n", 5) = 5
: echo s'exécute et écrit "test \ n" sur son stdout (maintenant redirigé vers / dev / null). dup2(10, 1) = 1
: restore stdout close(10) = 0
: fermer fd 10 n'est plus nécessaire. Notez que dans le shell Bourne, redirect une command composée a provoqué une fourchette (comme dans a=0; { a=1; echo "$a"; } >&2; echo "$a"
donnerait 1
puis 0
). Pour contourner cela, vous avez effectivement dû faire ce qui précède à la main:
Au lieu de
while cmd1; do cmd2; i=`expr "$i" + 1`; done > file
Tu devais faire:
exec 3>&1 > file while cmd1 3>&-; do cmd2 3>&-; i=`expr "$i" + 1 3>&-`; done exec >&3 3>&-
(avec un 3>&-
pour chaque command car ce fd n'a pas le drapeau O_CLOEXEC).
Et dans les premières versions du shell Bourne, vous ne pouviez pas redirect les builtins. Sur un Unix V7 sur un pdp11 émulé:
$ eval a=1 > /tmp/x illegal io $ read a < /etc/passwd illegal io
Dès que la command est terminée, les files d'input sont fermés, ce qui permet leur écriture par d'autres process, le descripteur de file est libéré et le process fils est terminé.