Невозможно завершить процесс, который запущен, но, по-видимому, не виден в диспетчере задач

Невозможно завершить процесс, который запущен, но, по-видимому, не виден в диспетчере задач

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

Связанный контент