it-swarm-pt.tech

Como suprimir a mensagem terminada após matar no bash?

Como você pode suprimir a mensagem Terminated que aparece depois que você mata um processo em um script bash?

Eu tentei set +bm, mas isso não funciona.

Sei que outra solução envolve chamar exec 2> /dev/null, mas isso é confiável? Como faço para redefini-lo novamente para que eu possa continuar vendo o stderr?

51
user14437

A resposta curta é que você não pode. O Bash sempre imprime o status dos trabalhos em primeiro plano. O sinalizador de monitoramento se aplica apenas a trabalhos em segundo plano e apenas a shells interativos, não a scripts.

consulte notify_of_job_status () em jobs.c.

Como você diz, você pode redirecionar para que o erro padrão aponte para/dev/null, mas você perde outras mensagens de erro. Você pode torná-lo temporário, fazendo o redirecionamento em uma subshell que executa o script. Isso deixa o ambiente original em paz.

(script 2> /dev/null)

que perderá todas as mensagens de erro, mas apenas desse script, e não de qualquer outra coisa executada nesse Shell.

Você pode salvar e restaurar o erro padrão redirecionando um novo editor de arquivos para apontar para lá:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

Mas eu não recomendaria isso - a única vantagem da primeira é que ela salva uma invocação sub-Shell, sendo mais complicada e, possivelmente até alterando o comportamento do script, se o script altera os descritores de arquivo.


EDIT:

Para obter uma resposta mais apropriada, verifique a resposta dada por Mark Edgar

16
wnoise

Para silenciar a mensagem, você deve redirecionar stderr no momento em que a mensagem é gerada . Como o comando kill envia um sinal e não espera o processo de destino responder, redirecionando stderr do comando kill Boa. O bash builtin wait foi criado especificamente para esse fim.

Aqui está um exemplo muito simples que mata o comando em segundo plano mais recente. ( Saiba mais sobre $! Aqui. )

kill $!
wait $! 2>/dev/null

Como ambos kill e wait aceitam vários pids, você também pode executar abates em lotes. Aqui está um exemplo que mata todos os processos em segundo plano (do processo/script atual, é claro).

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

Eu fui conduzido aqui a partir de bash: silenciosamente, mata o processo da função em segundo plano .

121
Mark Edgar

Inspirado em resposta de MarcH . Eu estava usando kill -INT como ele sugere com algum sucesso, mas notei que não estava matando alguns processos. Depois de testar alguns outros sinais, vejo que SIGPIPE também matará sem uma mensagem.

kill -PIPE

ou simplesmente

kill -13
16
Steven Penny

Solução: use SIGINT (funciona apenas em shells não interativos)

Demo:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798

8
MarcH

Talvez desanexe o processo do processo atual do Shell chamando disown?

4
Matthias Kestenholz

É isso que todos estamos procurando?

Não desejado:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

Procurado:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

Como você pode ver, nenhuma mensagem de término do trabalho. Funciona para mim também em scripts bash, também para processos em segundo plano mortos.

'set + m' desativa o controle do trabalho (consulte 'conjunto de ajuda') para o Shell atual. Portanto, se você digitar seu comando em uma subshell (como feito aqui entre parênteses), não influenciará as configurações de controle de tarefas do Shell atual. A única desvantagem é que você precisa recuperar o pid do seu processo em segundo plano para o Shell atual, se quiser verificar se ele terminou ou avaliar o código de retorno.

1
Ralph

Isso também funciona para killall (para aqueles que preferem):

killall -s SIGINT (yourprogram) 

suprime a mensagem ... Eu estava executando o mpg123 no modo de plano de fundo. Só poderia ser eliminado silenciosamente enviando um ctrl-c (SIGINT) em vez de um SIGTERM (padrão).

1
Coder of Salvation

Outra maneira de desativar as notificações de trabalho é colocar o comando em segundo plano em um sh -c 'cmd &' construir.

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...

# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5 
kill "${pid}"
'
1
phily

Simples:

{ kill $! } 2>/dev/null

Vantagem? pode usar qualquer sinal

ex:

{ kill -9 $PID } 2>/dev/null
0
user2429558

disown fez exatamente a coisa certa para mim - o exec 3> & 2 é arriscado por várias razões - set + bm não parecia funcionar dentro de um script, apenas no prompt do comando

0
clemep

Eu descobri que colocar o comando kill em uma função e depois a função de segundo plano suprime a saída de terminação

function killCmd() {
    kill $1
}

killCmd $somePID &
0
Al Joslin

Teve sucesso ao adicionar 'jobs 2>&1 >/dev/null 'para o script, não tenho certeza se isso ajudará o script de outra pessoa, mas aqui está uma amostra.

    while true; do echo $RANDOM; done | while read line
    do
    echo Random is $line the last jobid is $(jobs -lp)
    jobs 2>&1 >/dev/null
    sleep 3
    done
0
J-o-h-n-