Come sopprimere il messaggio terminato dopo aver ucciso in bash?

Come si può sopprimere il messaggio Terminated che appare dopo aver ucciso un processo in uno script bash?

Ho provato set +bm , ma non funziona.

So che un’altra soluzione implica chiamare exec 2> /dev/null , ma è affidabile? Come posso resettarlo in modo che possa continuare a vedere stderr?

La risposta breve è che non puoi. Bash stampa sempre lo stato dei lavori in primo piano. Il flag di monitoraggio si applica solo ai lavori in background e solo per shell interattive, non script.

vedi notify_of_job_status () in jobs.c.

Come dici tu, puoi redirect così l’errore standard punta a / dev / null ma poi ti perdi altri messaggi di errore. Puoi renderlo temporaneo eseguendo il reindirizzamento in una sottoshell che esegue lo script. Questo lascia l’ambiente originale da solo.

 (script 2> /dev/null) 

che perderà tutti i messaggi di errore, ma solo da quello script, non da qualsiasi altra esecuzione in quella shell.

È ansible salvare e ripristinare l’errore standard, reindirizzando un nuovo filedescriptor in modo che punti 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 

Ma non lo consiglierei – l’unico aspetto positivo del primo è che salva una chiamata alla sub-shell, mentre è più complicata e, se ansible, addirittura altera il comportamento dello script, se lo script altera i descrittori di file.


MODIFICARE:

Per una risposta più appropriata, controlla la risposta data da Mark Edgar

Per silenziare il messaggio, devi redirect lo stderr al momento della generazione del messaggio . Poiché il comando kill invia un segnale e non attende che il processo di destinazione risponda, redirect lo stderr del comando kill non ti fa bene. L’ wait incorporata di bash è stata creata appositamente per questo scopo.

Ecco un esempio molto semplice che uccide il comando di sfondo più recente. ( Ulteriori informazioni su $! Qui. )

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

Poiché sia kill che wait accettano più pid, puoi anche fare batch kill. Ecco un esempio che uccide tutti i processi in background (del processo / script corrente ovviamente).

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

Sono stato condotto qui da bash: in silenzio, ho interrotto il processo della funzione di sfondo .

Ispirato alla risposta di MarcH . Stavo usando kill -INT come suggerisce con un certo successo, ma ho notato che non stava uccidendo alcuni processi. Dopo aver provato alcuni altri segnali, vedo che SIGPIPE ucciderà anche senza un messaggio.

 kill -PIPE 

o semplicemente

 kill -13 

Soluzione: usa SIGINT (funziona solo con shell non interattive)

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

Forse staccare il processo dal processo corrente della shell chiamando disown ?

È questo ciò che stiamo cercando?

Non voluto:

 $ sleep 3 & [1] 234  $ $ [1]+ Done sleep 3 $ 

Ricercato:

 $ (set +m; sleep 3 &)  $ $ $ $ $ 

Come puoi vedere, nessun messaggio di fine lavoro. Funziona anche con script di bash, anche per i processi in background.

‘set + m’ disabilita il controllo del lavoro (vedi ‘help set’) per la shell corrente. Quindi se inserisci il tuo comando in una subshell (come fatto qui tra parentesi) non influenzerai le impostazioni di controllo del job della shell corrente. L’unico svantaggio è che è necessario riportare il pid del processo in background alla shell corrente se si desidera verificare se è stato terminato o valutare il codice di ritorno.

Questo funziona anche per killall (per chi lo preferisce):

killall -s SIGINT (tuo programma)

sopprime il messaggio .. Stavo eseguendo mpg123 in backgroundmode. Potrebbe essere ucciso silenziosamente inviando un ctrl-c (SIGINT) invece di un SIGTERM (predefinito).

Un altro modo per disabilitare le notifiche di lavoro è posizionare il comando in modo che venga eseguito lo sfondo in un costrutto sh -c 'cmd &' .

 #!/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}" ' 

disown ha fatto esattamente la cosa giusta per me – il exec 3> & 2 è rischioso per molte ragioni – set + bm non sembra funzionare all’interno di uno script, solo al prompt dei comandi

Ha avuto successo con l’aggiunta di ” jobs 2>&1 >/dev/null ” allo script, non certo se questo aiuterà lo script di qualcun altro, ma qui c’è un esempio.

  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 

Semplice:

{kill $! } 2> / dev / null

Vantaggio? può usare qualsiasi segnale

es: {kill -9 $ PID} 2> / dev / null

Ho trovato che mettere il comando kill in una funzione e quindi fare il backing della funzione sopprime l’output di terminazione

 function killCmd() { kill $1 } killCmd $somePID &