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

6604
aweeeezy

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

~ $ ps ax | grep snappr | awk '' 70824 ~ $ kill $(ps ax | grep snappr | awk '') -bash: kill: (70832) - No such process 
6
@BeowulfOF: "Порядок вывода ps"? А? Как это имеет смысл? Если бы `snappr` был запущен, первая команда перечислила бы два PID: для snappr и для grep, как объяснено в моем ответе, который я опубликовал за полчаса до того, как вы оставили этот комментарий. ... ... ... ... ... PS Возможно, вы захотите отредактировать ваш вклад немного лучше ("I the error states", "ad", "mit"). Scott 9 лет назад 0
Извините, Скотт, ошибки произошли из-за автокоррекции, я написал это вкратце со своего мобильного телефона. Нет, извините, поэтому я удалил комментарий. Oliver Friedrich 9 лет назад 0
Ваш `grep snappr` соответствует процессу` grep snappr`. Sobrique 9 лет назад 4
Какая платформа? Mac OS X? Linux? Cygwin? Peter Mortensen 9 лет назад 0

2 ответа на вопрос

17
Scott

Вы заметили, что у вас есть два разных PID в двух попытках?

Учтите это: если вы наберете команду как vi raven.txt, то ps axпоявится строка, которая показывает команду vi raven.txt. Аналогично, если вы наберете команду вроде grep snappr, то ps axпоявится строка, которая показывает команду grep snappr. И, если вы передадите вывод этого psчерез grep snappr, the grepнайдет строку, которая описывает себя . Итак, если вы введете

$ ps ax | grep snappr | awk '' 

несколько раз он будет печатать разное число каждый раз (потому что он печатает PID grep, и вы получаете новый, уникальный grepпроцесс при каждом запуске команды).

Наконец, учтите: killкоманда не может быть выполнена до тех пор, пока не будут известны ее аргументы. Чтобы его аргумент был известен, $(ps ax | grep snappr | awk '')конвейер должен быть завершен. Это означает, что grepдолжно быть прекращено 1 . Следовательно, killему присваивается PID grepпроцесса, но только после того, как grepпроцесс завершен - поэтому, естественно, он сообщает «Нет такого процесса».

Возможно, я должен был упомянуть, что snapprпроцесс не запущен. Если бы это было так, ваша первая команда выдала бы два числа: PID of snapprи PID of 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 Альтернативно, он awkможет закончить, если grepпросто закроет свой стандартный вывод. Это было бы очень необычным поведением для * nix программы.

У меня есть скрипт bash, который я хочу запустить только один раз на моей машине. В скрипте я использую этот код для проверки (где $ THIS - это имя скрипта): `PRIOR =" $ (ps --no-headers -Ao "pid, ppid, sid, args" | grep "$ THIS" | grep -Ev "(grep | $ PPID | $$ |) ")" `. Если $ PRIOR не равен нулю, скрипт уже запущен. Я добился большего успеха с этим, чем с `pgrep`. gogoud 9 лет назад 0
Ах да, старый `grep | grep -v` решение. Зачем запускать дополнительный процесс, который вам не нужен? Работай умом, а не силой. Scott 9 лет назад 0
Я согласен, это выглядит грязно. Я был бы счастлив найти лучший, надежный способ. ps -C не перехватывает все процессы, pgrep включает несуществующие процессы. gogoud 9 лет назад 0
(1) Знаете ли вы о какой-либо проблеме с моим решением `grep" [s] nappr "? (2) До тех пор, пока мы говорим о процессах убийства, кого волнует, включены ли уже не функционирующие процессы? Убийство несуществующего процесса - бесполезно. Scott 9 лет назад 0
Я понимаю, что мы здесь не по теме. Мне нравится ваше решение для подгузников! Но мне нужно исключить несуществующие, потому что я действительно хочу знать, есть ли живой процесс там (в этом случае остановитесь сейчас!) Или просто что-то, что умирает. И мне нужно не только исключить вызов grep, но и исключить работающий экземпляр самого скрипта ($$) и, возможно, родитель, вызвавший его ($ PPID). gogoud 9 лет назад 0
+1 за хороший ответ (но ... изобрел трюк [x] 20 лет назад? Или просто прочитал об этом в FAQ по Unix?;)) Olivier Dulac 9 лет назад 0
Я предпочитаю этот трюк `PS топор | egrep "[/] (PID | $ )" `или` ps ax | grep "[/] $ " `, чтобы избежать трехкратной глупости` grep $ | grep -v grep`. daniel Azuelos 9 лет назад 0
8
JakeGould

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

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

sudo pkill snappr 

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

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

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

Конечно, если вы пытаетесь убить процесс, который вы запустили (как указано в вопросе), если он не установлен, вы владеете процессом и вам не нужен `sudo`. И вам не следует использовать `sudo`, если вам это не нужно. Scott 9 лет назад 1
Скорее всего - процесс на самом деле не существует, `grep` соответствует самому себе. Sobrique 9 лет назад 2
используйте `killall` вместо` pkill`, так как по умолчанию `pkill` перебивает. Hongxu Chen 9 лет назад 0

Похожие вопросы