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/3
et lui assigne le prochain numéro fd disponible, 4. /proc/self/fd/3
est 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>&1
redirection n'est pas importante. Ce qui est important, c'est que nous demandons à tee d'ouvrir /proc/self/fd/N
où N est déjà utilisé. Nous devrions obtenir le même résultat si nous nous en débarrassons 3>&1
et prenons le départ à la /proc/self/fd/2
place. 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