web-dev-qa-db-fra.com

Bug de redirection de fichier Bash?

D'après ce que je comprends du programme IO, il y a stdin, stdout et stderr flux de données (et un code de retour). stdout et stderr sont les deux flux de sortie de données. Donc, si j'utilise la redirection bash pour fermer l'un des flux de sortie, je peux déterminer le flux vers lequel le texte est envoyé. Droite?

J'utilise Ubuntu 18.04.1 LTS et je rencontre un problème étrange avec la redirection bash.

Laissez-moi vous expliquer l'exemple. Voici ma commande:

# apt-cache show php5
N: Can't select versions from package 'php5' as it is purely virtual
N: No packages found
# |

Le paquetage php5 n'existe pas sous Ubuntu 18.04, donc apt-cache affiche une erreur. Je suppose que ce texte est envoyé au flux stderr, alors j'ai essayé de fermer ce flux:

# apt-cache show php5 2>&-
# |

Il semble que cela vérifie que le texte a été envoyé via stderr. Tout va bien jusqu'à présent! Mais maintenant, pour vérifier son intégrité, j'ai essayé de fermer stdout (je devrais voir le texte de l'erreur maintenant):

# apt-cache show php5 1>&-
# |

Quoi!? J'ai redirigé stdout cette fois, mais stderr n'apparaît pas non plus?

Selon Internet, les descripteurs de fichier sont corrects: https://www.gnu.org/software/bash/manual/html_node/Redirections.html

Je ne peux pas comprendre ce qui pourrait se passer ici.

Capture d'écran:

Bash redirect bug

3
Bradley Odell

TL; DR: Ce n'est pas bash, c'est apt-cache qui dérange avec les descripteurs de fichiers.

apt-cache fait quelque chose de très intéressant - il a tendance à pas écrire des lignes commençant par N: caractères destinés à stdout.

Considère ceci:

$ apt-cache show nonexistent
N: Unable to locate package nonexistent
E: No packages found

Nous voyons deux lignes, une commençant par N: une commençant par E:. N: les lignes vont à stdout. Dans votre exemple, vous avez deux lignes N:.

# apt-cache show php5
N: Can't select versions from package 'php5' as it is purely virtual
N: No packages found

Si vous suivez les appels système via strace -e write -f bash -c 'apt-cache show randomtext >&-', vous verrez que l'écriture de lignes E: se produit, mais que les lignes N n'y sont pas:

[pid 12450] write(2, "E", 1E)            = 1
[pid 12450] write(2, ": ", 2: )           = 2
[pid 12450] write(2, "No packages found", 17No packages found) = 17
[pid 12450] write(2, "\n", 1
)           = 1
[pid 12450] +++ exited with 100 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12450, si_uid=1000, si_status=100, si_utime=5, si_stime=2} ---
+++ exited with 100 +++

Donc, apt-cache est suffisamment intelligent pour vérifier la sortie standard redirigée. Mais qu'en est-il de stderr? Apparemment, les écritures sont toujours là: si vous faites strace -e write,openat,dup2 -f bash -c 'apt-cache show randomtext 2>&-, vous verrez que apt-cache ouvre /dev/null pour qu'il reste encore quelque chose pour stderr:

[pid 12543] openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 2
....
[pid 12543] write(2, "N", 1)            = 1
[pid 12543] write(2, ": ", 2)           = 2
[pid 12543] write(2, "Unable to locate package randomt"..., 35) = 35
[pid 12543] write(2, "\n", 1)           = 1
[pid 12543] write(2, "E", 1)            = 1
[pid 12543] write(2, ": ", 2)           = 2
[pid 12543] write(2, "No packages found", 17) = 17
[pid 12543] write(2, "\n", 1)           = 1
[pid 12543] +++ exited with 100 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12543, si_uid=1000, si_status=100, si_utime=5, si_stime=3} ---
+++ exited with 100 +++

Si vous effectuez la même chose avec d'autres programmes dans bash, cela fonctionne comme prévu:

# stdout closed, stderr not
$ ls -l /proc/self/fd >&-
ls: write error: Bad file descriptor
# stdout open , stderr closed, and it's number is assigned to whatever command is trying to open - in this case /proc/self/fd directory
$ ls -l /proc/self/fd 2>&-
total 0
lrwx------ 1 xie xie 64 Oct  6 11:32 0 -> /dev/pts/1
lrwx------ 1 xie xie 64 Oct  6 11:32 1 -> /dev/pts/1
lr-x------ 1 xie xie 64 Oct  6 11:32 2 -> /proc/12723/fd
3