Убить все фоновые задания

63

Существует ли более компактная форма убийства фоновых заданий, чем:

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

Кроме того, {1..5}, очевидно, содержит жестко закодированное магическое число, как я могу сделать его "N", где N - это правильное число, без выполнения:

$(jobs | wc -l)

Я фактически использую \ j в PS1, чтобы получить количество управляемых заданий, это эквивалентно?

Robottinosino
источник
3
kill $(jobs -p)кажется проще.
jw013
Я бы предпочел убивать работу индивидуально, если это возможно. (Я, возможно, неправильно понял ваш комментарий)
Robottinosino
for pid in $(jobs -p); do kill $pid; done?
jw013
3
@ jw013 Это не только проще, но на самом деле правильно (пожалуйста, опубликуйте это как ответ), в отличие от решения, основанного на подсчете строк выходных данных, jobsкоторое работает только в том случае, если задания последовательно нумеруются. Да, и «убивать задания по отдельности» не имеет смысла: передача нескольких PID killкоманде делает то же самое, что и передача их по отдельности.
Жиль "ТАК - перестань быть злым"
Я неправильно вводил команду, убивал слова $ (jobs -p) и тоже выглядел очень корректно. Готов принять.
Robottinosino

Ответы:

101

Чтобы выполнить killвсе фоновые задания bash, выполните

kill $(jobs -p)

Обратите внимание, что поскольку оба jobsи killвстроены bash, вы не должны сталкиваться с ошибками в списке аргументов слишком длинного типа.

jw013
источник
2
Также для потомков, то, что думает Багамат, - это способ сделать это, что zshлишает их всякого авторитета в этой теме.
Пет
Я чувствую, что должен знать это, но как здесь работает '$'?
Fersarr
1
@fersarr Вот ,
пожалуйста
@bahamat Это на самом деле не работает, поскольку PID может быть в поле 2 или 3, в зависимости от того, является ли задание одним из% + или% - или нет. Что работает kill %${(k)^jobdirs}, что действительно дольше; если вам нужно перечислить PID, вы можете использовать еще дольше ${${jobstates#*:*:}%%=*}.
Жиль "ТАК ... перестать быть злым"
В CentOS моя подсказка ждет большего ввода>
Janac Meena
15

Используйте xargsвместо $(jobs -p)подкоманды, потому что если jobs -pпусто, команда kill не будет выполнена.

jobs -p | xargs kill
brunocascio
источник
1
Это имеет тот же самый точный эффект, хотя, это печатает помощь и выходит с кодом 123
кошка
1
Команда отлично работает на OSX, но не работает на Debian
brunocascio
Это прекрасно работает на CentOS 6
Janac Meena
jobs -p | xargs -rn10 killбудет лучше, если jobs -pне вернет PID. Обратите внимание, что -rопция является расширением GNU.
NarūnasK
Как упомянуто выше, -rэто краткий формат для --no-run-if-emptyрасширения GNU, xargsкоторый указывает ему не запускать команду, если stdin не имеет данных.
Энтони Дж - правосудие для Моники
3

Я предпочитаю проверить, существуют ли какие-либо задания, прежде чем их убивать - таким образом, скрипт не потерпит неудачу, если ничего не выполняется

Это также короче, чтобы напечатать. Добавьте это в свой .bash_profile:

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

Затем запустите:

killjobs

Чтобы убить любые рабочие места.

mikemaccana
источник
1

У меня есть несколько сложных составных команд, которые я хочу завершить, отправив SIGINT каждому процессу в macOS. Ни одно из других решений не работало должным образом, поэтому я придумал следующее:

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

jobs -p перечисляет фоновые процессы, запущенные текущей оболочкой.

xargs -n1 выполняет pkill один раз для каждой работы.

pkill -SIGINT -g отправляет SIGINT (как ctrl + c) всем процессам в группе процессов.

Клемент Черлин
источник
1

Я думаю, в зависимости от того, что jobs -pдает результат, решение может быть немного другим. В моем случае

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

Следовательно, делать следующее нехорошо.

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

С другой стороны, запуск kill $(jobs -p)работает, но влечет за собой много сообщений об ошибках, поскольку строки, не являющиеся PID, также передаются kill.

Поэтому, мое решение - grepсначала использовать PID, а затем использовать xargsследующее:

$ jobs -p | grep -o -E '\s\d+\s' | xargs kill
Фанчен Бао
источник
1
Какую оболочку вы используете? Что echo $0показывает? Что help jobsпоказывает? Показанный вывод не соответствует POSIX ; любая реализация jobsдолжна иметь -pопцию с предполагаемым поведением.
Подстановочный
1
Спасибо за указание на это. Я использую Zsh, и это является причиной странного вывода. Я переключился на bash и jobs -pсделал только вывод PID. Я только что узнал, что zsh не полностью POSIX-совместимый.
Fanchen Bao
0

Похоже, что jobs -p | xargs killделает работу, однако он производит некоторые нежелательные выходные данные, чтобы убить. Здесь я группирую вывод jobs -pпо наличию / отсутствию символа + или -

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

А позже вы можете просто позвонить killjobs

samvel1024
источник