Я запустил приложение, которое не запускается, но не могу удалить его, потому что оно все еще работает. Я могу распечатать PID, но не могу завершить процесс, использующий его.
~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process
решение1
Вы заметили, что в двух попытках вы получили два разных PID?
Подумайте об этом: если вы введете команду типа vi raven.txt
, то ps ax
отобразит строку, которая показывает команду vi raven.txt
. Аналогично, если вы введете команду типа grep snappr
, то ps ax
отобразит строку, которая показывает команду grep snappr
. И если вы передадите вывод этого ps
через grep snappr
, то grep
найдет строкукоторый описывает себя. Итак, если вы введете
$ ps ax | grep snappr | awk '{print $1}'
многократно, каждый раз будет выводиться разное число (потому что печатается PID , и каждый раз при запуске команды grep
вы получаете новый, уникальный процесс).grep
Наконец, учтите: kill
команда не может быть выполнена, пока не будут известны ее аргументы. Чтобы ее аргумент был известен, конвейер $(ps ax | grep snappr | awk '{print $1}')
должен быть завершен. Это подразумевает, что grep
должен был завершиться 1 . Следовательно, kill
получает PID процесса grep
, но только после того, как grep
процесс завершился — поэтому, естественно, он сообщает «Нет такого процесса».
Возможно, мне следовало упомянуть, что не snappr
запущен ни один процесс. Если бы они были, ваша первая команда вывела бы два числа: PID snappr
и PID grep snappr
. Теперь, если snappr
бы были запущены, ваша команда могла бы начать работать полуправильно, то есть она делает то, что вам нужно, но также выдает сообщение об ошибке. Если запущен snappr
с PID 42097 и grep snappr
работает с PID 70848, то kill
команда будет kill 42097 70858
, которая убьет snappr
и получит сообщение об ошибке при попытке убить grep
процесс, который больше не существует.
Вы, вероятно, захотите улучшить это. Мой любимый способ, который я придумал 20 лет назад, это изменить grep
на grep "[s]nappr"
, который будет соответствовать, snappr
но не будет соответствовать самому себе. Другой подход — использовать pgrep
вместо ps | grep
.
1 В качестве альтернативы, the awk
может завершиться, если grep
просто закрыть свой stdout. Это было бы очень необычным поведением для программы *nix.
решение2
Более короткий ответ
Не прыгайте через обручи Bash, чтобы убить snappr
с помощью ps
, пропущенного через grep
и затем пропущенного через awk
вот так. Вместо этого попробуйте убить его вот так, используяpkill
; никакой суеты и беспорядка, и он сразу же выбирает цель на основе имени процесса:
sudo pkill snappr
Более длинный ответ
Не совсем понятно, какСнапперработает на уровне системного процесса, но проблема может заключаться в том, что вы захватываете только идентификатор дочернего процесса вместо идентификатора родительского процесса.
На самом деле я считаю, что метод, который вы используете для получения идентификатора процесса ( ps ax | grep snappr | awk '{print $1}'
), вернет целый список идентификаторов процессов, подключенных к процессу, snappr
независимо от того, родительский он или дочерний. Так что, используя это, вымощьзавершить один идентификатор процесса, который является всего лишь идентификатором дочернего процесса, при этом родительский идентификатор все еще будет активен и сможет «породить» другой дочерний процесс для компенсации.
Так что, возможно, вы можете сделать что-то вроде этого, чтобы получить окончательный родительский идентификатор любого идентификатора процесса, который вы ему передаете, и действовать в соответствии с ним; простое доказательство концепции того, как это работает:
ps -p [process ID] -o ppid=
Выполнение этой простой команды в Bash даст вам идентификатор родительского процесса для идентификатора дочернего процесса, который вы указали [process ID]
. Таким образом, если идентификатор дочернего процесса 4567
имеет идентификатор родительского процесса, 123
то команда будет выглядеть так:
ps -p 4567 -o ppid=
И это вернулось бы, 123
.
Тем не менее, это может быть опасным способом работы с блуждающим процессом, поскольку если ваш скрипт захватывает фактический идентификатор родительского процесса snapper
, то родитель этого идентификатора процесса может быть на самом деле вашей собственной оболочкой Bash. Таким образом, вы можете непреднамеренно просто убить свою оболочку Bash вместо того, чтобы snapper
вылететь из системы, оставив snapper
процесс запущенным.
Но, несмотря на все вышесказанное, почему бы не облегчить себе жизнь и просто не бегать?pkill
так:
sudo pkill snappr
Это завершит все подключенные процессы snappr
без каких-либо сложных манипуляций с командной строкой.