Por que alguns comandos 'paralisam' o terminal até que eles terminem?

22

Às vezes, você executa um programa no terminal, digamos, lxpanel . O terminal não o levará de volta ao prompt, ele travará. Você pode pressionar Ctrl+ Cpara voltar ao prompt, mas isso mata lxpanel. No entanto, pressionar Alt+ F2(que abre uma janela para executar um comando) e a execução lxpanelfunciona normalmente.

Por que é isso? O que há de diferente entre executar um comando no terminal e na janela 'executar' que aparece quando você pressiona Alt+ F2?

O lxpanel aqui foi usado apenas como exemplo. Eu experimentei isso com vários programas

sqram
fonte
1
Dica: O GNU Screen ( screen) pode, entre outras coisas, ser usado para "encapsular" processos de execução mais longa. Você pode se desconectar dele, voltar ao shell, reconectar e ver a saída do processo em execução. O reencadeamento pode até ser feito em outro terminal, SSH etc. Também pode haver outros programas que permitem fazer esse tipo de coisa.
28611 poplitea

Respostas:

28

Por padrão, o terminal executará o programa em primeiro plano, para que você não volte ao shell até que o programa termine. Isso é útil para programas que lêem stdin e / ou gravam no stdout - geralmente você não deseja que muitos deles sejam executados ao mesmo tempo. Se você deseja que um programa seja executado em segundo plano, você pode iniciá-lo assim:

$ lxpanel &

Ou, se já estiver em execução, você pode suspendê-lo com Ctrl+ Ze, em seguida, executar bgpara movê-lo para o segundo plano. De qualquer forma, você terminará com um novo prompt de shell, mas o programa ainda está em execução e sua saída aparecerá no terminal (para que possa aparecer subitamente enquanto você digita)

Alguns programas (normalmente daemons) irão bifurcar um processo separado quando iniciarem e, em seguida, deixarão o processo principal imediatamente. Isso permite que o programa continue funcionando sem bloquear seu shell

Michael Mrozek
fonte
Então, o que o sistema está realmente fazendo quando você executa o programa pela janela 'run' pressionando Alt + f2? (pelo menos no gnome e no openbox, alt + f2 faz isso). Eu pergunto, porque assim que você digita o comando, o programa inicia e a caixa desaparece. é apenas adicionar um & para ele?
Sql
2
@lyrae: por padrão, o shell aguarda a conclusão do programa antes de continuar a sessão do shell, ele não "trava", por qualquer definição de "trava"; alt + f2 não espera pelo programa. O motivo pelo qual o shell aguarda a conclusão do programa é porque ele pode redirecionar o que o usuário digitou no shell para a entrada padrão do programa e / ou exibir a saída padrão do programa. Como alt + f2 é usado principalmente para iniciar um programa GUI, alt + f2 não oferece a possibilidade de usar entrada / saída padrão e, portanto, não precisa esperar.
Página Inicial>
1
@lyrae: alt + f2 não faz nada de especial para iniciar o programa em segundo plano; é o shell que está fazendo algo especial, adicionando '&' é a funcionalidade do shell. Ao iniciar um comando sem um '&', o shell redireciona a entrada padrão do programa para sua própria entrada padrão e a saída padrão do programa para sua própria saída padrão (um pouco artificial, pois o shell também fornece muitos outros serviços, como a interceptação de Ctrl -C, para enviar um comando de sinal SIGINT ao programa em primeiro plano). O '&' diz ao shell para não fazer isso e apenas iniciar o programa (também artificial).
Lie Ryan
1
@LieRyan: parte do que você está dizendo que o shell faz é de fato gerenciado pelo driver do terminal do kernel, e "with &" geralmente é mais "especial" do que "sem &", além do que o shell chama wait () [ou waitpid ou equivalente], que não é feito com alt-f2.
Random832
6

Quando você inicia um programa em um terminal, o terminal "trava" até que o programa pare. Pressionando Ctrl+, cvocê fecha o programa e volta ao prompt. Você verá isso em todos os aplicativos da GUI, tente o Firefox, por exemplo.

Quando você usa outro método, como Alt + F2 ou clicando nos menus, o programa é iniciado em segundo plano, para que nada de estranho aconteça (e não há nenhum prompt de comando).

Se você ainda deseja iniciar aplicativos GUI a partir do terminal, anexe &no final do seu comando, assim

lxpanel &

Isso instrui o terminal a rodar lxpanelem segundo plano e fornece outro prompt imediatamente.

phunehehe
fonte
3

Os programas são executados por meio de um shell, em primeiro plano, por padrão. Isso faz com que o shell suspenda a operação e direcione stdin / stdout / sterr do terminal para o programa. Os programas executados no ambiente de área de trabalho são bifurcados , o que faz com que sejam executados independentemente do programa que os executou. Isso pode ser simulado na maioria dos shells anexando &a ao comando, embora isso ainda conecte std * ao terminal (embora a leitura de stdin em um programa em segundo plano tenha complicações adicionais).

Ignacio Vazquez-Abrams
fonte
2

O & background bem, exceto os programas que retornam exigindo interação do console mais tarde (por exemplo, uma "atualização do apt-y" que eventualmente entra no estado STOP, pois deseja solicitar ao usuário uma pergunta "realmente forçar mesmo?" Muito mais tarde .... quando ninguém mais está assistindo).

Para tapar esse buraco e informar o processo que um terminal realmente nunca ficará disponível, anexo <& - a alguns dos meus comandos, desconectando-os completamente do terminal ativo, informando que o STDIN não é mais possível. Certifique-se de que / bin / bash é seu shell, se você o usar. O script continuará registrando quaisquer erros relacionados a nenhum pseudoterminal disponível para lançar qualquer prompt.

Por exemplo:

`./runme.sh &> runme.log <&- & disown`

é minha melhor maneira de me desassociar da atual sessão do terminal. STDOUT e STDERR são registrados no runme.log, não importa se o console ou o shell são encerrados mais cedo ou se você faz logout / su em uma conta diferente (sem lixo de terminal do runme) e agradece por negar até o pai-filho O relacionamento PID é removido.

UPDATE: mesmo com isso, tive problemas com um semáforo associando-o ao nome do pai original, então agora eu recomendo:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Obviamente, remova o &> se desejar receber a saída do CRON por email ou redirecione tudo para / dev / null em vez de um arquivo.

Marcos
fonte
Uma maneira um pouco menos complicada de conseguir que comecei a usar éat now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Marcos