it-roy-ru.com

Linux/Unix команда, чтобы определить, запущен ли процесс?

Мне нужна независимая от платформы (Linux/Unix | OSX) команда Shell/bash, которая определит, запущен ли конкретный процесс. например mysqld, httpd... Какой самый простой способ/команда для этого?

86
Highway of Life

Хотя pidof и pgrep являются отличными инструментами для определения того, что работает, они, к сожалению, недоступны в некоторых операционных системах. Определенным отказоустойчивым было бы использовать следующее: ps cax | grep command

Вывод в Gentoo Linux:

 14484? S 0:00 Apache2 
 14667? S 0:00 Apache2 
 19620? Sl 0:00 Apache2 
 21132? Сс 0:04 Апач2 

Вывод на OS X:

 42582 ?? Z 0: 00,00 (smbclient) 
 46529 ?? Z 0: 00,00 (smbclient) 
 46539 ?? Z 0: 00,00 (smbclient) 
 46547 ?? Z 0: 00,00 (smbclient) 
 46586 ?? Z 0: 00,00 (smbclient) 
 46594 ?? Z 0: 00,00 (smbclient) 

Как в Linux, так и в OS X, grep возвращает код выхода, поэтому легко проверить, был ли найден процесс:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

Более того, если вам нужен список PID, вы также можете легко их найти:

ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'

Этот подход подходит для написания простого теста с пустой строкой, а затем итерации по обнаруженным идентификаторам PID.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi

Вы можете проверить это, сохранив его в файл (с именем «running») с разрешениями на выполнение (chmod + x running) и выполнив его с параметром: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

ВНИМАНИЕ !!!

Помните, что вы просто анализируете вывод ps ax, что означает, что, как видно из вывода Linux, он не просто совпадает с процессами, но и с аргументами, передаваемыми этой программе. Я настоятельно рекомендую быть максимально точным при использовании этого метода (например, ./running "mysql" также будет соответствовать процессам mysqld). Я настоятельно рекомендую использовать which для проверки полного пути, где это возможно.


Рекомендации:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

158
Caleb Gray

Вы ДОЛЖНЫ знать PID!

Поиск процесса путем попытки какого-либо распознавания образов по аргументам процесса (например, pgrep "mysqld") - это стратегия, которая рано или поздно обречена на неудачу. Что делать, если у вас работает два mysqld? Забудь о таком подходе. Вы МОЖЕТЕ сделать это правильно временно, и МОЖЕТ работать в течение года или двух, но затем происходит что-то, о чем вы даже не думали.

Только идентификатор процесса (pid) действительно уникален.

Всегда сохраняйте pid при запуске чего-либо в фоновом режиме. В Bash это можно сделать с помощью переменной $! Bash. Сделав это, вы избавите себя SO от многих проблем.

Как определить, запущен ли процесс (по pid)

Так что теперь возникает вопрос, как узнать, работает ли pid.

Просто сделайте:

 ps -o pid = -p <pid> 

Это POSIX и, следовательно, портативный. Он вернет сам pid, если процесс запущен, или ничего не вернет, если процесс не запущен. Строго говоря, команда вернет один столбец pid, но так как мы дали пустой заголовок заголовка (материал, непосредственно предшествующий знаку равенства), и это единственный запрошенный столбец, команда ps вообще не будет использовать заголовок , Что мы и хотим, потому что это облегчает анализ.

Это будет работать на Linux, BSD, Solaris и т.д.

Другой стратегией будет проверка значения выхода из приведенной выше команды ps. Он должен быть нулевым, если процесс запущен, и ненулевым, если это не так. Спецификация POSIX говорит, что ps должен выйти> 0, если произошла ошибка, но мне неясно, что представляет собой «ошибка». Поэтому я лично не использую эту стратегию, хотя я почти уверен, что она будет работать на всех платформах Unix/Linux.

24
peterh

В большинстве дистрибутивов Linux вы можете использовать pidof (8).

Он напечатает идентификаторы всех запущенных экземпляров указанных процессов или ничего, если нет запущенных экземпляров.

Например, в моей системе (у меня есть четыре экземпляра bash и один запущенный экземпляр remmina):

$ pidof bash remmina
6148 6147 6144 5603 21598

В других Unix pgrep или комбинация ps и grep позволят достичь того же, что справедливо указали другие.

13
Frédéric Hamidi

Самый простой способ - использовать ps и grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi

Если у вашей команды есть некоторые аргументы команды, то вы также можете поставить больше 'grep cmd_arg1' после 'grep $ command', чтобы отфильтровать другие возможные процессы, которые вас не интересуют.

Пример: показать мне, если какой-либо процесс Java с предоставленным аргументом: 

-Djava.util.logging.config.file = logging.properties

бежит

ps ax | grep -v grep | grep Java | grep Java.util.logging.config.file=logging.properties | wc -l
6
Pawel Solarski

Это должно работать на большинстве разновидностей Unix, BSD и Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Проверено на:

  • SunOS 5.10 [Отсюда PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Дарвин 11.2.0
  • FreeBSD 9.0-STABLE
  • Red Hat Enterprise Linux ES выпуск 4 
  • Red Hat Enterprise Linux Server, выпуск 5
6
Johnsyweb

Объединяя различные предложения, самая чистая версия, которую я смог придумать (без ненадежного grep, который запускает части слов):

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

kill -0 не убивает процесс, но проверяет, существует ли он, а затем возвращает true, если у вас нет pidof в вашей системе, сохраните pid при запуске процесса:

$ mysql &
$ echo $! > pid_stored

тогда в сценарии:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
5
gletscher

Просто незначительное добавление: если вы добавите флаг -c в ps, вам не нужно удалять строку, содержащую процесс grep с grep -v впоследствии. То есть.

ps acux | grep cron

это все, что нужно для набора текста в системе bsd-ish (включая MacOSX). Вы можете оставить -u, если вам нужно меньше информации.

В системе, где генетика нативной команды ps указывает на SysV, вы должны использовать

ps -e |grep cron

или же

ps -el |grep cron 

для списка, содержащего больше, чем просто pid и имя процесса. Конечно, вы можете выбрать конкретные поля для печати, используя опцию -o <field,field,...>.

5
Tatjana Heuser

Я использую pgrep -l httpd, но не уверен, что он присутствует на любой платформе ... 
Кто может подтвердить на OSX?

3
olibre

Вы должны знать PID вашего процесса.

Когда вы запустите его, его PID будет записан в переменной $!. Сохраните этот PID в файл.

Затем вам нужно будет проверить, соответствует ли этот PID запущенному процессу. Вот полный скелетный скрипт:

FILE="/tmp/myapp.pid"

if [ -f $FILE ];
then
   PID=$(cat $FILE)
else
   PID=1
fi

ps -o pid= -p $PID
if [ $? -eq 0 ]; then
  echo "Process already running."  
else
  echo "Starting process."
  run_my_app &
  echo $! > $FILE
fi

На основании ответа из peterh. Хитрость в том, чтобы знать, работает ли данный PID, заключается в инструкции ps -o pid= -p $PID.

1
icarito

Ни один из ответов не сработал для меня, так вот мой:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

Объяснение:

|tr -d '\n'

Это удаляет возврат каретки, созданный терминалом. Остальное можно объяснить этим постом.

0
Jeff Luyet

Этот подход можно использовать в том случае, если команды 'ps', 'pidof' и rest недоступны. Я лично использую procfs очень часто в моих инструментах/скриптах/программах.

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

Небольшое объяснение того, что происходит:

  1. -m1 - остановить процесс при первом совпадении
  2. "mysqld $ | httpd $" - grep будет соответствовать строкам, завершившимся на mysqld OR httpd
  3. / proc/[0-9] * - bash будет соответствовать строке, начинающейся с любого числа
  4. вырезать - просто разделить вывод разделителем '/' и извлечь поле 3
0
Tom Lime

Это печатает количество процессов, чье базовое имя - "chromium-browser":

ps -e -o args= | awk 'BEGIN{c=0}{
 if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
 if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"

Если при этом выводится «0», процесс не выполняется. Команда предполагает, что путь процесса не содержит пробелов. Я не проверял это с приостановленными процессами или процессами зомби.

Протестировано с использованием gwak в качестве альтернативы awk в Linux.

Вот более универсальное решение с примером использования:

#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
 local quiet=1;
 shift
else
 local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
 name=$2
 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
 if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}

process='chromium-browser'

printf "Process \"${process}\" is "
if isProcessRunning -q "$process" 
 then printf "running.\n"
 else printf "not running.\n"; fi

printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
0
jarno

Вот моя версия. Особенности:

  • проверяет точное имя программы (первый аргумент функции). поиск "mysql" не будет соответствовать запуску "mysqld"
  • ищет аргументы программы (второй аргумент функции)

сценарий:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning Java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi
0
Raigedas