Найти и убить процесс в одной строке, используя bash и regex

410

Мне часто нужно убивать процесс во время программирования.

Теперь я делаю это:

[~]$ ps aux | grep 'python csp_build.py'
user    5124  1.0  0.3 214588 13852 pts/4    Sl+  11:19   0:00 python csp_build.py
user    5373  0.0  0.0   8096   960 pts/6    S+   11:20   0:00 grep python csp_build.py
[~]$ kill 5124

Как я могу извлечь идентификатор процесса автоматически и убить его в одной строке?

Вот так:

[~]$ ps aux | grep 'python csp_build.py' | kill <regex that returns the pid>
  • 2
    Поверь мне! : 'D Первый выбранный вами ответ гораздо сложнее, чем решение, которое вы сказали в своем ответе. Я предпочел бы выбрать свой путь.
  • 0
    Лучший способ проверить, существует ли процесс: stackoverflow.com/questions/3043978/…
Теги:
terminal
awk

20 ответов

891
Лучший ответ

В bash вы сможете:

kill $(ps aux | grep '[p]ython csp_build.py' | awk '{print $2}')

Подробная информация о его работе выглядит следующим образом:

  • ps предоставляет вам список всех процессов.
  • Фильтры grep, основанные на вашей строке поиска, [p] - это трюк, чтобы остановить процесс фактического grep.
  • awk просто дает вам второе поле каждой строки, которое является PID.
  • Конструкция $(x) означает выполнение x, затем вывести ее и поместить в командную строку. Результатом этого конвейера ps внутри этой конструкции является список идентификаторов процессов, поэтому вы получите команду типа kill 1234 1122 7654.

Здесь транскрипт, показывающий его в действии:

pax> sleep 3600 &
[1] 2225
pax> sleep 3600 &
[2] 2226
pax> sleep 3600 &
[3] 2227
pax> sleep 3600 &
[4] 2228
pax> sleep 3600 &
[5] 2229
pax> kill $(ps aux | grep '[s]leep' | awk '{print $2}')
[5]+  Terminated              sleep 3600
[1]   Terminated              sleep 3600
[2]   Terminated              sleep 3600
[3]-  Terminated              sleep 3600
[4]+  Terminated              sleep 3600

и вы можете увидеть, как он заканчивает все шпалы.


Объяснение бит grep '[p]ython csp_build.py' более подробно:

Когда вы выполняете sleep 3600 &, за которым следует ps -ef | grep sleep, вы получаете два процесса с sleep в нем: sleep 3600 и grep sleep (поскольку оба они имеют sleep в них, это не ракетостроение).

Однако ps -ef | grep '[s]leep' не создаст процесс с sleep в нем, вместо этого создаст grep '[s]leep', а вот сложный бит: grep не найдет его, потому что ищет регулярное выражение " любой символ из класса символов [s] (который равен s), за которым следует leep.

Другими словами, он ищет sleep, но процесс grep grep '[s]leep', который не имеет в нем sleep.

Когда мне было показано это (кем-то здесь, на SO), я сразу начал использовать его, потому что

  • это еще один процесс, чем добавление | grep -v grep; и
  • он элегантный и подлый, редкая комбинация: -)
  • 2
    @paxdiablo, можете ли вы предоставить ссылку для этого? Я сбит с толку, почему это работает.
  • 0
    @glenn, я попытался уточнить это немного. Надеюсь, это поможет.
Показать ещё 11 комментариев
91

если у вас есть pkill,

pkill -f csp_build.py

Если вы хотите только grep против имени процесса (вместо полного списка аргументов), оставьте -f.

  • 1
    Ничего не случилось, когда я проверял это.
  • 6
    сначала используйте pgrep, чтобы убедиться, что вы нашли правильный процесс. затем снова используйте pkill на правильном шаблоне.
Показать ещё 6 комментариев
34

Один вкладыш:

ps aux | grep -i csp_build | awk '{print $2}' | xargs sudo kill -9

  • Распечатайте столбец 2: awk '{print $2}'
  • sudo является необязательным
  • Запустите kill -9 5124, kill -9 5373 и т.д. (kill -15 более изящный, но немного медленнее)

Бонус:

У меня также есть две функции быстрого доступа, определенные в моем .bash_profile (~/.bash_profile для osx, вы должны увидеть, что работает для вашей машины * nix).

  • p
    • перечисляет все P rocesses, содержащие ключевое слово
    • использование: p csp_build, p python и т.д.

Код bash_profile:

# FIND PROCESS
function p(){
        ps aux | grep -i $1 | grep -v grep
}
  1. ka
    • < ll процессы, которые имеют это ключевое слово
    • использование, например: ka csp_build, ka python и т.д.
    • дополнительный уровень убийства, например: ka csp_build 15, ka python 9

Код bash_profile:

# KILL ALL
function ka(){

    cnt=$( p $1 | wc -l)  # total count of processes found
    klevel=${2:-15}       # kill level, defaults to 15 if argument 2 is empty

    echo -e "\nSearching for '$1' -- Found" $cnt "Running Processes .. "
    p $1

    echo -e '\nTerminating' $cnt 'processes .. '

    ps aux  |  grep -i $1 |  grep -v grep   | awk '{print $2}' | xargs sudo kill -klevel
    echo -e "Done!\n"

    echo "Running search again:"
    p "$1"
    echo -e "\n"
}
  • 0
    Напоминание - не забудьте перезапустить оболочку bash (терминал) для загрузки новых функций. ИЛИ запустите source ~/.bash_profile в текущей оболочке, чтобы импортировать новые функции (это то, что я предпочитаю).
  • 0
    Как и многие другие ответы здесь, это монументально страдает от бесполезного использования grep . Помните, все, что выглядит как grep x | awk '{ y }' обычно лучше и часто более надежен, если заменить его на awk '/x/ { y }'
Показать ещё 10 комментариев
12

Попробуйте использовать

ps aux | grep 'python csp_build.py' | head -1 | cut -d " " -f 2 | xargs kill
  • 0
    Пришлось немного его изменить. Это сработало. Благодарю. :) ps aux | grep 'python csp_build.py' | голова -1 | cut -d "" -f 5 | XARGS убивают
  • 2
    Пояснения приветствуются.
Показать ещё 2 комментария
9
killall -r regexp

-r, --regexp

Интерпретировать шаблон имени процесса как расширенное регулярное выражение.

7

Вы можете использовать только pkill '^python*' для убийства процесса regex.

Если вы хотите увидеть, что вы собираетесь убить или найти до убийства, просто используйте pgrep -l '^python*', где -l выдает также имя процесса. Если вы не хотите использовать pkill, используйте только:

pgrep '^python*' | xargs kill

5

вы можете сделать это с помощью awk и backtics

ps auxf |grep 'python csp_build.py'|`awk '{ print "kill " $2 }'`

$2 в awk печатает столбец 2, а backtics запускает напечатанное выражение.

Но гораздо более чистым решением было бы для процесса python хранить его идентификатор процесса в /var/run, а затем вы можете просто прочитать этот файл и убить его.

  • 0
    Разве вы не убьете оба процесса 5124 и 5373 тогда? Я думаю, это не проблема.
  • 0
    это не должно быть проблемой, но вы всегда можете добавить другой grep для исключения процесса grep: "grep -v grep" между grep и awk
Показать ещё 2 комментария
4

Использовать pgrep - доступно на многих платформах:

kill -9 `pgrep -f cps_build`

pgrep -f вернет все PID с совпадением "cps_build"

  • 2
    Если у вас есть pgrep , у вас также будет pkill . Как всегда, не используйте kill -9 если вы не знаете, почему kill -15 (по умолчанию) или kill -2 не будут работать.
  • 0
    Это выглядит как худший пересказ ответа @ nathanael, в котором пропущен неверно направленный -9 и используется правильный современный синтаксис подстановки команд. Подтвердите это вместо этого; хотя, конечно, ответ pkill еще лучше.
Показать ещё 3 комментария
3

Моя задача - убить все, что соответствует регулярному выражению, которое помещается в определенную директорию (после тестов селена не все было остановлено). Это сработало для меня:

for i in `ps aux | egrep "firefox|chrome|selenium|opera"|grep "/home/dir1/dir2"|awk '{print $2}'|uniq`; do kill -9 $i; done
  • 0
    Параметр kill -9 возможно, слишком агрессивен. Это не позволяет им освободить свои ресурсы.
  • 0
    Ницца! Единственный, который учитывает тот факт, что может быть более одного процесса сопоставления! Одно небольшое замечание: возможно, вы захотите добавить «grep -v grep» или что-то подобное в каналы, чтобы сам процесс grep не отображался в вашем списке процессов.
Показать ещё 2 комментария
3
ps -o uid,pid,cmd|awk '{if($1=="username" && $3=="your command") print $2}'|xargs kill -15
  • 0
    Не может +1 из-за суточного лимита, но стоит использовать параметр ps с опцией -o .
  • 0
    ps не дают мне много. [~] $ ps PID TTY TIME CMD 6365 pts / 6 00:00:00 ps 29112 pts / 6 00:00:00 bash
2

Это можно сделать еще быстрее, чем принятое решение (ы).

Если я хочу убить midori, например:

kill -SIGTERM $(pgrep midori)

Готово!

2

Я начал использовать что-то вроде этого:

kill $(pgrep 'python csp_build.py')
2

Метод, использующий только awkps):

ps aux | awk '$11" "$12 == "python csp_build.py" { system("kill " $2) }'

При использовании тестирования равенства строк я не могу совместить этот процесс.

  • 0
    По какой-то причине я не получаю «python csp_build.py». Но "питон" один бьет.
  • 0
    @ Orjanp Да, глупый недосмотр с моей стороны, см. Новую версию.
Показать ещё 1 комментарий
1

В некоторых случаях я хотел бы убивать процессы одновременно так:

➜  ~  sleep 1000 &
[1] 25410
➜  ~  sleep 1000 &
[2] 25415
➜  ~  sleep 1000 &
[3] 25421
➜  ~  pidof sleep
25421 25415 25410
➜  ~  kill `pidof sleep`
[2]  - 25415 terminated  sleep 1000                                                             
[1]  - 25410 terminated  sleep 1000
[3]  + 25421 terminated  sleep 1000

Но, я думаю, это немного неуместно в вашем случае. (Возможно, в фоновом режиме запущены python a, python b, python x...)

1

Дайте -f для pkill

pkill -f /usr/local/bin/fritzcap.py

точный путь файла .py

# ps ax | grep fritzcap.py
 3076 pts/1    Sl     0:00 python -u /usr/local/bin/fritzcap.py -c -d -m
1

Вам не нужен пользовательский переключатель для ps.

kill `ps ax | grep 'python csp_build.py' | awk '{print $1}'`
1

Убить наши собственные процессы, запущенные из обычного PPID, довольно часто, pkill, связанный с флагом –P, является для меня победителем. Пример @ghostdog74:

# sleep 30 &                                                                                                      
[1] 68849
# sleep 30 &
[2] 68879
# sleep 30 &
[3] 68897
# sleep 30 &
[4] 68900
# pkill -P $$                                                                                                         
[1]   Terminated              sleep 30
[2]   Terminated              sleep 30
[3]-  Terminated              sleep 30
[4]+  Terminated              sleep 30
0

Пригодится следующая команда:

kill $(ps -elf | grep <process_regex>| awk {'print $4'})

например., ps -elf | grep top

    0 T ubuntu    6558  6535  0  80   0 -  4001 signal 11:32 pts/1    00:00:00 top
    0 S ubuntu    6562  6535  0  80   0 -  2939 pipe_w 11:33 pts/1    00:00:00 grep --color=auto top

kill -$(ps -elf | grep top| awk {'print $4'})

    -bash: kill: (6572) - No such process
    [1]+  Killed                  top

Если процесс все еще застрял, используйте расширение "-9" для hardkill, как показано ниже:

kill -9 $(ps -elf | grep top| awk {'print $4'})

Надеюсь, что поможет...!

0

Я использую gkill processname, где gkill - это script:

cnt=`ps aux|grep $1| grep -v "grep" -c`
if [ "$cnt" -gt 0 ]
then
    echo "Found $cnt processes - killing them"
    ps aux|grep $1| grep -v "grep"| awk '{print $2}'| xargs kill
else
    echo "No processes found"
fi

ПРИМЕЧАНИЕ: он не будет убивать процессы, которые имеют "grep" в их командных строках.

  • 1
    Как и многие, многие другие изобретения якского сарая, это пронизано бесполезным использованием grep и других распространенных антипаттернов сценариев оболочки.
0

Я использую это, чтобы убить Firefox, когда он script захлопнулся и cpu bashing:) Замените "Firefox" на приложение, которое хотите умереть. Я нахожусь в оболочке Bash - OS X 10.9.3 Darwin.

kill -Hup $(ps ux | grep Firefox | awk 'NR == 1 {next} {print $2}' | uniq | sort)

  • 0
    Замена grep Firefox | awk 'NR == 1 { next } ...' с awk 'NR == 1 || $11 !~ /Firefox/ { next } ...' не только сохраняет процесс, но и повышает точность. Это не сложно избавиться от sort | uniq в чистом Awk также (тогда как, конечно, uniq | sort просто ошибочен - он пропустит любые дубликаты, которые не являются смежными, и скрыт ошибку, без необходимости сортируя выходные данные uniq ).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню