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?

Robottinosino
la source
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.

jw013
la source
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
brunocascio
la source
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.

Mikemaccana
la source
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.

Clément Cherlin
la source
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
Fanchen Bao
la source
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

samvel1024
la source