Como executar um comando após a conclusão de um já existente?

Como executar um comando após a conclusão de um já existente?

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 ( stdoute 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-Ze executar algo como:

fg ; echo Finished

Onde fgtraz o processo suspenso para o primeiro plano ( bgfaria 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_CMDpoderia ser algo como notify-send ..., desde que DISPLAYesteja 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.shwait 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 pgrepe 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 reptyrsão as mais bonitas e confiáveis ​​para meus propósitos.

informação relacionada