O que faz `<& -`?

20

Copiei um trecho de Bash para segundo plano um comando ssh executado remotamente:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

O que <&-faz?
Meu palpite é que é o mesmo que< /dev/null

Minha próxima entendimento é que os três principais descritores de arquivos ( stdin, stdout, stderr) precisam ser fechados para evitar:

  1. O trabalho que está sendo realizado em segundo plano e o script saindo - conflitante de alguma forma?
  2. Quando o terminal é fechado, todos os processos que estão aceitando stdin do terminal são fechados?
Eric Francis
fonte
Referência cruzada obrigatória: consulte Quais são os operadores de controle e redirecionamento do shell? - apesar de tudo o que diz sobre esse operador é que "pode ​​ser usado para fechar ou duplicar descritores de arquivos" e você deve "ver a seção relevante do manual do seu shell".
G-Man diz 'Reinstate Monica'
Se bem me lembro, ssh -nNT user@remote 'command'criará uma sessão SSH não interativa. Acrescente-o &ao segundo plano, anexe nohup-o commandao para mantê-lo em execução se a sua conexão acabar.
Mark K Cowan
11
O @MarkKCowan man sshsugere que -N desabilite a execução de um comando remoto por completo, e um teste rápido suporta isso.
Tom Hunt
Ah, sim, usei -nNTR para encaminhamento de porta reversa. Ignore o -N e -R então :)
Mark K Cowan

Respostas:

30

<&-não é exatamente a mesma coisa que < /dev/null. <&-fecha fd 0, enquanto o < /dev/nullredireciona do dispositivo /dev/null, que nunca fornece dados e sempre fornece EOF na leitura. A diferença é principalmente que uma read(2)chamada de um FD fechado (o <&-caso) apresentará um erro no EBADF, enquanto uma chamada de um FD redirecionado a nulo não retornará bytes lidos (condição de fim de arquivo). Se o seu programa nunca lê a partir de stdin, a distinção não importa.

Fechar os FDs é uma boa prática se você estiver em segundo plano, pois um processo em segundo plano será interrompido se tentar ler algo do TTY. Este exemplo não lida completamente com tudo o que deveria; idealmente, haveria nohupou setsidinvocação em algum lugar para desassociar completamente o processo em segundo plano.

Tom Hunt
fonte
Então eu devo usar nohupalém de fechar os descritores de arquivo?
Eric Francis
2
O método mais completo (que imita a maneira como os programas se daemonizam) é algo parecido setsid some process <&- >path/to/log 2>path/to/error. O método mais rápido é algo parecido nohup some process &.
21715 Tom Tom Hunt
2
@ EricFrancis: Usar nohupnão faz sentido aqui. nohupimpedir que o processo receba HUPsinal quando seu terminal de controle estiver fechado. Mas você não tinha nenhum terminal neste caso.
cuonglm
@ TomHunt: O processo em segundo plano não parou, a sessão ssh ficou.
cuonglm
2
não é uma boa ideia fechar os fds 0, 1 e 2 ... você não deseja que o próximo fd seja criado para assumir um desses valores. melhor redirecioná-los para / dev / null
Murray Jensen
7

Veja man bash:

  [n]<&word

é usado para duplicar descritores de arquivo de entrada. Se for wordexpandido para um ou mais dígitos, o descritor de arquivo indicado por nserá uma cópia desse descritor de arquivo. Se os dígitos em word não especificarem um descritor de arquivo aberto para entrada, ocorrerá um erro de redirecionamento. Se a palavra avaliar -, o descritor de arquivo nserá fechado. Se nnão for especificado, a entrada padrão (descritor de arquivo 0) é usada.

choroba
fonte
A definição correta é que não é especificado o que acontece quando você possui [n]<&worde a palavra contém mais de um único dígito.
schily 17/09/2015
O que você quer dizer? O man bashincorreto?
Eric Francis
O @EricFrancis, por não ser especificado no padrão, bashdecide implementá-lo de maneira sã (para alguma definição adequada de "sã"). Outras conchas podem ou não fazê-lo.
muru 17/09/2015
@ muru A questão está marcada bash, não posix-shell.
Barmar 24/09/2015
@Barmar ok. Tão...?
muru
7

<&- feche a entrada padrão.

A forma geral, definida pelo POSIX , é:

[n]<&word

Seu objetivo de criar descritor de arquivo né uma cópia do descritor de arquivo indicado por word. A entrada padrão é assumida se nfor omitida e se wordfor -, o descritor de arquivo nserá fechado.

Não é o mesmo que </dev/null, desde quando, no caso de </dev/null, a entrada padrão ainda estava aberta e foi redirecionada para outro local.

Você precisa fechar todos os descritores de arquivo dos processos anexados ao soquete ssh, caso contrário, a sessão ssh não poderá ser fechada.

Você pode executar o comando na máquina remota sem anexá-lo à sessão ssh, usando screen ou tmux :

ssh user@remote 'screen -S test -d -m command'
cuonglm
fonte
Por que o voto negativo?
cuonglm