3> & 1 implica 4> & 3 5> & 3 etc.?

31

Eu esperaria

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

falhar com erros como / proc / self / fd / 4: Esse arquivo ou diretório não existe, etc., mas para minha surpresa, ele gera

foo
foo
foo
foo
foo

É como fazer 3>&1com que todos os descritores a seguir sejam redirecionados para stdout, exceto que não funcionará se eu mudar 3para outra coisa, como

$ 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

Existe uma explicação para esse comportamento?

oguz ismail
fonte

Respostas:

31

strace mostra esta sequência de chamadas do 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
...

A primeira linha é aberta /proc/self/fd/3e atribui a ele o próximo número fd disponível, 4. /proc/self/fd/3é um caminho especial. Abri-lo tem um efeito semelhante ao dup ing fd 3: fd 4 pontos no mesmo local que fd 3, o tty.

O mesmo acontece para cada openat()chamada sucessiva . Quando a poeira assenta, os valores 4, 5, 6 e 7 são duplicados do valor 3.

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

Observe que o 3>&1redirecionamento não é importante. O importante é que estamos pedindo para abrir /proc/self/fd/Nonde N já está em uso. Deveríamos obter o mesmo resultado se nos livrarmos 3>&1e começarmos o tee /proc/self/fd/2. Vamos ver:

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

Confirmado! Mesmo resultado.

Também podemos repetir o mesmo número fd repetidamente. Obtemos o mesmo resultado quando atingimos o fd 6. Quando chega ao último, ele abre descritores suficientes para tornar possível o salto para 6.

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