
Suponha que você execute um comando que leva algum tempo para retornar e deseja executar um comando diferente depois de executado, mas não planejou isso com antecedência.
Eu sei que existe a opção de pressionar Ctrl + Ze enviar fg && otherCommand
. No entanto, isso tem duas falhas principais:
- Não funciona se o primeiro comando for uma composição de comandos diferentes (
command1 && command2
oucommand1; command2
) porque os comandos subsequentes da primeira linha enviada não serão executados. - A execução do primeiro comando é interrompida enquanto você digita o próximo comando. Com esses comandos desagradáveis de 30 segundos, o tempo que você gasta digitando o próximo comando representa uma boa parte do tempo de execução restante, se não todo.
Eu também sei que você pode simplesmente digitar o próximo comando enquanto um comando está sendo executado e clicar Enterpara executá-lo. No entanto, isso também tem duas falhas principais:
- Não funciona se o comando que você executa primeiro lê
stdin
. - Se o comando executado primeiro produzir uma saída, você não poderá ver o que digitou.
Existe uma maneira rápida de enfileirar mais comandos enquanto um comando está sendo executado, possivelmente envolvendo o uso de um emulador de terminal especial ou de vários terminais?
Responder1
Pressione Ctrl+ Ze execute imediatamente bg
. Isso faz com que o comando atual continue sendo executado em segundo plano. Então você pode usar fg && otherCommand
para agendar otherCommand
após o atual.
Para facilitar isso, configurei Ctrl+ Zno meu shell para executarbg
quando pressiono-o em uma linha de comando vazia. VerNo zsh, como posso rejeitar mais rapidamente o processo em primeiro plano?eComo você envia aplicativos de linha de comando diretamente para segundo plano?; Não verifiquei se as versões modernas do bash facilitam fazer o mesmo.
Responder2
Você pode criar um pipe nomeado (isso precisa ser feito uma vez):
mkfifo ~/myfifo
Então, a partir de um terminal (vamos chamá-lo de terminal A), você pode dizer:
exec 10< ~/myfifo
Para atribuir a extremidade de leitura do pipe ao descritor de arquivo 10, você pode usar qualquer outro número acima de 2 (para que a entrada, saída e erro padrão permaneçam disponíveis se outro comando precisar).
Então, de outro terminal (vamos chamá-lo de terminal B), você pode dizer:
cat - > ~/myfifo
Para completar a conexão ao terminal A, que então retorna o prompt. Este comando grava o que você insere da entrada padrão no pipe. Então você pode inserir o seguinte no terminal A:
while read -u10 -r LINE; do eval "$LINE"; done
Portanto, ele executará os comandos digitados no terminal B. O read
comando lerá as linhas do descritor de arquivo 10 e executará com eval
. eval
permite que você execute comandos shell, como exportar variáveis.
Enquanto o terminal A estiver aberto, você poderá interromper o loop com Ctrl + C para poder inserir comandos novamente e, posteriormente, reiniciar o loop para começar a executar os comandos restantes na fila.
Os comandos exec e while podem ser colocados em um shellscript para que você possa usar Ctrl-Z fg && yourscript
para ativar o modo pipe caso tenha esquecido de fazê-lo no início.
Responder3
Você provavelmente deseja:
wait $pid
Se você não estiver executando no mesmo shell, não poderá usar um integrado e precisará de uma solução alternativa. Veja a discussãoaqui.
Responder4
EDITAR:Interpretei mal a pergunta, mas a técnica abaixo ainda pode ser útil para as pessoas ao executar comandos em um script bash (para que tenham um único PID)
Isto é o que eu uso (no Linux), quando o comando1 está imprimindo uma saída útil e eu só quero iniciar outro processo em outro shell assim que terminar (ou seja, não quero colocar o comando1 em segundo plano):
tail --pid=$command1_pid -f /dev/null; command2
onde $command1_pid
está o PID do processo que você está esperando terminar
(Acho que originalmente encontrei aqui:https://stackoverflow.com/a/41613532/1676393. Veja lá para outros detalhes úteis. Como uma versão que funcionará no Darwin (macOS))
Passo a passo:
- pare o comando1 com Ctrl+Z
- run
ps
, procure o processo correspondente ao comando1 e encontre seu PID - em seguida, reinicie o processo de command1 digitando
fg
e, em um novo shell, execute o comando acima
Assim, o comando2 iniciará no novo shell quando o comando1 for executado no shell antigo.