Bash способ проверить, если процесс уже работает в фоновом режиме (и пропустить повторное выполнение на основании этого)?


11

Могу ли я создать командную строку bash, которая запускает определенную команду, только если процесс еще не запущен (в фоновом режиме)?

Как проверить *, если команда уже запущена?

(так что я могу добавить следующую команду с &&промежуточным между ними, чтобы следующая выполнялась, только если первая верна).

*: проверить, определить, обнаружить, узнать


3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Рахул Патил

1
@RahulPatil вы можете использовать просто pgrep "process_name"вместоps | grep | grep
спешить

хм, я забыл это ..: D
Рахул Патил

1
Почему бы вам не использовать файл блокировки, а при втором запуске он будет запускаться только после исчезновения файла блокировки.
BitsOfNix

лучший способ проверить, существует ли процесс: stackoverflow.com/questions/3043978/…
Тревор Бойд Смит

Ответы:


6

3

Я использовал эту технику время от времени:

$ pgrep <process name> || <process name>

До pgrepэтого раньше делали так:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

пример

Немного с этим [p]делает так, что в результате grepон не найдет себя.

$ ps -eaf | grep -q [s]leep || sleep 10

2

Это может быть сложно, потому что вы можете иметь отдельные экземпляры одного и того же процесса, которые живут независимо. Например, серверы, прослушивающие разные порты, или службы, работающие под разными пользователями. Чтобы различать эти экземпляры, необходимо назначить каждому из них уникальный тег. Тэг часто является файлом, но это может быть локальный сокет в абстрактном пространстве имен, порт TCP и т. Д. - подойдет любой уникальный идентификатор. Когда тег является файлом, это может быть обычный файл, содержащий идентификатор процесса (pid-файл), или именованный канал или сокет, который прослушивает файл, и т. Д. В идеале тег является конечной точкой связи, которая позволяет клиентам подключаться к этому процессу.

Каждый из этих различных типов тегов по-разному проверяет, работает ли искомый экземпляр. Например, с локальным файловым сокетом попробуйте подключиться к нему и запустить процесс, если на этом сокете нет процесса, прослушивающего. Если тег является pid-файлом, проверьте, существует ли процесс с этим идентификатором процесса, но имейте в виду, что это хрупкий процесс, поскольку, если процесс завершился, может быть не связанный процесс, который повторно использовал свой идентификатор. Помните, что если два клиента попытаются достичь процесса за короткий промежуток времени, они могут обнаружить, что процесс не существует, и оба попытаются запустить его; должная защита от этого состояния гонки может быть сложно.

Управлять экземплярами легче, когда все они запускаются одним и тем же процессом супервизора, и этот процесс супервизора обнаруживает, когда экземпляры умирают, и реагирует соответствующим образом. Многие сервисные программы мониторинга могут это сделать.

Если программа не отвечает на известной конечной точке связи и не управляется программой супервизора, тегом бедного человека является pidfile: файл, содержащий идентификатор процесса. Когда вы запустите процесс, запишите pid в файл с заранее заданным именем. Когда вам нужно, чтобы процесс существовал, прочитайте pid-файл и посмотрите, есть ли процесс с этим pid. Когда вы завершите процесс, сотрите файл pid. Наиболее существенная проблема с неконтролируемым pid-файлом заключается в том, что если процесс умирает, его pid может быть повторно использован каким-то не связанным процессом. Вы должны по крайней мере проверить имя процесса или исполняемый файл процесса, чтобы убедиться, что вы говорите с правильным процессом. Многие варианты Unix имеют команду pgrep :pgrep SOMENAME перечисляет процессы, чье имя содержит SOMENAME в качестве подстроки, с дополнительными опциями для ограничения для конкретного пользователя, для запроса точного соответствия, для изменения того, какое из нескольких возможных понятий «имя процесса» используется, и т. д.


1

Вы можете использовать этот подход:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi

1

Другие опции:

  • pgrep -xq processname
    • Соответствует только первым 15 символам в GNU / Linux
    • Не включает в себя предков на OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Соответствует только первым 15 символам в GNU / Linux
    • sed 's|.*/||' удаляет части dirname в OS X

В GNU / Linux ps -o commусекает имена команд до 15 символов и pgrepи ps -Cсоответствуют только первые 15 символов.

ps -C (сопоставлять имена команд) не поддерживается в OS X.

В OS X ps -o commпечатает абсолютные пути команд и ps -co commпечатает только имена команд. В GNU ps -o commвыводит только имена команд и -cимеет другое значение.

Pgrep в OS X не включает процессы-предки (такие как bash, Terminal или launchd) без них -a. GNU pgrep включает их по умолчанию и не поддерживает -a.

grep -xи pgrep -xне подразумевайте -F, поэтому используйте, -Fxесли имя процесса может содержать символы регулярного выражения.


-C также недоступен в моем cygwin :)
n611x007

1

Извините, но все эти решения не поддерживают contab, так как одна и та же командная строка будет появляться дважды в результате 'ps'.

Так вот мое:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file

О чем ты сожалеешь? Что такое контаб? Вы имеете в виду проверку изнутри cronработы?
Антон

0

С баш

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Примечание: - удалить, echoесли вывод выглядит нормально.


0

Я объясню случай, когда вы запускаете команду в beckgreoud. "$!" сохранить PID последнего фонового процесса. Таким образом, вы можете использовать его, чтобы найти его в таблицах процессов, следуя ответам выше:

sleep 4 &
ps -ef | grep -w  $!  ...

Встроенная команда "jobs" - попробуйте это:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Относительно опции "&&"

Вместо && используйте команду wait. В следующем примере myproc2 не будет работать до тех пор, пока не завершится myproc1:

myproc1 &
wait
myproc2

0

Получите состояние вашего процесса:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Ссылка:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Например, я использовал его для условного воспроизведения или приостановки процесса sox в сеансе tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'

-1

Вы можете использовать его внутри скрипта:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.