Як визначити, запущений процес чи ні, і використовувати його для створення умовного сценарію оболонки?


108

Як я можу визначити, запущений процес чи ні, а потім мати сценарій bash, який виконує деякі речі на основі цієї умови?

Наприклад:

  • якщо процес abcзапущений, зробіть це

  • якщо він не працює, зробіть це.


1
Важливо зазначити, що жодне з наведених нижче рішень не враховує стан процесу. Коментар на одне із моїх запитань привів мене сюди, але відповідь на це ввібрала мене в різні стани програми, як zombieпроцес "(не те, що я б назвав" запущеним "процесом). Повний список того , що STATзначення стовпця, у висновку ps, вказує на це тут для тих , хто схильний писати відповідь , який пристосовує це, або редагувати їх самостійно.
user66001

Супутня дискусія: unix.stackexchange.com/questions/74185/…
blong

найкращий спосіб перевірити наявність процесу: stackoverflow.com/questions/3043978/…
Тревор Бойд Сміт

Відповіді:


166

Баш сценарій, щоб зробити щось подібне, виглядатиме приблизно так:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Цей скрипт просто перевіряє, чи працює програма "gedit".

Або ви можете перевірити, чи програма не працює так:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi

@DreadPirateShawn ви можете мені сказати, чому використовувати / dev / null, а не просто 0? Використання числа робить код більш читабельним, принаймні для noob (наприклад, у мене). Без переадресації, нічого немає
Сільвіу

2
@Silviu так? Гуглінг /dev/null: "/ dev / null перенаправляє стандартний висновок команди на нульовий пристрій, який є спеціальним пристроєм, який відкидає інформацію, написану на ньому" ... за допомогою 0перенаправлення виводу команди на названий файл 0. У цьому випадку я б радив стати більш комфортним > /dev/null- ви побачите це всюди, оскільки це стандартний / правильний спосіб відкинути вихід.
DreadPirateShawn

Дякую, я використав це для гарного маленького сценарію, який перевіряє, чи працює програма перед її виконанням. (хоча мені довелося трохи розширити його, оскільки виконуваний файл google chrome не має такої ж назви, що і команда run, ім'я exec - просто хром.)
Cestarian

3
Будь ласка, додайте -xпараметр, щоб pgrepвін шукав точну програму, інакше він отримає помилковий правильний випадок, якщо знайде ту саму рядок у назві іншого додатка. Я просто витратив 1 годину, щоб знайти це.
Танос Апостолу

1
Щоб перевірити, чи програма не працює,! pgrep
Mohammed Noureldin

36

Будь-яке рішення, яке використовує щось на кшталт ps aux | grep abcабо pgrep abcє недоліком.

Чому?

Оскільки ви не перевіряєте, чи працює певний процес, ви перевіряєте, чи є якісь запущені процеси, які відповідають abc. Будь-який користувач може легко створити та запустити виконуваний файл з іменем abc(або який міститься abcдесь у його імені чи аргументах), що спричинить помилковий позитив для вашого тесту. Є різні варіанти , які можна застосувати до ps, grepі pgrepзвузити область пошуку, але ви все одно не отримаєте надійний тест.

Тож як я можу надійно перевірити певний запущений процес?

Це залежить від того, для чого вам потрібен тест.

Я хочу переконатися, що служба abc працює, а якщо ні, запустіть її

Для цього потрібні init та upstart. Вони запускають службу та забезпечують її збереження в pidfile. Спробуйте запустити послугу ще раз (через init або upstart), і вона перевірить pidfile, або запустити його, якщо його немає, або перервати, якщо він вже працює. Це все ще не на 100% надійно, але воно настільки ж близьке, як ви отримаєте.

Див. Як я можу перевірити, чи все ще працює мій ігровий сервер ... для інших рішень.

abc - мій сценарій. Мені потрібно переконатися, що працює лише один екземпляр мого сценарію.

У цьому випадку використовуйте файл lockck або lockdir. Напр

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Інші способи блокування див. У розділі " Bash FAQ" 45 .


3
Хоча це технічно правда, я ніколи особисто не стикався з такою проблемою в реальному житті. Більшість програм не змінюють своїх імен способами, що розбивають сценарії. Таким чином, для простих сценаріїв щось на кшталт pgrepабо psє цілком адекватним, і ваш підхід здається непосильним. Якщо ви пишете сценарій для публічного розповсюдження, вам слід написати його найбезпечнішим можливим способом.
Скотт Северанс

2
@ScottSeverance Програми не змінюють назву; це вимагало б втручання незалежно. Інші користувачі, які виконують ту саму програму, або інші програми з подібними іменами, раптом спричинить, що скрипт отримає помилкові позитиви і, таким чином, зробить неправильну справу. Я просто віддаю перевагу «твори», а не «переважно твори».
geirha

2
Я помиляюсь. Але багато хто з нас працюють з однокористувальними системами. І в декількох ситуаціях з користувачем легко також привітатися з ім'ям користувача.
Скотт Северанс

1
що робити, якщо ваш сценарій виходить з ладу під час виконання та відмирає до розблокування файлу?
jp093121

2
@ jp093121 Пастка EXIT спрацьовує при виході сценарію. Незалежно від того, що він виходить, оскільки він досягає кінця скрипту, команди виходу, або отримує сигнал (з яким можна обробляти), rmкоманда виконується. Тому поки він закінчується після встановлення пастки, блокування не повинно бути.
geirha

18

Це те, що я використовую:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

Простий англійською мовою: якщо 'pgrep' повертає 0, процес запущений, інакше це не так.


Пов'язане читання:

Баш-сценарій :: Порівняння рядків

Посібники Ubuntu pgrep


дякую! Я теж спробував це, я теж прекрасно працює :)
Nirmik

pgrepмає той самий 15-ти символьний ліміт "особливості", який згадувався раніше, таким чином, наприклад pgrep gnome-power-manager, також не вдасться
Торсен

1
Переконайтеся, що ви використовуєте -xопцію pgrep : "Тільки відповідати процесам, чиє ім'я (або командний рядок, якщо вказано -f) точно відповідає шаблону."
Аластер Ірвін


2

Визначаючи ідею @ rommel-cid, ви можете використовувати pidofз || (||) запустити команду, якщо процес не існує, і && запустити щось, якщо процес існує, таким чином створивши швидку умову if / then / else. Наприклад, ось такий із запущеним процесом (мій браузер Chrome, назва якого процес "chrome") та тестування процесу, який не існує. Я придушив стандартний вихід за допомогою 1> / dev / null, щоб він не друкував:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$

1

Жодне з "простих" рішень не працювало для мене, тому що бінарний файл, який мені потрібно перевірити, не встановлюється загальносистемно, тому мені доводиться перевіряти шлях, який, в свою чергу, вимагає використання ps -ef | grepпідходу:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi

0

Перше, що мені прийшло в голову щодо вашої проблеми:
ps aux | grep -i abcпокаже подробиці процесу, якщо його запуск. Ви можете збігати кількість рядків або час, за який він працює, і порівняти з нулем або будь-якими іншими маніпуляціями. Коли ви запустите вищевказану команду, вона покаже вам принаймні один рядок виводу, тобто детальну інформацію про процес, створений командою th grep. Тому подбайте про це.
Це повинно бути простим злом. Помістіть його в сценарій bash і подивіться, чи корисно це.


0

Використання start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Він працює як звичайний користувач.


0

Я виявив, що прийнята відповідь, опублікована @John Vrbanac, не працює для мене, і що відповідь, опублікована @geirha, не відповідає на початкове запитання.

Рішення Джона Врбанака не спрацювало, щоб перевірити, запущений чи PHP процес для мене, я запускаю CentOS 7.

Відповідь @ geirha лише гарантує, що примірник не запущений до запуску іншого. Це не було початкове запитання, оригінальне запитання - перевірити, запущений процес чи ні.

Ось що для мене спрацювало:

Скажімо, у моєму процесі в його назві був рядок "Jane". Це виявить, працює він чи ні. Це працює для сценаріїв BASH та PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi

1
Так, але це веб-сайт Ubuntu Q&A. Не дивно, що деякі відповіді тут не працюють на CentOS 7, оскільки Linux тут не є темою. Інші версії Linux підтримуються на unix.stackexchange.com
Elder Geek

хоча автор відповіді використовує CentOS, ця відповідь все-таки справедлива для ubuntu.
Phillip -Zyan K Lee- Stockmann

0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Примітка : pgrep -x lxpanelабо pidof lxpanelяк і раніше звіти, які lxpanelпрацюють, навіть коли вони не працюють (зомбі); тож, щоб активувати живий процес, нам потрібно використовувати psіgrep


-1

Станом на 23 вересня 2016 р. Для pgrep потрібен варіант "-x", щоб сценарій муру працював.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Я спробував і випробував вищевказаний скрипт на машині Ubuntu 16.04.1. Насолоджуйтесь!


-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done

1
Ласкаво просимо до Ask Ubuntu! Я рекомендую відредагувати цю відповідь, щоб розширити її конкретними подробицями про те, що це робить. (Дивіться також Як я можу написати гарну відповідь? Для загальних порад про те, які типи відповідей вважаються найціннішими на AskUbuntu.)
Девід Фоерстер,

-3

isProcessRunning () {if [$ (pidof $ 1)> / dev / null]; тоді retval = 'true'; else retval = 'помилково'; fi; echo $ retval; }

isProcessRunning geany

правда

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.