Баш спосіб перевірити, чи процес вже запущений у фоновому режимі (і пропустити повторне виконання на основі цього)?


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 тощо. - це зробить будь-який унікальний ідентифікатор. Коли тег є файлом, це може бути звичайний файл, що містить ідентифікатор процесу (pidfile), або названий канал або сокет, який файл слухає, і т.д. В ідеалі тег - це кінцева точка зв'язку, яка дозволяє клієнтам підключатися до цього процесу.

Кожен з цих різних типів тегів призводить до різного способу перевірки, чи працює і запущений екземпляр, який ви шукаєте. Наприклад, за допомогою локального файлового сокета спробуйте підключитися до нього та запустіть процес, якщо в цьому сокеті немає прослуховування процесу. Якщо тег є pidfile, перевірте, чи є процес з цим ідентифікатором процесу, але будьте уважні, що це неміцно, оскільки якщо процес загинув, може виникнути незв'язаний процес, який повторно використав свій ідентифікатор. Остерігайтеся, що якщо два клієнти намагаються досягти процесу за короткий проміжок часу, вони можуть виявити, що процес не існує, і обидва намагаються його запустити; правильний захист від цієї умови гонки може бути складним.

Простіше керувати випадками, коли вони починаються одним і тим самим процесом супервізора, і цей процес супервізора виявляє, коли екземпляри гинуть, і відповідно реагує. Багато програм моніторингу послуг, які можуть це зробити.

Якщо програма не відповідає на відому кінцеву точку зв’язку і не керується програмою супервізора, тег бідолахи - це pidfile: файл, що містить ідентифікатор процесу. Коли ви запускаєте процес, запишіть pid у файл із заздалегідь заданим іменем. Коли вам потрібен процес, прочитайте pidfile і перевірте, чи є процес із цим pid. Коли ви вбиваєте процес, видаліть pidfile. Найбільш помітною проблемою з непідконтрольним pidfile є те, що якщо процес вмирає, його 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 (Імена команд матчу) не підтримується в ОС X.

В OS X ps -o commдрукується абсолютний шлях команд і ps -co commдрукується лише імена команд. У GNU ps -o commдрукуються лише імена команд і -cмають інше значення.

У pgrep OS X не входять процеси предків (наприклад, bash, Terminal або startd) без -a. Pgrep GNU включає їх за замовчуванням, і він не підтримує -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  $!  ...

Вбудована команда "робочі місця" - спробуйте:

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.