6

Я запустил приложение, которое не запускается, но не могу удалить его, потому что оно все еще работает. Я могу распечатать PID, но не убить процесс, используя его.

~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process

2 ответа2

17

Вы заметили, что у вас есть два разных 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 .


В качестве альтернативы, awk может закончиться, если grep просто закроет свой стандартный вывод.  Это было бы очень необычным поведением для * nix программы.

8

Краткий ответ

Не перепрыгивайте через обруч Bash, чтобы убить snappr с помощью ps , пропустите через grep а затем пропустите через awk вот так. Вместо этого попытайтесь убить его таким образом, используя pkill ; без суеты и суеты, и она нацелена на имя процесса из коробки:

sudo pkill snappr

Более длинный ответ

Не совсем понятно, как работает Snapper на уровне системных процессов, но проблема может заключаться в том, что вы захватываете только идентификатор дочернего процесса, а не идентификатор родительского процесса.

На самом деле, я считаю, что метод, который вы используете для получения идентификатора процесса (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 без каких-либо хитрых манипуляций с командной строкой.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .