![Como executar um comando após a conclusão de um já existente?](https://rvso.com/image/1289035/Como%20executar%20um%20comando%20ap%C3%B3s%20a%20conclus%C3%A3o%20de%20um%20j%C3%A1%20existente%3F.png)
Se eu iniciar um script que vai demorar muito, inevitavelmente percebo isso depois de iniciá-lo e gostaria de ter uma maneira de fazer algum tipo de alerta quando ele terminar.
Então, por exemplo, se eu executar:
really_long_script.sh
e pressione Enter... como posso executar outro comando quando terminar?
Responder1
Você pode separar vários comandos por ;
, para que sejam executados sequencialmente, por exemplo:
really_long_script.sh ; echo Finished
Se você deseja executar o próximo programa somente se o script terminar com o código de retorno 0 (o que geralmente significa que foi executado corretamente), então:
really_long_script.sh && echo OK
Se você quiser o oposto (ou seja, continuar apenas se o comando atual falhar), então:
really_long_script.sh || echo FAILED
Você poderia executar seu script em segundo plano (mas cuidado, a saída dos scripts ( stdout
e stderr
) continuaria indo para o seu terminal, a menos que você o redirecionasse para algum lugar) e, em seguida wait
:
really_long_script.sh &
dosomethingelse
wait; echo Finished
Se você já executou o script, poderá suspendê-lo com Ctrl-Z
e executar algo como:
fg ; echo Finished
Onde fg
traz o processo suspenso para o primeiro plano ( bg
faria com que ele fosse executado em segundo plano, da mesma forma que começou &
)
Responder2
Se o processo não for executado no tty atual, tente isto:
watch -g ps -opid -p <pid>; mycommand
Responder3
Você também pode usar o controle de trabalho do bash. Se você começou
$ really_long_script.sh
então pressione ctrl+z para suspendê-lo:
^Z
[1]+ Stopped really_long_script.sh
$ bg
para reiniciar o trabalho em segundo plano (como se o tivesse iniciado com really_long_script.sh &
). Então você pode esperar por este trabalho em segundo plano com
$ wait N && echo "Successfully completed"
onde N é o ID do trabalho (provavelmente 1 se você não executou nenhum outro trabalho em segundo plano) que também é exibido [1]
acima.
Responder4
Há algum tempo escrevi um script para aguardar o final de outro processo. NOISE_CMD
poderia ser algo como notify-send ...
, desde que DISPLAY
esteja configurado corretamente.
#!/bin/bash
NOISE_CMD="/usr/bin/mplayer -really-quiet $HOME/sfx/alarm-clock.mp3"
function usage() {
echo "Usage: $(basename "$0") [ PROCESS_NAME [ PGREP_ARGS... ] ]"
echo "Helpful arguments to pgrep are: -f -n -o -x"
}
if [ "$#" -gt 0 ] ; then
PATTERN="$1"
shift
PIDS="$(pgrep "$PATTERN" "$@")"
if [ -z "$PIDS" ] ; then
echo "No process matching pattern \"$PATTERN\" found."
exit
fi
echo "Waiting for:"
pgrep -l "$PATTERN" "$@"
for PID in $PIDS ; do
while [ -d "/proc/$PID" ] ; do
sleep 1
done
done
fi
exec $NOISE_CMD
Sem qualquer argumento, apenas faça barulho imediatamente. Esse comportamento permite algo assim por conveniência (digamos que você chame o script abaixo alarm.sh
):
apt-get upgrade ; ~/bin/alarm.sh
É claro que você pode fazer muitas coisas engraçadas com esse script, como deixar uma instância de alarm.sh
wait por uma instância de alarm.sh
, que está aguardando algum outro comando. Ou executar um comando logo após a conclusão de alguma tarefa de outro usuário logado... >:D
Uma versão anterior do script acima pode ser interessante, se você quiser evitar uma dependência pgrep
e aceitar pesquisar IDs de processos por conta própria:
#!/bin/bash
if [ "$#" -lt 2 -o ! -d "/proc/$1" ] ; then
echo "Usage: $(basename "$0") PID COMMAND [ ARGUMENTS... ]"
exit
fi
while [ -d "/proc/$1" ] ; do
sleep 1
done
shift
exec "$@"
Um pouco fora do assunto, mas útil em situações semelhantes: alguém pode estar interessado emreptyr
, uma ferramenta que "rouba" um processo de algum shell (pai) e o executa a partir do shell atual. Eu tentei implementações semelhantes e reptyr
são as mais bonitas e confiáveis para meus propósitos.