Est-ce que 3> & 1 implique 4> & 3 5> & 3 etc.?

31

Je m'attendrais

echo foo | tee /proc/self/fd/{3..6} 3>&1

échouer avec des erreurs comme / proc / self / fd / 4: Aucun fichier ou répertoire, etc., mais à ma grande surprise, il génère

foo
foo
foo
foo
foo

C'est comme si 3>&1tous les descripteurs suivants étaient redirigés vers stdout, sauf que cela ne fonctionne pas si je passe 3à autre chose, comme

$ echo foo | tee /proc/self/fd/{3..6} 4>&1
tee: /proc/self/fd/3: No such file or directory
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo
$ echo foo | tee /proc/self/fd/{4..6} 4>&1
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo

Y a-t-il une explication à ce comportement?

oguz ismail
la source

Réponses:

31

strace montre cette séquence d'appels système:

$ strace -o strace.log tee /proc/self/fd/{3..6} 3>&1
...
$ cat strace.log
...
openat(AT_FDCWD, "/proc/self/fd/3", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
openat(AT_FDCWD, "/proc/self/fd/4", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 5
openat(AT_FDCWD, "/proc/self/fd/5", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 6
openat(AT_FDCWD, "/proc/self/fd/6", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 7
...

La première ligne s'ouvre /proc/self/fd/3et lui assigne le prochain numéro fd disponible, 4. /proc/self/fd/3est un chemin spécial. L' ouvrir a un effet similaire à duper fd 3: fd 4 pointe au même endroit que fd 3, le tty.

La même chose se produit pour chaque openat()appel successif . Lorsque la poussière se dépose, les fds 4, 5, 6 et 7 sont tous des doublons de fd 3.

  • 1 → tty
  • 3 → tty
  • 4 → tty
  • 5 → tty
  • 6 → tty
  • 7 → tty

Notez que la 3>&1redirection n'est pas importante. Ce qui est important, c'est que nous demandons à tee d'ouvrir /proc/self/fd/NN est déjà utilisé. Nous devrions obtenir le même résultat si nous nous en débarrassons 3>&1et prenons le départ à la /proc/self/fd/2place. Voyons voir:

$ echo foo | tee /proc/self/fd/{2..6}
foo
foo
foo
foo
foo
foo

Confirmé! Même résultat.

Nous pouvons également répéter le même nombre fd encore et encore. Nous obtenons le même résultat lorsque nous atteignons fd 6. Au moment où il atteint le dernier, il a ouvert suffisamment de descripteurs pour rendre le saut à 6 possible.

$ echo foo | tee /proc/self/fd/{2,2,2,2,6}
foo
foo
foo
foo
foo
foo
John Kugelman
la source