Чому я отримую різний статус виходу для ps | grep в сценарії?


11

Я біжу нижче сценарію:

#!/bin/bash

ps ax  | grep -q [v]arnish
if [ $? -eq 0 ];then
        echo varnish is running...
        exit 0
else
        echo "Critical : varnish is not running "
        exit 2
fi

Вихід такий:

[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0

Коли я запускаю те саме в командному рядку, я отримую статус виходу як 1:

[root@server ~]# ps ax  | grep -q [v]arnish; echo $?
1

Справа, як лак не встановлений на сервері. Цей сценарій чудово працює на сервері, де встановлений лак.

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


Використовуйте справжню систему нагляду за процесами, а не цей вид хакерів. Ваша операційна система майже напевно має вбудований спосіб гарантувати, що ваші демони, на яких ви хочете залишитись, автоматично перезапускаються після відмови, будь то на початку, daemontools, systemd, startd або одна з багатьох, багатьох інших альтернатив. Усі вони будуть більш надійними та здібними, ніж цей вид ручного хакеру.
Чарльз Даффі

Відповіді:


10

Під час запуску сценарію, який називається check_varnish_pro.shтестом

ps ax  | grep -q [v]arnish

є успішним, оскільки існує сценарій з ім'ям check_лаку_pro .


14

Загалом, погана ідея спробувати простий підхід psі grepспробувати визначити, чи працює даний процес.

Вам буде набагато краще використовувати pgrepдля цього:

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi

Дивіться посібник для pgrep. У деяких системах (напевно, не в Linux) ви отримуєте -qпрапор, що відповідає тому ж прапору, для grepякого позбавляється від необхідності перенаправлення на /dev/null. Існує також -fпрапор, який виконує збіг у повному командному рядку, а не лише у назві процесу. Можна також обмежити збіг процесами, що належать певному користувачеві, який використовує -u.

Встановлення pgrepтакож надає вам доступ до pkillякого дозволяє подавати сигнали процесів на основі їх імен.

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

У Linux у вас є systemctl( systemctl is-active --quiet varnishповерне 0, якщо він працює, 3 в іншому випадку), на OpenBSD у вас є rcctlі т.д.


Тепер до вашого сценарію:

У вашому сценарії ви аналізуєте вихід з ps ax. Цей вихід буде містити ім'я самого сценарію check_varnish_pro.sh, який, очевидно, містить рядок varnish. Це дає хибний позитив. Ви б помітили це, якби ви працювали без -qпрапора під grepчас тестування.

#!/bin/bash
ps ax | grep '[v]arnish'

Запуск:

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh

Інша проблема полягає в тому, що хоча ви намагаєтесь «приховати» grepпроцес від виявлення grepсам, використовуючи [v]в шаблоні. Такий підхід буде невдалим, якщо вам трапиться запустити скрипт або командний рядок у каталозі, який має в ньому файл чи каталог varnish(у такому випадку ви знову отримаєте помилковий позитив). Це пояснюється тим, що шаблон не цитується, і оболонка виконуватиме ім'я файлів з ним.

Подивитися:

bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2  SN+p    0:00.02 grep varnish

Наявність файлу varnishпризведе до заміни оболонки на [v]arnishім'я файлу, varnishі ви отримаєте потрапляння на шаблон у таблиці процесів ( grepпроцес).


4
тому що все є файлом "у linux land".
zee

@ z_- Не зовсім впевнений у тому, як це підключено, але це справедливо навіть у нелісовиках UNIX.
Kusalananda

4
Не тільки процес грепування; Назва сценарію check_varnish_pro.shтакож є фактором.
ТЯО

@TNW Спочатку я цього не помітив, але ти маєш рацію. Я додам це.
Kusalananda

3

@AlexP дуже коротко пояснює, що насправді відбувається, але ідея @ Kusalananda щодо використання pgrep/ pkillдля критичного процесу сильно не рекомендується . Кращі рішення включають:

  • Запитати службу, чи працює вона. systemctl status varnishdслід подбати про це на сучасній установці * nix.
  • Якщо з якоїсь нещасної обставини у вас немає служби, ви можете просто змінити сценарій запуску, щоб повідомити про проблему, як тільки процес завершиться:

    varnish || true
    some_command_to_send_an_alert_that_the_service_has_died
  • Крім того, змініть сценарій, який запускає службу для запису PID, а потім періодично перевіряйте стан kill -0 "$pid".

Я погоджуюсь, я саме звертався до аспектів проблеми сценаріїв оболонок. Зауважте, що systemctlвін доступний майже лише в Linux (AFAIK), а не у всіх сучасних системах, схожих на Unix.
Кусалаланда

Первісне питання мав тег "linux"; Я не впевнений, чому це було видалено @muru.
l0b0

Спасибі l0b0. У мене було два питання «Чому» та «Як покращити». @ Відповідь AlexP вирішила моє перше питання, а ваша відповідь - краще рішення для другого питання. Але Кусалаланда пояснює речі, пов’язані з цим, які, на мою думку, будуть корисними для людей, які мають подібні проблеми. Тому я зараз плутаю, що прийняти як відповідь.
prado

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