Como executar um comando depois que um já existente, existente, terminar?

27

Se eu começar um script que levará muito tempo, eu inevitavelmente perceberei isso depois de começar o roteiro, e gostaria de ter um jeito de fazer algum tipo de alerta quando terminar.

Então, por exemplo, se eu correr:

really_long_script.sh

e pressione enter ... como posso executar outro comando assim que terminar?

    
por mlissner 11.09.2011 / 07:53

5 respostas

37

Você pode separar vários comandos por ; , então eles são 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, continue somente se o comando atual tiver falhado), do que:

really_long_script.sh || echo FAILED

Você pode executar seu script em segundo plano (mas cuidado, a saída de scripts ( stdout e stderr ) continuará indo para o terminal, a menos que você o redirecione para algum lugar) e wait para ele:

really_long_script.sh &
dosomethingelse
wait; echo Finished

Se você já executou o script, poderá suspendê-lo com Ctrl-Z e, em seguida, executar algo como:

fg ; echo Finished

Em que fg coloca o processo suspenso em primeiro plano ( bg o executaria em segundo plano, praticamente como iniciado com & )

    
por 11.09.2011 / 08:16
9

Você também pode usar o controle de trabalho do bash. Se você começou

$ really_long_script.sh

pressione ctrl + z para suspendê-lo:

^Z
[1]+  Stopped                 really_long_script.sh
$ bg

para reiniciar o trabalho em segundo plano (como se tivesse começado com really_long_script.sh & ). Então você pode esperar por este trabalho em segundo plano com

$ wait N && echo "Successfully completed"

em que N é o ID do trabalho (provavelmente 1 se você não executou nenhum outro trabalho em segundo plano), que também é exibido como [1] acima.

    
por 11.09.2011 / 11:47
7

Se o processo não for executado no tty atual, outra opção seria:

watch -g ps -opid -p <pid>; mycommand
    
por 08.02.2016 / 16:24
1

Acontece que isso não é tão difícil: você pode simplesmente digitar o próximo comando na janela enquanto o existente é executado, pressionar enter e quando o primeiro terminar, o segundo comando será executado automaticamente.

Eu estou supondo que existem maneiras mais elegantes, mas isso parece funcionar.

Editando para adicionar isso, se você deseja executar um alerta após o término do comando, você pode criar esses aliases em .bashrc e, em seguida, executar alert enquanto estiver em execução:

 alias alert_helper='history|tail -n1|sed -e "s/^\s*[0-9]\+\s*//" -e "s/;\s*alert$//"'
 alias alert='notify-send -i gnome-terminal "Finished Terminal Job" "[$?] $(alert_helper)"'
    
por 11.09.2011 / 07:54
1

Há algum tempo, escrevi um script para aguardar o final de outro processo. NOISE_CMD poderia ser algo como notify-send ... , dado que DISPLAY está definido 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 nenhum argumento, apenas faça algum ruído imediatamente. Esse comportamento permite algo assim por conveniência (digamos que você chame o script abaixo de 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 aguardar uma instância de alarm.sh , que está aguardando outro comando. Ou executar um comando logo após a conclusão de alguma tarefa de outro usuário conectado ... >: D

Uma versão anterior do script acima pode ser interessante, se você quiser evitar uma dependência em pgrep e aceitar a identificação de processos de pesquisa:

#!/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 "$@"

Ligeiramente fora do assunto, mas útil em situações semelhantes: Alguém pode estar interessado em reptyr , uma ferramenta que "rouba "um processo de algum shell (pai) e o executa do shell atual. Eu tentei implementações semelhantes e reptyr é o mais bonito e confiável para os meus propósitos.

    
por 29.06.2014 / 20:27