Beenden Sie alle Hintergrundjobs

63

Gibt es eine kompaktere Form zum Beenden von Hintergrundjobs als:

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

Außerdem enthält {1..5} offensichtlich eine fest codierte magische Zahl. Wie kann ich sie zu "N" machen, wobei N die richtige Zahl ist, ohne Folgendes zu tun:

$(jobs | wc -l)

Ich verwende \ j in PS1, um die Anzahl der verwalteten Jobs zu ermitteln. Ist das äquivalent?

Robottinosino
quelle
3
kill $(jobs -p)scheint einfacher.
JW013,
Ich würde es vorziehen, Jobs nach Möglichkeit einzeln zu töten. (Ich könnte jedoch Ihren Kommentar falsch verstanden haben)
Robottinosino
for pid in $(jobs -p); do kill $pid; done?
JW013
3
@ jw013 Es ist nicht nur einfacher, es ist auch richtig (bitte als Antwort posten), im Gegensatz zu einer Lösung, die darauf basiert, die Zeilen der Ausgabe zu zählen, jobsdie nur funktioniert, wenn die Jobs fortlaufend nummeriert werden. Oh, und "Jobs einzeln beenden" ist bedeutungslos: Das Übergeben mehrerer PIDs an den killBefehl bewirkt genau dasselbe wie das separate Übergeben.
Gilles 'SO- hör auf böse zu sein'
Ich habe den Befehl falsch eingegeben, $ (jobs -p) Wörter getötet und sehe auch für mich sehr korrekt aus. Bereit zu akzeptieren.
Robottinosino

Antworten:

102

Um nur killalle von verwalteten Hintergrundjobs anzuzeigen bash, gehen Sie wie folgt vor

kill $(jobs -p)

Beachten Sie, dass Sie, da beide jobsund integriert killsind bash, keine Fehler der Argumentliste mit zu langem Typ erhalten sollten.

jw013
quelle
2
Auch für die Nachwelt ist das, was Bahamat denkt, die Art und Weise, wie dies getan wird, um zshsie als Autorität auf diesem Gebiet zu disqualifizieren.
8.
Ich habe das Gefühl, dass ich das wissen sollte, aber wie funktioniert das '$' hier?
Fersarr
1
@fersarr Here you go
jw013
@bahamat Das funktioniert nicht wirklich, da sich die PID möglicherweise in Feld 2 oder 3 befindet, je nachdem, ob der Job% + oder% - ist oder nicht. Was funktioniert, ist kill %${(k)^jobdirs}, was in der Tat länger ist; Wenn Sie die PIDs auflisten müssen, können Sie die noch länger verwenden ${${jobstates#*:*:}%%=*}.
Gilles 'SO- hör auf böse zu sein'
Auf CentOS wartet meine Eingabeaufforderung auf weitere Eingaben>
Janac Meena 13.11.18
15

Verwenden Sie xargsanstelle des $(jobs -p)Unterbefehls, da jobs -pder Befehl kill fehlschlägt , wenn er leer ist.

jobs -p | xargs kill
brunocascio
quelle
1
Dies hat genau den gleichen Effekt, gibt jedoch die Hilfe aus und wird mit dem Code 123
cat am
1
Der Befehl funktioniert gut unter OSX, aber nicht unter Debian
brunocascio
Dies funktioniert hervorragend unter CentOS 6
Janac Meena 13.11.18
jobs -p | xargs -rn10 killwird es besser machen, wenn jobs -pkeine PIDs zurückgegeben werden. Beachten Sie, dass es sich bei dieser -rOption um eine GNU-Erweiterung handelt.
NarūnasK
Wie oben erwähnt, -rist dies das Kurzformat für die --no-run-if-emptyGNU-Erweiterung, mit xargsder angewiesen wird, den Befehl nicht auszuführen, wenn stdin keine Daten enthält.
Anthony G - Gerechtigkeit für Monica
3

Ich bevorzuge es, zu prüfen, ob Jobs vorhanden sind, bevor ich sie beende. Auf diese Weise schlägt das Skript nicht fehl, wenn nichts ausgeführt wird.

Es ist auch kürzer zu tippen. Werfen Sie dies in Ihre .bash_profile:

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

Dann renne:

killjobs

Um laufende Jobs zu beenden.

Mikemaccana
quelle
1

Ich habe mehrere zusammengesetzte Befehle im Hintergrund, die ich ordnungsgemäß beenden möchte, indem ich SIGINT an jeden Prozess unter macOS sende. Keine der anderen Lösungen hat dafür richtig funktioniert, daher habe ich mir Folgendes ausgedacht:

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

jobs -p listet Hintergrundprozesse auf, die von der aktuellen Shell gestartet wurden.

xargs -n1 Führt pkill einmal für jeden Job aus.

pkill -SIGINT -g Sendet SIGINT (wie Strg + C) an alle Prozesse in der Prozessgruppe.

Clement Cherlin
quelle
1

Ich denke, je nachdem, welche Ausgabe es jobs -pgibt, könnte die Lösung leicht abweichen. In meinem Fall

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

Daher ist das Folgende nicht gut.

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

Auf der anderen Seite kill $(jobs -p)funktioniert das Ausführen , bringt jedoch viele Fehlermeldungen mit sich, da auch die Nicht-PID-Zeichenfolgen übergeben werden kill.

Daher ist meine Lösung, zuerst grepdie PID und dann xargswie folgt zu verwenden:

$ jobs -p | grep -o -E '\s\d+\s' | xargs kill
Fanchen Bao
quelle
1
Welche Shell benutzt du? Was echo $0zeigt? Was help jobszeigt? Die abgebildete Ausgabe ist nicht POSIX-kompatibel . Jede Implementierung von jobssollte eine -pOption mit dem beabsichtigten Verhalten haben.
Wildcard
1
Vielen Dank für den Hinweis. Ich benutze zsh, und das ist der Grund für die seltsame Ausgabe. Ich bin auf bash umgestiegen und jobs -phabe nur PID ausgegeben. Ich habe gerade erfahren, dass zsh nicht vollständig POSIX-kompatibel ist.
Fanchen Bao
0

Scheint, als ob jobs -p | xargs killder Job erledigt ist, erzeugt jedoch einige unerwünschte Ausgaben, die zum Töten weitergeleitet werden. Hier gruppiere ich die Ausgabe jobs -pvon mit / ohne + oder - Zeichen

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

Und später kannst du einfach anrufen killjobs

samvel1024
quelle