Ontem li este comentário do SO, que diz que no shell (pelo menos bash
) >&-
"tem o mesmo resultado que" >/dev/null
.
Na verdade, esse comentário se refere ao guia do ABS como a fonte de suas informações. Mas essa fonte diz que a >&-
sintaxe "fecha os descritores de arquivo".
Não está claro para mim se as duas ações de fechar um descritor de arquivo e redirecioná-lo para o dispositivo nulo são totalmente equivalentes. Então, minha pergunta é: eles são?
Parece que fechar um descritor é como fechar uma porta, mas redirecioná-lo para um dispositivo nulo está abrindo uma porta para o limbo! Os dois não me parecem exatamente iguais, porque se eu vir uma porta fechada, não tentarei jogar nada, mas se vir uma porta aberta, assumirei que posso.
Em outras palavras, sempre me perguntei se >/dev/null
meios que cat mybigfile >/dev/null
realmente processariam cada byte do arquivo e o gravariam no /dev/null
esquecimento. Por outro lado, se o shell encontrar um descritor de arquivo fechado, costumo pensar (mas não tenho certeza) que ele simplesmente não escreverá nada, embora a questão permaneça se cat
ainda será lido todos os bytes.
Este comentário diz >&-
e >/dev/null
" deveria " ser o mesmo, mas não é uma resposta tão retumbante para mim. Gostaria de ter uma resposta mais autorizada com alguma referência ao núcleo padrão ou de origem ou não ...
fonte
Respostas:
Não, você certamente não deseja fechar os descritores de arquivo 0, 1 e 2.
Se você fizer isso, na primeira vez em que o aplicativo abrir um arquivo, ele se tornará stdin / stdout / stderr ...
Por exemplo, se você fizer:
Quando
tee
(pelo menos algumas implementações, como o busybox ') abrir o arquivo para gravação, ele será aberto no descritor de arquivo 1 (stdout). Entãotee
, escreveremostext
duas vezes emfile
:Sabe-se que isso causa vulnerabilidades de segurança. Por exemplo:
E
chsh
(um aplicativo setuid) pode acabar escrevendo mensagens de erro no/etc/passwd
.Algumas ferramentas e até algumas bibliotecas tentam se proteger contra isso. Por exemplo, o GNU
tee
moverá o descritor de arquivo para um acima de 2 se os arquivos que ele abrir para gravação forem atribuídos a 0, 1, 2 enquanto o busyboxtee
não.A maioria das ferramentas, se não puderem gravar no stdout (porque, por exemplo, não está aberto), reportará uma mensagem de erro no stderr (no idioma do usuário, o que significa processamento extra para abrir e analisar arquivos de localização ...), portanto será significativamente menos eficiente e possivelmente causará falha no programa.
De qualquer forma, não será mais eficiente. O programa ainda fará uma
write()
chamada do sistema. Só pode ser mais eficiente se o programa deixar de gravar em stdout / stderr após a primeirawrite()
chamada do sistema com falha , mas os programas geralmente não fazem isso. Eles geralmente saem com um erro ou continuam tentando.fonte
Não é uma resposta completa para sua pergunta, mas sim, o que foi dito acima é como funciona.
cat
lê o (s) arquivo (s) nomeado (s) ou a entrada padrão, se nenhum arquivo for nomeado, e envia para seu padrão a saída do conteúdo deles até encontrar um EOF no último arquivo nomeado (incluindo entrada padrão). Esse é o seu trabalho.Ao adicionar,
>/dev/null
você está redirecionando a saída padrão para / dev / null. Esse é um arquivo especial (um nó do dispositivo) que joga fora qualquer coisa escrita nele (e retorna imediatamente o EOF na leitura). Observe que o redirecionamento de E / S é um recurso fornecido pelo shell, não por cada aplicativo individual, e que não há nada mágico no nome / dev / null, apenas o que existe lá na maioria dos sistemas semelhantes ao Unix .Também é importante observar que a mecânica específica dos nós dos dispositivos varia de sistema operacional para sistema operacional, mas cat (que em um sistema GNU significa coreutils) é multiplataforma (o mesmo código-fonte precisa ser executado pelo menos no Linux e Hurd) e, portanto, não pode levar dependências para kernels específicos do sistema operacional. Além disso, ele ainda funciona se você criar um alias / dev / null (no Linux, isso significa um nó de dispositivo com o mesmo número de dispositivo principal / secundário) com outro nome. E sempre há o caso de escrever em outro lugar que se comporte efetivamente da mesma forma (digamos, / dev / zero).
Segue-se que
cat
não tem conhecimento das propriedades especiais de / dev / null e, de fato, provavelmente não tem conhecimento do redirecionamento, mas ainda precisa executar exatamente o mesmo trabalho: lê os arquivos nomeados e gera o conteúdo de o (s) arquivo (s) para sua saída padrão.cat
Acontece que o resultado padrão de ir para o vazio não é algo emcat
si.fonte
cat mybigfile > /dev/null
fará comcat
que cada byte seja lidobigfile
na memória. E, para todos osn
bytes, ele chamaráwrite(1, buffer, n)
. Sem o conhecimento docat
programa, o programawrite
não fará absolutamente nada (exceto, talvez, por alguma contabilidade trivial). Escrever para/dev/null
não requer processamento de todos os bytes.cat
ou decp
outro funcionariammap
inserindo grandes pedaços do arquivo de origem na memória e depois chamandowrite()
a região mapeada. Se você estivesse escrevendo/dev/null
, awrite()
chamada retornaria imediatamente, sem falhas nas páginas do arquivo de origem, para que nunca fosse realmente lida no disco.cat
é executado em muitas plataformas, mas uma olhada casual no código-fonte mostrará muitos#ifdef
s: não é literalmente o mesmo código que é executado em todas as plataformas, e há muitas seções dependentes do sistema.