Команда Linux / Unix, щоб визначити, чи працює процес?


97

Мені потрібна незалежна від платформи (Linux / Unix | OSX) команда shell / bash, яка визначатиме, чи працює конкретний процес. наприклад mysqld, httpd... Який найпростіший спосіб / команда це зробити?

Відповіді:


168

Хоча pidofі pgrepє чудовими інструментами для визначення того, що працює, вони, на жаль, недоступні в деяких операційних системах. Безперечним відмовою в безпеці буде використання наступного:ps cax | grep command

Вихід на Gentoo Linux:

14484? S 0:00 apache2
14667? S 0:00 apache2
19620? Sl 0:00 apache2
21132? Ss 0:04 apache2

Вихід на OS X:

42582 ?? Z 0: 00,00 (smbclient)
46529 ?? Z 0: 00,00 (smbclient)
46539 ?? Z 0: 00,00 (smbclient)
46547 ?? Z 0: 00,00 (smbclient)
46586 ?? Z 0: 00,00 (smbclient)
46594 ?? Z 0: 00,00 (smbclient)

І в Linux, і в OS X grep повертає вихідний код, тому легко перевірити, знайдено процес чи ні:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

Крім того, якщо ви хочете, щоб список PID-кодів, ви також можете легко похвалитися за ці:

ps cax | grep httpd | grep -o '^ [] * [0-9] *'

Чий вихід однаковий для Linux та OS X:

3519 3521 3523 3524

Вихід із наведеного нижче є порожнім рядком, що робить цей підхід безпечним для процесів, які не виконуються:

відлуння ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'

Цей підхід підходить для написання простого тесту порожнього рядка, а потім навіть повторення через виявлені PID.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi

Ви можете перевірити його, збереживши його у файл (названий "запущеним") з дозволами на виконання (chmod + x running) та виконавши його з параметром: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

УВАГА!!!

Будь ласка, майте на увазі, що ви просто розбираєте вихід, а ps axце означає, що, як видно з виходу Linux, це не просто збігання процесів, а й аргументи, передані цій програмі. Я настійно рекомендую бути максимально конкретним при використанні цього методу (наприклад ./running "mysql", також відповідатиме "mysqld" процесам). Я настійно рекомендую використовувати, whichщоб перевірити повний шлях, де це можливо.


Список літератури:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm


Процес може працювати, але зупинити. Отже, якщо мета - перевірити, чи mysqld або httpd "запущені" (відповідь), ви також повинні перевірити, зупинено чи ні.
oluc

2
Вибачте, але, хоча відповідь, безумовно, правильна з семантичної точки зору, я повністю проти спроби знайти процес за узгодженням шаблону на векторі аргументу процесу. Будь-який такий підхід рано чи пізно приречений на збій (ви насправді самі цього зізнаєтесь, сказавши, що потрібно більше перевірок). Я додав власну рекомендацію в окрему відповідь.
peterh

6
grepтакож виявиться запущеним (наприклад ps cax | grep randomname, завжди поверне 0, тому що grepзнаходить grep randomname(сподіваюся, це зрозуміло ...). Одним виправленням є додавання квадратних дужок навколо першої літери імені процесу, наприклад ps cax | grep [r]andomname.
Кайл Г.

ps cax | rev | cut -f1 -d' ' | revвідображатиметься лише стовпець імені для полегшення розбору.
Тизоїд

1
ps caxне може виводити ім'я команди повністю. Наприклад, він друкує "Chrome-браузер" замість "Chrome-браузер".
jarno

24

Ви повинні знати ПІД!

Пошук процесу, намагаючись зробити якесь розпізнавання шаблонів на аргументах процесу (як pgrep "mysqld"), - це стратегія, яка рано чи пізно приречена на збій. Що робити, якщо у вас працює два mysqld? Забудьте про такий підхід. Ви МОЖЕТЕ отримати це право тимчасово, і воно МОЖЕ працювати рік-два, але тоді трапляється щось, про що ви не думали.

Тільки ідентифікатор процесу (pid) справді унікальний.

Завжди зберігайте під, коли ви запускаєте щось у фоновому режимі. У Bash це можна зробити за допомогою $!змінної Bash. Ви заощадите настільки багато проблем, зробивши це.

Як визначити, чи працює процес (за pid)

Тож тепер стає питання, як дізнатись, чи працює пуд.

Просто робіть:

ps -o pid = -p <pid>

Це POSIX і, отже, портативний. Він поверне сам pid, якщо процес запущений, або нічого не поверне, якщо процес не працює. Строго кажучи, команда поверне один стовпець, pidале, оскільки ми дали, що порожній заголовок заголовка (матеріал, що безпосередньо передує знаку рівності), і це єдиний запитуваний стовпець, тоді команда ps взагалі не буде використовувати заголовка. Що ми хочемо, тому що це полегшує розбір.

Це буде працювати на Linux, BSD, Solaris тощо.

Іншою стратегією було б перевірити значення виходу з вищевказаної psкоманди. Він повинен бути нульовим, якщо процес запущений, і не нульовим, якщо його немає. Специфікація POSIX говорить, що psнеобхідно вийти> 0, якщо сталася помилка, але мені незрозуміло, що являє собою "помилку". Тому я особисто не використовую цю стратегію, хоча я впевнений, що вона буде добре працювати на всіх платформах Unix / Linux.


1
За винятком цього, це не відповідає на питання, яке визначає, чи працює служба. PID НЕ буде відомо , в таких випадках, тому ця відповідь є дійсним , тільки якщо ви робите знати PID.
Шосе життя

2
Неправильно. Весь мій коментар - зробити крок назад і сказати, що якщо ви вперше опинитесь у ситуації, коли вам потрібно зробити якусь форму, grep <sometext>щоб знайти заданий процес, то ви зробили щось не так, коли ви розпочали процес, IMHO. Я беру на думку питання ОП, що він справді має контроль над тим, як розпочато процес.
пітер

2
Більш правильним "терміном" для питання про ОП повинен був стати "міжплатформна команда, щоб визначити, чи працює служба", це не та система, яка запускає чек, а зовнішня система, тому PID просто не збирається відомі взагалі.
Шосе життя

2
Це не дурно. Процес, який вас зацікавив, може загинути після того, як система вистачає надовго, щоб PID-адреси завернулися, і інший процес може бути призначений тому самому PID, який ви перевіряєте. stackoverflow.com/questions/11323410/linux-pid-recycling
кламація

1
@claymation. Справедливий пункт. Однак метод PID все-таки кращий, ніж узгодження шаблону для аргументів процесу, оскільки зіткнення PID набагато малоймовірне, ніж скажімо про випадкове запуску двох примірників однієї служби. Всього два мої центи. :-)
п'ятницю

15

У більшості дистрибутивів Linux можна використовувати pidof(8).

Він надрукує ідентифікатори процесу всіх запущених екземплярів зазначених процесів, або нічого, якщо не буде запущених екземплярів.

Наприклад, у моїй системі (у мене є чотири екземпляри bashта один екземпляр remminaзапуску):

$ pidof bash remmina
6148 6147 6144 5603 21598

В інших Уніках pgrepабо в поєднанні psта grepдосягнуть того самого, як справедливо зазначали інші.


+1 pidof httpdпрекрасно працює на Red Hat 5. Але на моїй Red Hat 4, pidofнемає :-(
olibre

Дійсно, ця команда менш поширена, ніж я думав, я відредагував свою відповідь, щоб зробити це зрозумілішим.
Фредерік Хаміді

Гарна чиста відповідь дійсно. (на підтримуваних системах). Дякую.
Mtl Dev

7

Це має працювати на більшості ароматів Unix, BSD та Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Тестовано на:

  • SunOS 5.10 [Звідси PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Дарвін 11.2.0
  • FreeBSD 9.0-STABLE
  • Випуск Red Hat Enterprise Linux ES 4
  • Реліз Red Hat Enterprise Linux Server 5

2
+1 Так просто ps. Щоб уникнути другого, grepпропоную:ps aux | grep [h]ttpd
олибре

Я не використовував трюк з квадратними дужками, щоб полегшити введення змінної в основну grep.
Johnsyweb

1
Гаразд;) Я щойно перевірив Red Hat AS 4 та Red Hat AP 5. Звичайно, я працюю! Таким чином, ви можете додати до свого списку: Red Hat Enterprise Linux ES випуск 4 та Red Hat Enterprise Linux Server Edition 5 . Ура
олібре

@Downvoter: Чому? Що я пропустив? Наскільки я можу сказати, прийнята відповідь робить той самий пошук!
Johnsyweb

6

Найпростішим способом є використання ps та grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi

Якщо у вашій команді є декілька аргументів команди, ви можете також поставити більше 'grep cmd_arg1' після 'grep $ command', щоб відфільтрувати інші можливі процеси, які вас не цікавлять.

Приклад: покажіть мені, чи є який-небудь процес Java з наданим аргументом:

-Djava.util.logging.config.file = logging.properties

біжить

ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l

2
Власне, використання ps caxвиключає необхідність використання grep -v. Так, наприклад, ви можете використовувати: ps cax | grep java > /dev/null || echo "Java not running".
Шосе життя

1
У 3-му рядку є помилка. будь ласка, змініть "біг" на "$ працює".
Програміст

5

Лише незначне доповнення: якщо ви додасте -cпрапор до ps, після цього не потрібно видаляти рядок, що містить процес grep grep -v. Тобто

ps acux | grep cron

- це все, що вам потрібно набрати в системі bsd-ish (сюди входить MacOSX) Ви можете залишити -uподалі, якщо вам потрібно менше інформації.

У системі, де генетика нативної psкоманди вказує на SysV, ви використовуєте

ps -e |grep cron

або

ps -el |grep cron 

для списку, що містить більше, ніж просто pid та ім'я процесу. Звичайно, ви можете вибрати конкретні поля для друку, використовуючи цю -o <field,field,...>опцію.


Як ця відповідь є портативною? (Ви кажете, що різні форми команди ps повинні використовуватися на різних платформах)
peterh

ps, на жаль, є одним із тих інструментів, що мають різний набір варіантів для одного результату залежно від їх походження. Отже, якщо ви не напишете свою власну (знову несумісну з чим-небудь іншим) обгортку навколо цього, шлях слід було б знати основні лінії спадщини та відповідно адаптуватися. Інакше, коли ви розробляєте сценарії - там ви б використовували ці відмінності, щоб визначити, на якій галузі ви працюєте, та адаптувати поведінку вашого сценарію. Підсумок: вам потрібно знати обоє. Відомий приклад: сценарій «налаштування» Ларрі Уолла. Відома цитата: Вітаю, ви не керуєте Юніс.
Тетяна Хейзер

5

Поєднуючи різні пропозиції разом, найчистіша версія, яку мені вдалося придумати (без ненадійного жадання, що запускає частини слів), це:

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

kill -0 не вбиває процес, але перевіряє, чи він існує, а потім повертає true, якщо у вас немає pidof у вашій системі, зберігайте pid під час запуску процесу:

$ mysql &
$ echo $! > pid_stored

потім у сценарії:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

3

Я використовую, pgrep -l httpdале не впевнений, що він присутній на будь-якій платформі ...
Хто може підтвердити на OSX?


Дякую @Johnsyweb. Ви також можете перевірити, pidofбудь ласка? Добре, що ти зробив. Дякую. Тому ми повинні знайти щось інше, що працює над OSX ... Вашим основним ps|grepможе бути єдине рішення ;-)
olibre

1

Ви повинні знати PID вашого процесу.

Коли ви запускаєте його, його PID буде записаний у $!змінну. Збережіть цей PID у файл.

Тоді вам потрібно буде перевірити, чи відповідає цей PID виконуваному процесу. Ось повний сценарій скелета:

FILE="/tmp/myapp.pid"

if [ -f $FILE ];
then
   PID=$(cat $FILE)
else
   PID=1
fi

ps -o pid= -p $PID
if [ $? -eq 0 ]; then
  echo "Process already running."  
else
  echo "Starting process."
  run_my_app &
  echo $! > $FILE
fi

Виходячи з відповіді о peterh. Хитрість дізнатися, чи працює даний PID, є в ps -o pid= -p $PIDінструкції.


0

Цей підхід може бути використаний у випадку, якщо команди "ps", "pidof" та інші недоступні. Я особисто дуже часто використовую PROFS у своїх інструментах / скриптах / програмах.

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

Невелике пояснення, що відбувається:

  1. -m1 - зупинка процесу на першому матчі
  2. "mysqld $ | httpd $" - grep відповідатиме рядкам, які закінчилися на mysqld АБО httpd
  3. / proc / [0-9] * - bash буде відповідати рядку, який розпочався з будь-якого числа
  4. вирізати - просто розділити вихід на роздільник '/' та витягнути поле 3

0

Це друкує кількість процесів, базовим ім'ям яких є "Chrome-браузер":

ps -e -o args= | awk 'BEGIN{c=0}{
 if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
 if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"

Якщо це надрукує "0", процес не запущений. Команда припускає, що шлях процесу не містить пробільного простору. Я не перевіряв цього з призупиненими процесами чи процесами зомбі.

Тестовано з використанням gwakв якості awkальтернативи в Linux.

Ось більш універсальне рішення з прикладом використання:

#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
 local quiet=1;
 shift
else
 local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
 name=$2
 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
 if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}

process='chromium-browser'

printf "Process \"${process}\" is "
if isProcessRunning -q "$process" 
 then printf "running.\n"
 else printf "not running.\n"; fi

printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"

0

Ось моя версія. Особливості:

  • перевіряє точну назву програми (перший аргумент функції). пошук "mysql" не відповідатиме запуску "mysqld"
  • шукає програмні аргументи (другий аргумент функції)

сценарій:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi

0

Жодна з відповідей не працювала для мене, тому ось моя:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

Пояснення:

|tr -d '\n'

Це видаляє повернення каретки, створене терміналом. Решту можна пояснити цією публікацією.


-1

Наступна функція оболонки, що базується лише на стандартних командах та параметрах POSIX, повинна працювати на більшості (якщо такої немає) системи Unix та Linux. :

isPidRunning() {
  cmd=`
    PATH=\`getconf PATH\` export PATH
    ps -e -o pid= -o comm= |
      awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
  `
  [ -n "$cmd" ] &&
    printf "%s is running\n%s\n\n" "$1" "$cmd" ||
    printf "%s is not running\n\n" $1
  [ -n "$cmd" ]
}

$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd

$ isPidRunning ksh
ksh is running
5230 ksh

$ isPidRunning bash
bash is not running

Зауважте, що він задихнеться при передачі сумнівного імені команди "0]", а також не зможе визначити процеси, що мають вбудований простір у свої імена.

Зауважте також, що найбільш схвалене та прийняте рішення вимагає переносних psпараметрів і безперешкодно використовує оболонку, яка, незважаючи на свою популярність, не гарантується, щоб бути присутнім на кожній машині Unix / Linux ( bash)


$ isPidRunning 0]друкує, наприклад, "0] працює 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [міграція / 0] 35 [сторожовий / 0]" тут.
jarno

Для чого вам потрібна річ PATH?
jarno

Я розробив рішення далі тут .
jarno

@jarno Налаштування PATH - це вимога для портативного сценарію. В іншому випадку це не вдасться принаймні на Solaris 10 та старіших версіях та, можливо, інших реалізаціях Unix.
jlliagre

1
@jarno Я можу це зробити, але мені потрібно буде повторити цю настройку PATH і для awk. Зауважте, що я повернувся до старого синтаксису backtick, щоб він був переносним із синтаксисом bourne оболонок перед POSIX.
jlliagre
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.