É assim porque a leitura de /dev/fd/
entries que representa sockets não é implementada no Linux. Você pode encontrar um bom artigo sobre raciocínio aqui . Assim, você pode chamar stat
no link e é por isso que o vê com ls
, mas o acesso é deliberadamente proibido.
Agora, para a segunda parte - por que o bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345
funciona? Isso é porque o soquete é lido usando a API de soquete / arquivo, não /proc
filesystem. Isso é o que eu observei acontecer:
-
A instância
bash
em execução no seu terminal cria um soquete com o fd 6. - Criança
bash
é executada e chamadup2(6, 0)
para anexar seu soquete comocat
'stdin
. - Se a
dup2
call não falhar, o cat lê destdin
.
Você pode reproduzir e observar com:
netcat -lp 12345 # in another terminal session (GNU netcat)
strace -f -e trace=open,read,write,dup2 bash -c 'ls -l /dev/fd/6; cat <&6' \
6</dev/tcp/localhost/12345
Se você está se perguntando por que o processo filho bash
tem acesso ao fd 6 - os descritores de arquivo sobrevivem fork
e se eles não estiverem marcados para fechar em exec
, eles também não serão fechados lá.