Проверьте, запущен ли процесс Mac с использованием Bash по имени процесса - PullRequest
19 голосов
/ 30 ноября 2009

Как проверить, выполняется ли процесс в Mac OS X, используя имя процесса в скрипте Bash?

Я пытаюсь написать сценарий Bash, который перезапустит процесс, если он остановился, но ничего не сделает, если он все еще работает.

Ответы [ 10 ]

29 голосов
/ 30 ноября 2009

Разбор этого:

ps aux | grep [-i] $ProcessName | wc -l

... это, вероятно, ваш лучший выбор. Вот короткий скрипт, который делает то, что вам нужно:

#!/bin/bash
PROCESS=myapp
number=$(ps aux | grep $PROCESS | wc -l)

if [ $number -gt 0 ]
    then
        echo Running;
fi

РЕДАКТИРОВАТЬ: Я изначально включил флаг -i в grep, чтобы сделать его без учета регистра; Я сделал это, потому что пример программы, которую я пробовал, был python, который в Mac OS X запускается как Python - если вы точно знаете случай вашего приложения, -i не требуется.

Преимущество этого подхода в том, что он масштабируется вместе с вами - в будущем, если вам нужно убедиться, что, скажем, пять экземпляров вашего приложения запущены, вы уже рассчитываете. Единственное предостережение в том, что, если другое приложение имеет имя вашей программы в командной строке, оно может появиться - регулярные выражения grep решат эту проблему, если вы будете хитрыми (и столкнетесь с этим).

Исследуйте справочные страницы Дарвина для ps, grep и wc.

25 голосов
/ 08 октября 2013

Более короткое решение:

if pgrep $PROCESS_NAME; then
    echo 'Running';
fi

Пояснение:

pgrep завершается с 0, если запущен процесс, соответствующий $PROCESS_NAME, в противном случае он существует с 1.
if проверяет код выхода pgrep, а что касается кодов выхода, 0 - это успех.

11 голосов
/ 30 ноября 2009

Другой способ - использовать (злоупотреблять) параметр -d команды killall. Опции -d на самом деле не убивают процесс, а вместо этого выводят, что будет сделано. Он также выйдет со статусом 0, если найдет соответствующий процесс, или 1, если не найдет. Собираем это вместе:

#!/bin/bash
`/usr/bin/killall -d "$1" &> /dev/null`
let "RUNNING = ! $?"     # this simply does a boolean 'not' on the return code
echo $RUNNING

Чтобы отдать должное, где это необходимо, я изначально извлек эту технику из сценария в программе установки iTunes.

5 голосов
/ 01 августа 2011

Эта простая команда сделает свое дело. Квадратные скобки вокруг имени процесса не позволяют отображать команду grep в списке процессов. Обратите внимание, что после запятой нет пробела. Могут возникнуть некоторые проблемы с переносимостью, поскольку ps в некоторых системах Unix может потребовать тире перед параметрами:

ps axo pid,command | grep "[S]kype"

Преимущество заключается в том, что вы можете использовать результаты в выражении if, например: '

if [[ ! $(ps axo pid,command | grep "[i]Tunes.app") ]]; then
    open -a iTunes
fi

Или, если вы предпочитаете этот стиль:

[[ ! $(ps axo pid,command | grep "[S]kype") ]] && open -a Skype  || echo "Skype is up"

Еще одним преимуществом является то, что вы можете получить pid, добавив канал в awk '{print $ 1}'.

echo "iTunes pid: $(ps axo pid,command | grep "[i]Tunes.app" | awk '{print $1}')"
3 голосов
/ 02 июля 2014

Вы можете использовать killall или kill, в зависимости от того, пытаетесь ли вы найти задачу по PID или по имени.

По имени:

if ! killall -s -0 $PROCESS_NAME >/dev/null 2>&1; then
  # Restart failed app, or do whatever you need to prepare for starting the app.
else
  at -f $0 +30seconds # If you don't have this on cron, you can use /usr/bin/at
fi

По PID:

if ! kill -0 $PID 2>/dev/null; then
  # Restart app, do the needful.
else
  at -f $0 +30seconds
fi

Если вы посмотрите Руководство по OSX , вы увидите другой набор команд управления процессами; поскольку это не ядро ​​Linux, имеет смысл, что они будут управлять процессами по-другому.

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/killall.1.html

Пример вывода с моего терминала (конечно, вычеркивая имя пользователя и хоста):

user@localhost:~$ kill -0 782 # This was my old, stale SSH Agent.
bash: kill: (782) - No such process
user@localhost:~$ echo $?
1

user@localhost:~$ kill -0 813 # This is my new SSH agent, I only just created.
user@localhost:~$ echo $?
0

Код возврата из kill -0 всегда будет безопасным способом проверять, запущен ли процесс, потому что -0 не отправляет сигнал, который когда-либо будет обработан приложением. Это не убьет приложение, а «kill» называется только «kill», потому что обычно оно используется для остановки приложения.

Когда вы посмотрите на интерфейсы, которые он использует в источнике, вы увидите, что он на самом деле напрямую взаимодействует с таблицей процессов (а не очищает потенциально загруженный вывод из ps) и просто отправляет сигнал приложению. Некоторые сигналы указывают на то, что приложение должно завершать работу или останавливаться, в то время как другие сигналы говорят ему перезапустить службы, либо перечитать конфигурацию, либо заново открыть дескрипторы файлов, чтобы записывать файлы, которые были недавно повернуты. Существует множество вещей, которые «kill» и «killall» могут делать, которые не завершают работу приложения, и регулярно используются для простой отправки сигнала приложению.

2 голосов
/ 20 октября 2010

Мне не хватает репутации, чтобы комментировать ответ killall выше, но есть killall -s для того, чтобы сделать это без отправки каких-либо сигналов:

killall -s "$PROCESSNAME" &> /dev/null
if [ $? -eq 0 ]; then
    echo "$PROCESSNAME is running"
    # if you also need the PID:
    PID=`killall -s "$PROCESSNAME" | awk '{print $3}'`
    echo "it's PID is $PID"
fi
1 голос
/ 24 февраля 2013

Я расширил сценарий pidof, найденный в сети, на использование регулярных выражений (обычно подстрок) и без учета регистра

#!/bin/sh
ps axc  |awk "BEGIN{ n=tolower(\"$1\")}\
    tolower(\$5) ~n {print  \$1}";

просто создайте скрипт с именем "pidof" с этим содержимым и поместите его в свой путь, т. Е. В один из каталогов в

echo $PATH

и сделать его исполняемым (возможно, используя sudo)

chmod 755 /usr/local/bin/pidof

и используйте это так, конечно же

kill -9 `pidof pyth`
0 голосов
/ 21 февраля 2014

Возможно, слишком поздно для ОП, но это может помочь другим, кто найдет эту тему.

Следующая модификация вышеприведенной темы amrox хорошо работает для перезапуска приложений на моей OS X:

killall -d TextEdit &> /dev/null && killall TextEdit &> /dev/null; open -a TextEdit

Я использую следующий AppleScript для обновления и перезапуска демонов:

tell application "System Events" to set pwd to POSIX path of container of (path to me)
do shell script "launchctl unload -w /Library/LaunchDaemons/time-test.plist; cp -f " & quoted form of pwd & "/time-test.plist /Library/LaunchDaemons; launchctl load -w /Library/LaunchDaemons/time-test.plist" with administrator privileges

Предполагается, что исходный или обновленный файл plist находится в том же каталоге, что и AppleScript.

0 голосов
/ 01 декабря 2009

Это точно!

pgrep, pkill и pfind для OpenBSD и Darwin (Mac OS X)

http://proctools.sourceforge.net

(также доступно через MacPorts: информация о порте proctools)

pidof by nightproductions.net

0 голосов
/ 30 ноября 2009

у Mac есть пидоф? ...

if pidof $processname >/dev/null ; then echo $processname is running ; fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...