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/Noù N 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