strace
mostra questa sequenza di chiamate di sistema:
$ 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 prima riga si apre /proc/self/fd/3
e le assegna il successivo numero fd disponibile, 4. /proc/self/fd/3
è un percorso speciale. L'apertura ha un effetto simile al duping di fd 3: fd 4 punta nello stesso posto di fd 3, il tty.
La stessa cosa accade per ogni openat()
chiamata successiva . Quando la polvere si deposita, fds 4, 5, 6 e 7 sono tutti duplicati di fd 3.
- 1 → tty
- 3 → tty
- 4 → tty
- 5 → tty
- 6 → tty
- 7 → tty
Si noti che il 3>&1
reindirizzamento non è importante. L'importante è che stiamo chiedendo a T di aprirsi /proc/self/fd/N
dove N è già in uso. Dovremmo ottenere lo stesso risultato se ci sbarazziamo di 3>&1
e iniziamo /proc/self/fd/2
invece a iniziare . Vediamo:
$ echo foo | tee /proc/self/fd/{2..6}
foo
foo
foo
foo
foo
foo
Confermato! Stesso risultato
Possiamo anche ripetere lo stesso numero fd più volte. Otteniamo lo stesso risultato quando premiamo fd 6. Quando raggiunge l'ultimo ha aperto abbastanza descrittori per rendere possibile il salto a 6.
$ echo foo | tee /proc/self/fd/{2,2,2,2,6}
foo
foo
foo
foo
foo
foo