Tuer tous les emplois de fond


63

Existe-t-il une forme plus compacte de suppression des tâches en arrière-plan que:

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

De plus, {1..5} contient évidemment un nombre magique codé en dur. Comment puis-je le faire "N", N étant le bon nombre, sans faire un:

$(jobs | wc -l)

J'utilise réellement \ j dans PS1 pour obtenir le nombre de travaux gérés. Est-ce équivalent?


3
kill $(jobs -p)semble plus facile.
jw013

Je préférerais tuer les emplois individuellement, si possible. (J'ai peut-être mal compris votre commentaire, cependant)
Robottinosino, le

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

3
@ jw013 C'est non seulement plus facile, mais en fait, c'est correct (postez-le comme réponse), contrairement à une solution basée sur le comptage des lignes de la sortie, jobsqui ne fonctionne que si les tâches sont numérotées de manière consécutive. Oh, et «tuer les travaux individuellement» n'a pas de sens: transmettre plusieurs PID à la killcommande revient exactement à les transmettre séparément.
Gilles 'SO- arrête d'être méchant'

J'entrais dans la commande de manière incorrecte, tue les mots $ (jobs -p) et me semble également très correct. Prêt à accepter.
Robottinosino

Réponses:


101

Pour seulement killtous les jobs d'arrière-plan gérés par bash,

kill $(jobs -p)

Notez que puisque les deux jobset killsont intégrés dans bash, vous ne devriez pas avoir des erreurs de la liste d'arguments trop longue de type.


2
Également pour la postérité, ce que Bahamat pense, c’est la manière de le faire, ce qui les zshdisqualifie en tant qu’autorité sur le sujet.
Peth

Je sens que je devrais le savoir, mais comment fonctionne le '$' ici?
Fersarr

1
@fersarr Ici vous allez
jw013

@bahamat Cela ne fonctionne pas, car le PID peut se trouver dans les champs 2 ou 3, selon que le travail est%% ou% - ou non. Ce qui fonctionne est kill %${(k)^jobdirs}ce qui est effectivement plus long; si vous devez répertorier les PID, vous pouvez utiliser le plus long ${${jobstates#*:*:}%%=*}.
Gilles, arrête de faire le mal

Sur CentOS, mon invite attend d'autres entrées>
Janac Meena

15

Utilisez à la xargsplace de la $(jobs -p)sous - commande, car si jobs -pest vide, la commande kill échouera.

jobs -p | xargs kill

1
Cela a exactement le même effet, il affiche l’aide et se termine avec le code 123
Cat

1
La commande fonctionne bien sous OSX mais ne fonctionne pas sous Debian
brunocascio Le

Cela fonctionne très bien sur CentOS 6
Janac Meena

jobs -p | xargs -rn10 killfera mieux mieux si jobs -pne renvoie aucun PID. Notez que cette -roption est l’extension GNU.
NarūnasK

Comme mentionné ci-dessus, il -rs'agit du format abrégé de l' --no-run-if-emptyextension GNU, xargsqui lui indique de ne pas exécuter la commande si stdin ne contient aucune donnée.
Anthony G - justice pour Monica le

3

Je préfère vérifier s'il y a des emplois existants avant de les tuer - de cette façon, le script ne va pas échouer si rien ne tourne.

C'est aussi plus court pour taper. Jetez ceci dans votre .bash_profile:

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

Puis lancez:

killjobs

Pour tuer tous les travaux en cours d'exécution.


1

J'ai plusieurs commandes composées en arrière-plan que je souhaite terminer avec élégance, en envoyant SIGINT à chaque processus, sur macOS. Aucune des autres solutions ne fonctionnait correctement pour cela, alors je suis venu avec ceci:

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

jobs -p liste les processus en arrière-plan démarrés par le shell actuel.

xargs -n1 exécute pkill une fois pour chaque travail.

pkill -SIGINT -g envoie SIGINT (comme ctrl + c) à tous les processus du groupe de processus.


1

Je suppose que selon la sortie jobs -p, la solution pourrait être légèrement différente. Dans mon cas

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

Par conséquent, ce qui suit n’est pas bon.

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

D'autre part, l'exécution kill $(jobs -p)fonctionne, mais entraîne beaucoup de messages d'erreur, car les chaînes non PID sont également transmises kill.

Par conséquent, ma solution consiste à greputiliser d'abord le PID, puis à l'utiliser xargscomme suit:

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

1
Quelle coquille utilisez-vous? Que echo $0montre? Que help jobsmontre? La sortie illustrée n’est pas conforme à POSIX ; toute implémentation de jobsdevrait avoir une -poption avec le comportement souhaité.
Wildcard

1
Merci de l'avoir signalé. J'utilise zsh, et c'est la raison de la sortie étrange. Je suis passé à bash et jobs -pn'ai généré que le PID. Je viens d'apprendre que zsh n'est pas complètement compatible POSIX.
Fanchen Bao le

0

On dirait que jobs -p | xargs killça fait le boulot, mais ça produit des sorties indésirables qui vont être tuées. Je regroupe ici la sortie de jobs -pen ayant / ne pas avoir le caractère + ou -

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

Et plus tard, vous pouvez simplement appeler killjobs

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.