Мне нужна независимая от платформы (Linux / Unix | OSX) команда shell / bash, которая определит, запущен ли конкретный процесс. например mysqld
, httpd
... Каков самый простой способ / команда сделать это?
Мне нужна независимая от платформы (Linux / Unix | OSX) команда shell / bash, которая определит, запущен ли конкретный процесс. например mysqld
, httpd
... Каков самый простой способ / команда сделать это?
Ответы:
Хотя pidof
и pgrep
являются отличными инструментами для определения того, что работает, они, к сожалению, недоступны в некоторых операционных системах. Определенным отказоустойчивым было бы использование следующего:ps cax | grep command
Вывод в Gentoo Linux:
14484? S 0:00 apache2 14667? S 0:00 apache2 19620? Сл 0:00 apache2 21132? СС 0:04 apache2
Вывод в OS X:
42582 ?? Z 0: 00.00 (клиент) 46529 ?? Z 0: 00.00 (клиент) 46539 ?? Z 0: 00.00 (клиент) 46547 ?? Z 0: 00.00 (клиент) 46586 ?? Z 0: 00.00 (клиент) 46594 ?? Z 0: 00.00 (клиент)
И в 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 httpd | grep -o '^ [] * [0-9] *'
Чей вывод одинаков в Linux и OS X:
3519 3521 3523 3524
Результатом следующего является пустая строка, что делает этот подход безопасным для неработающих процессов:
эхо 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
для проверки полного пути, где это возможно.
Ссылки:
grep
будет также найти сам работает (например , ps cax | grep randomname
всегда возвращает 0 , потому что grep
находки grep randomname
(надеюсь , это понятно ...) Одним из способов исправить это добавить квадратные скобки вокруг первой буквы имени процесса, например. ps cax | grep [r]andomname
.
ps cax | rev | cut -f1 -d' ' | rev
будет отображать только столбец имени для облегчения анализа.
ps cax
может не выводить имя команды полностью. Например, он печатает «хром-браузер» вместо «хром-браузер».
Поиск процесса путем попытки распознать какой-то образ на аргументах процесса (например, pgrep "mysqld"
) - это стратегия, которая рано или поздно обречена на провал. Что делать, если у вас работает два mysqld? Забудьте об этом подходе. Вы МОЖЕТЕ сделать это временно, и это МОЖЕТ работать в течение года или двух, но затем происходит что-то, о чем вы не думали.
Только идентификатор процесса (pid) действительно уникален.
Всегда сохраняйте pid, когда запускаете что-то в фоновом режиме. В Bash это можно сделать с помощью $!
переменной Bash. Поступив так, вы избавите себя от ТАКИХ проблем.
Итак, теперь возникает вопрос, как узнать, запущен ли pid.
Просто сделайте:
ps -o pid = -p <pid>
Это POSIX и, следовательно, переносимый. Он вернет сам pid, если процесс запущен, или ничего не вернет, если процесс не запущен. Строго говоря, команда вернет один столбец,pid
но, поскольку мы дали ему пустой заголовок (материал, непосредственно предшествующий знаку равенства), и это единственный запрошенный столбец, команда ps вообще не будет использовать заголовок. Это то, что мы хотим, потому что это упрощает синтаксический анализ.
Это будет работать в Linux, BSD, Solaris и т. Д.
Другой способ - проверить значение выхода из приведенной выше ps
команды. Он должен быть равен нулю, если процесс запущен, и отличному от нуля, если нет. Спецификация POSIX говорит, что ps
должно выйти> 0, если произошла ошибка, но мне неясно, что составляет «ошибку». Поэтому я лично не использую эту стратегию, хотя уверен, что она также будет работать на всех платформах Unix / Linux.
grep <sometext>
чтобы найти данный процесс, то вы сделали что-то не так, когда начали процесс, ИМХО. Я исхожу из вопроса ОП, что он действительно контролирует запуск процесса.
В большинстве дистрибутивов Linux вы можете использовать pidof
(8).
Он напечатает идентификаторы всех запущенных экземпляров указанных процессов или ничего, если нет запущенных экземпляров.
Например, в моей системе (у меня четыре экземпляра bash
и один экземпляр remmina
запущен):
$ pidof bash remmina
6148 6147 6144 5603 21598
В других Unices pgrep
или в комбинации ps
и grep
достигнет того же самого, как справедливо указывали другие.
pidof httpd
отлично работает на Red Hat 5. Но на моем Red Hat 4 pidof
нет :-(
Это должно работать на большинстве разновидностей Unix, BSD и Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Проверено на:
PATH=...
]ps
. Чтобы избежать второго, grep
я предлагаю:ps aux | grep [h]ttpd
grep
.
Самый простой способ - использовать 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
ps cax
устраняет необходимость использования grep -v
. Так, например, вы можете использовать: ps cax | grep java > /dev/null || echo "Java not running"
.
Небольшое дополнение: если вы добавите -c
флаг в ps, вам не нужно grep -v
впоследствии удалять строку, содержащую процесс grep с . Т.е.
ps acux | grep cron
это все, что вам нужно для набора текста в системе bsd-ish (включая MacOSX). Вы можете оставить -u
Если вам нужно меньше информации, .
В системе, где генетика собственной ps
команды указывает обратно на SysV, вы должны использовать
ps -e |grep cron
или
ps -el |grep cron
для списка, содержащего не только идентификатор процесса и имя процесса. Конечно, вы можете выбрать определенные поля для печати, используя эту -o <field,field,...>
опцию.
Собрав вместе различные предложения, самая чистая версия, которую я смог придумать (без ненадежного 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"
Я использую, pgrep -l httpd
но не уверен, что он присутствует на какой-либо платформе ...
Кто может подтвердить на OSX?
pidof
? Хорошо, ты сделал. Спасибо. Так что мы должны найти что-нибудь еще, работающее на OSX ... Ваше основное ps|grep
может быть единственным решением ;-)
Когда вы его запустите, его 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
инструкции.
Такой подход можно использовать в случае, если команды ps, pidof и rest недоступны. Лично я очень часто использую procfs в своих инструментах / скриптах / программах.
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
Небольшое объяснение того, что происходит:
Это печатает количество процессов, чье базовое имя - "Chrome-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"
Вот моя версия. Особенности:
сценарий:
#!/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
Ни один из ответов у меня не сработал, поэтому вот мой:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Пояснение:
|tr -d '\n'
Это удаляет возврат каретки, созданный терминалом. Остальное можно объяснить в этом посте.
Следующая функция оболочки, основанная только на стандартных командах и параметрах POSIX, должна работать в большинстве (если не вообще) систем Unix и Linux. :
isPidRunning() {
cmd=`
PATH=\`getconf PATH\` export PATH
ps -e -o pid= -o comm= |
awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
`
[ -n "$cmd" ] &&
printf "%s is running\n%s\n\n" "$1" "$cmd" ||
printf "%s is not running\n\n" $1
[ -n "$cmd" ]
}
$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd
$ isPidRunning ksh
ksh is running
5230 ksh
$ isPidRunning bash
bash is not running
Обратите внимание, что он задыхается при передаче сомнительного имени команды «0]», а также не сможет идентифицировать процессы, в именах которых есть пробелы.
Также обратите внимание, что наиболее популярное и принятое решение требует непереносимых ps
опций и безвозмездно использует оболочку, которая, несмотря на ее популярность, не гарантированно присутствует на каждой машине Unix / Linux ( bash
)
$ isPidRunning 0]
выводит, например, «0] выполняется 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [migration / 0] 35 [watchdog / 0]» здесь.