Почему pidof и pgrep ведут себя по-разному?

8

У меня есть сценарий /etc/init.d/myserviceинициализации для инициализации службы, как это:

...
start() {
  ...
  daemon /usr/sbin/myservice
  ...
}

stop() {
  ...
  pgrep myservice
  pidof myservice
  ps -ef | grep myservice
  ...
}

И когда я пытаюсь остановить службу, это вывод:

10000 10001
10000
root      10000     1  0 09:52 ?        00:00:02 /usr/sbin/myservice
root      9791   9788  0 10:06 pts/1    00:00:00 /bin/sh /sbin/service myservice stop
root      10001  9791  1 10:06 pts/1    00:00:00 /bin/sh /etc/init.d/myservice stop 
root      9805   9796  0 10:06 pts/1    00:00:00 grep myservice

Это ожидается? Почему pidofвозвращается только правильный PID службы, которую я хочу остановить, и pgrepвозвращает PID службы и PID сценария инициализации? Могу ли я рассчитывать на то, pidofчто всегда будет игнорировать PID из сценария инициализации?

Pigueiras
источник

Ответы:

7

pidof = найти идентификатор процесса работающей программы

Pidof находит идентификаторы процесса (pids) названных программ. Он выводит эти идентификаторы на стандартный вывод. Эта программа используется в некоторых системах, используемых в сценариях изменения уровня выполнения, особенно когда система имеет структуру r, подобную System-V.

sysadmin@codewarden:~$ pidof apache2
5098 5095 5094 5092

pgrep = поиск или сигнализация процессов на основе имени и других атрибутов, pgrep просматривает запущенные в данный момент процессы и перечисляет идентификаторы процессов, которые соответствуют критериям выбора.

sysadmin@codewarden:~$ pgrep apache2
5092
5094
5095
5098

pgrep, (p) = process, grep= grep печатает совпадающие строки

Хотите узнать больше о pgrep & pidof? Просто запустите в терминале, как

# man pidof
# man pgrep
Бабин Лонстон
источник
1
Ага, вот почему pidofне возвращается 10001, потому что программы shнет?
Pigueiras
да, вы правы
Бабин Лонстон
0

Я думаю, что вы не должны полагаться pidof, это может привести к сбою вашей программы. Простой пример с supervisordпрограммой:

% cuonglm at ~
% ps -ef | grep supervisord
root      8512     1  0 16:53 ?        00:00:00 /usr/bin/python /usr/bin/supervisord
cuonglm   8584  7688  0 17:00 pts/0    00:00:00 grep --color=auto supervisord
% cuonglm at ~
% pidof supervisord
% cuonglm at ~
% 

Вы можете видеть, что supervisordфактически вызывается интерпретатором Python, вызывает pidofсбой:

#! /usr/bin/python                                                            
# EASY-INSTALL-ENTRY-SCRIPT: 'supervisor==3.0a8','console_scripts','supervisord'
__requires__ = 'supervisor==3.0a8'                                            
import sys                                                                    
from pkg_resources import load_entry_point                                    

if __name__ == '__main__':                                                    
    sys.exit(                                                                 
        load_entry_point('supervisor==3.0a8', 'console_scripts', 'supervisord')()
    )
cuonglm
источник
Но в этом случае я могу на это положиться, нет? Я не использую интерпретатор для выполнения программы (это исполняемый двоичный файл).
Pigueiras
Конечно. Но я думаю, что хороший способ - это использовать killproc. Почему вы не используете это, в то время как вы использовали daemonв startфункции?
cuonglm
Поскольку я хочу получить PID для уничтожения дочерних элементов процесса, я использовал его killprocдля уничтожения самого процесса.
Pigueiras
Почему ты должен это делать? если ты убьешь parent process, его child processволя тоже умерла.
cuonglm
Нет, я так не думаю: stackoverflow.com/questions/8533377/…
Pigueiras
0

Команда pidofигнорирует сценарии, если вы не включите эту -xопцию. Кроме того, наиболее безопасно включить полный путь в команду pidof, как в:

killme=$(pidof -x /usr/bin/supervisord)
      *instead of*
killme=$(pidof -x supervisord)

это минимизирует шансы на совпадение с каким-либо другим процессом.

Джон Хэсколл
источник