Para ler do descritor de arquivo 6 eu posso usar <&6
ou </dev/fd/6
(aka /proc/self/fd/6
). Geralmente ambos funcionam igualmente bem. No entanto, se esse descritor de arquivo for um soquete, coisas estranhas acontecem. Por exemplo:
$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address
Aqui ls
mostra que o descritor está realmente presente. Mas acessar os dados não é possível dessa maneira. Se eu usar, cat <&6
tudo funcionará bem novamente.
Qual é a diferença entre as duas maneiras de acessar o descritor de arquivo?
Existe uma boa maneira de acessar um descritor se o número for fornecido em uma variável? ( </dev/fd/$fd
funcionaria, mas <&$fd
não funciona.)
(A situação acima pode ser observada no linux, mas não no OpenBSD. - Parece que o descritor de arquivo é um dispositivo de caractere comum lá.)
linux
bash
socket
file-descriptors
michas
fonte
fonte
Respostas:
É assim porque a leitura de
/dev/fd/
entradas que representam soquetes não é implementada no Linux. Você pode encontrar uma boa descrição sobre o raciocínio aqui. Você pode acessarstat
o link e é por isso que o vêls
, mas o acesso é deliberadamente proibido.Agora, para a segunda parte - por que
bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345
funciona? Isso ocorre porque o socket é lido usando a API socket / file, não o/proc
sistema de arquivos. Isto é o que eu observei acontecendo:bash
A instância em execução no seu terminal cria um soquete com o fd 6.bash
corre e ligadup2(6, 0)
, a fim de conectar seu soquete comocat
'sstdin
.dup2
chamada não falhar, o gato lêstdin
.Você pode reproduzir e observar com:
Se você está se perguntando por que o
bash
processo filho tem acesso aos descritores fd 6 - filefork
, e se eles não estão marcados para fecharexec
, eles também não são fechados.fonte
Para responder sua pergunta direta, " qual é a diferença ?":
Quando você redireciona
<&6
, o shell usa umadup2()
chamada do sistema para duplicar o descritor de arquivo. Quando você (tenta) redirecionar</dev/fd/6
, ele usaráopen()
.O kernel não suporta
open()
soquetes/dev/fd
; eles estão presentes no diretório apenas para informações dedecoração.fonte