Uccidi tutti i lavori in background


63

Esiste una forma più compatta di uccidere i lavori in background rispetto a:

for i in {1..5}; do kill %$i; done

Inoltre, {1..5} ha ovviamente un numero magico codificato, come posso renderlo "N" con N che è il numero giusto, senza fare un:

$(jobs | wc -l)

In realtà utilizzo \ j in PS1 per ottenere il numero di lavori gestiti, è equivalente?


3
kill $(jobs -p)sembra più facile.
jw013,

Preferirei uccidere i lavori individualmente, se possibile. (Potrei aver frainteso il tuo commento, però)
Robottinosino,

for pid in $(jobs -p); do kill $pid; done?
jw013,

3
@ jw013 Non è solo più semplice, ma in realtà è corretto (si prega di pubblicarlo come risposta), a differenza di una soluzione basata sul conteggio delle righe dell'output di jobscui funziona solo se i lavori vengono numerati consecutivamente. Oh, e "uccidere i lavori individualmente" non ha senso: passare più PID al killcomando fa esattamente la stessa cosa che passarli separatamente.
Gilles 'SO- smetti di essere malvagio' il

Stavo inserendo il comando in modo errato, ho ucciso $ (jobs -p) parole e sembra molto corretto anche per me. Pronto ad accettare
Robottinosino,

Risposte:


101

Per appena killtutti i processi in background gestiti da bash, fanno

kill $(jobs -p)

Si noti che dal momento che entrambi jobse killsono integrati bash, non si dovrebbe incontrare alcun errore dell'elenco Argument troppo lungo .


2
Anche per i posteri, ciò che Bahamat pensa sia il modo di farlo, zshli squalifica come qualsiasi autorità sull'argomento.
p

Sento che dovrei saperlo, ma come funzionano i '$' qui?
Fersarr,

1
@fersarr Here you go
jw013

@bahamat In realtà non funziona poiché il PID può trovarsi nel campo 2 o 3 a seconda che il lavoro sia uno di% + o% - oppure no. Ciò che funziona è kill %${(k)^jobdirs}, che è davvero più lungo; se è necessario elencare i PID, è possibile utilizzare anche più a lungo ${${jobstates#*:*:}%%=*}.
Gilles 'SO- smetti di essere malvagio' il

Su CentOS, il mio prompt è in attesa di ulteriori input>
Janac Meena,

15

Utilizzare al xargsposto del $(jobs -p)sottocomando, perché se jobs -pè vuoto il comando kill non riuscirà.

jobs -p | xargs kill

1
Questo ha lo stesso identico effetto, stampa l'aiuto ed esce con il codice 123
cat

1
Il comando funziona bene su OSX ma non funziona su Debian
brunocascio l'

Funziona alla grande su CentOS 6
Janac Meena il

jobs -p | xargs -rn10 killfarà meglio se jobs -pnon restituisce alcun PID. Nota che l' -ropzione è l'estensione GNU.
NarūnasK,

Come accennato in precedenza, -rè il formato breve per l' --no-run-if-emptyestensione GNU a xargscui viene indicato di non eseguire il comando se stdin non ha dati.
Anthony G - giustizia per Monica il

3

Preferisco controllare se ci sono lavori che esistono prima di ucciderli - in questo modo lo script non fallirà se non c'è nulla in esecuzione.

È anche più breve da digitare. Getta questo nel tuo .bash_profile:

function killjobs () {
    JOBS="$(jobs -p)";
    if [ -n "${JOBS}" ]; then;
        kill -KILL ${JOBS};
    fi
}

Quindi eseguire:

killjobs

Per uccidere tutti i lavori in esecuzione.


1

Ho diversi comandi composti in background che voglio terminare con garbo, inviando SIGINT ad ogni processo, su macOS. Nessuna delle altre soluzioni ha funzionato correttamente, quindi ho pensato a questo:

jobs -p | xargs -n1 pkill -SIGINT -g

jobs -p elenca i processi in background avviati dalla shell corrente.

xargs -n1 esegue pkill una volta per ogni lavoro.

pkill -SIGINT -g invia SIGINT (uguale a ctrl + c) a tutti i processi nel gruppo di processi.


1

Immagino che, a seconda dell'output jobs -p, la soluzione potrebbe essere leggermente diversa. Nel mio caso

$ jobs -p
[1]  - 96029 running    some job
[2]  + 96111 running    some other job

Pertanto, fare quanto segue non va bene.

$ jobs -p | xargs kill
kill: illegal process id: [1]

D'altra parte, l'esecuzione kill $(jobs -p)funziona ma comporta molti messaggi di errore, poiché anche le stringhe non PID vengono passate kill.

Pertanto, la mia soluzione è grepprima il PID e quindi utilizzare xargs, come segue:

$ jobs -p | grep -o -E '\s\d+\s' | xargs kill

1
Che shell stai usando? Cosa echo $0mostra? Cosa help jobsmostra? L'output illustrato non è conforme a POSIX ; qualsiasi implementazione di jobsdovrebbe avere -pun'opzione con il comportamento previsto.
Wildcard il

1
Grazie per averlo segnalato. Sto usando zsh, e questa è la ragione dello strano output. Sono passato a bash e jobs -pho emesso solo PID. Ho appena imparato che zsh non è completamente conforme a POSIX.
Fanchen Bao,

0

Sembra jobs -p | xargs killfare il lavoro, tuttavia produce un output indesiderato convogliato per uccidere. Qui sto raggruppando l'output di jobs -pavendo / non avendo il carattere + o -

function killjobs() {
    JOBS=$(jobs -p)
    echo $JOBS | grep -v "+\|-"| awk '{print $2}' | xargs kill -9
    echo $JOBS | grep "+\|-"| awk '{print $3}' | xargs kill -9
}

E più tardi puoi semplicemente chiamare killjobs

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.