Как вы проверяете, выполняется ли процесс в Mac OS X с помощью имени процесса в Bash script?
Я пытаюсь написать Bash script, который перезапустит процесс, если он остановился, но ничего не сделает, если он все еще запущен.
Как вы проверяете, выполняется ли процесс в Mac OS X с помощью имени процесса в Bash script?
Я пытаюсь написать Bash script, который перезапустит процесс, если он остановился, но ничего не сделает, если он все еще запущен.
Разбор этого:
ps aux | grep -v grep | grep -c [-i] $ProcessName
... вероятно, это лучшая ставка для вас.
ps aux
перечисляет все запущенные в настоящее время процессы, включая сам скрипт Bash, который анализируется grep -v grep
по совету Джейкоба (в комментариях), а grep -c [-i] $ProcessName
возвращает необязательное без учета регистра целое число процессов с целочисленным возвратом, предложенным Себастьяном..
Вот короткий скрипт, который делает то, что вам нужно:
#!/bin/bash
PROCESS=myapp
number=$(ps aux | grep -v grep | grep -ci $ProcessName)
if [ $number -gt 0 ]
then
echo Running;
fi
ОБНОВЛЕНИЕ: Я изначально включил флаг -i
в grep
, чтобы сделать его нечувствительным к регистру; Я сделал это, потому что пример программы, которую я пробовал, был python
, который в Mac OS X работает как Python
- если вы точно знаете пример своего приложения, -i
не нужен.
Преимущество этого подхода в том, что он масштабируется вместе с вами - в будущем, если вам нужно убедиться, что, скажем, пять экземпляров вашего приложения запущены, вы уже рассчитываете. Единственное предостережение: если другое приложение имеет имя вашей программы в командной строке, оно может появиться - регулярные выражения в grep
решат эту проблему, если вы лукавите (и столкнетесь с этим).
Более короткое решение:
if pgrep $PROCESS_NAME; then
echo 'Running';
fi
Пояснение:
pgrep
выходит с 0, если выполняется процесс, соответствующий $PROCESS_NAME
, в противном случае он существует с 1. if
проверяет код выхода pgrep
, и, поскольку коды выхода идут, 0 успешно.
Другой способ - использовать (злоупотреблять?) опцию -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
Чтобы отдать должное, я изначально вытащил эту технику из script в установщик iTunes.
Эта простая команда сделает трюк. Скобки вокруг имени процесса не позволяют команде 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}')"
Вы можете использовать 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
Образец вывода из моего терминала (конечно, вычеркивание пользователя и имени хоста):
[email protected]:~$ kill -0 782 # This was my old, stale SSH Agent.
bash: kill: (782) - No such process
[email protected]:~$ echo $?
1
[email protected]:~$ kill -0 813 # This is my new SSH agent, I only just created.
[email protected]:~$ echo $?
0
Код возврата из kill -0 всегда приведет к безопасному способу проверить, запущен ли процесс, поскольку -0 не посылает сигнал, который когда-либо будет обрабатываться приложением. Он не будет убивать приложение, а "kill" называется "kill", потому что он обычно используется для остановки приложения.
Когда вы смотрите на интерфейсы, которые он использует в источнике, вы увидите, что он фактически взаимодействует с таблицей процессов напрямую (а не grepping потенциально загружаемого вывода из ps) и просто посылает сигнал в приложение. Некоторые сигналы указывают, что приложение должно быть остановлено или остановлено, в то время как другие сигналы говорят ему перезапустить службы или перечитать конфигурацию или повторно открыть файловые дескрипторы для файлов журналов, которые были недавно повернуты. Существует множество вещей, которые могут "убить" и "убить", что не прерывает приложение, и оно регулярно используется для простого отправки сигнала в приложение.
Мне не хватает репутации, чтобы прокомментировать ответ 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 PID is $PID"
fi
Я добавил pidof script, найденный в сети, чтобы использовать регулярные выражения (обычно подстроки) и нечувствителен к регистру
#!/bin/sh
ps axc |awk "BEGIN{ n=tolower(\"$1\")}\
tolower(\$5) ~n {print \$1}";
просто создайте script с именем "pidof" с этим контентом и поместите его в свой путь, т.е. в один из каналов в
echo $PATH
и сделать его исполняемым (возможно, используя sudo)
chmod 755 /usr/local/bin/pidof
и использовать его, как это, конечно
kill -9 `pidof pyth`
У Mac есть pidof?...
if pidof $processname >/dev/null ; then echo $processname is running ; fi
Это точно!
pgrep, pkill и pfind для OpenBSD и Darwin (Mac OS X)
http://proctools.sourceforge.net
(также доступно через MacPorts: информация о профилях портов proctools)
pidof by nightproductions.net
Возможно, слишком поздно для OP, но это может помочь другим пользователям найти этот поток.
Следующая модификация темы amrox выше хорошо работает для перезапуска приложений на моей ОС 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.