Вы пытаетесь определить концепцию, которой просто не существует. Вы не найдете общего понятия «имя программы» или «имени приложения», которое выходит за рамки того, что вы можете найти в качестве имени исполняемого файла.
Имя исходного файла и , как правило, не сохраняются в исполняемом файле. Для скрипта «основным» исходным файлом является имя исполняемого файла, но скрипт также использует код из множества других мест (по крайней мере интерпретатора ). Для скомпилированной программы информация недоступна во время выполнения, если только что-то специфичное для компилятора или цепочки сборки не помещает ее туда, а в большинстве случаев этого не происходит.
Просмотр /proc/$pid/exe
дает путь к исполняемому файлу. Все процессы имеют исполняемый файл¹. Исполняемый файл мог быть переименован или удален с момента запуска процесса. Это единственное универсальное понятие «имя программы».
Первый элемент /proc/$pid/cmdline
— это аргумент 0, передаваемый при вызове процесса. Это имя выбирается вызывающей стороной процесса. Если вызывающая сторона не ушла со своего пути, обычно это базовое имя исполняемого файла, с частью каталога или без нее, в зависимости от того, была ли программа вызвана через поиск в PATH. Процесс может перезаписать эту часть, но некоторые программы делают это в основном (, несколько демонов делают это, чтобы отразить свой статус таким образом, который можно легко увидеть с помощьюps
).
Linux также хранит имя процесса, о котором сообщает ps -o comm
. Он доступен через /proc/$pid/status
. Это исходное базовое имя исполняемого файла, усеченное до 16 байт.
¹ В /proc
есть записи, ссылка exe
которых не читается. Это потоки ядра или зомби, а не процессы. Для всех процессов ссылка доступна для чтения (с надлежащим разрешением ), хотя она может не указывать на существующий файл, если исполняемый файл был удален.
Когда GNU grep
попытается записать свой результат, он завершится ошибкой с не -нулевым статусом выхода, потому что ему некуда записать вывод, потому что SSH-соединение потеряно.
Это означает, что оператор if
всегда использует ветвь else
.
Чтобы проиллюстрировать это, (это не точно то, что происходит в вашем случае, но оно показывает, что произойдет, если GNU grep
не сможет записать свой вывод):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Здесь мы grep
для строки, которую производит echo
, но мы закрываем оба потока вывода для grep
, чтобы она не могла никуда писать. Как видите, статус выхода GNU grep
равен 2, а не 0.
Это характерно для GNU grep
, grep
в системах BSD не будет вести себя одинаково:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Чтобы исправить это, убедитесь, что сценарий не генерирует выходные данные. Вы можете сделать это с помощью exec >/dev/null 2>&1
. Кроме того, мы должны использовать grep
с его опцией -q
, так как мы совсем не заинтересованы в просмотре вывода из него (это, как правило, также ускорит grep
, поскольку он не нужно анализировать весь файл, но в этом случае это очень мало влияет на скорость, так как файл очень маленький ).
Короче:
#!/bin/sh
# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1
while true; do
date >sdown.txt
ping -c 1 -W 1 myserver.net >pingop.txt
if ! grep -q "64 bytes" pingop.txt; then
mutt -s "Server Down!" myemail@address.com <sdown.txt
break
fi
sleep 10
done
Вы также можете использовать тест ping
напрямую, устраняя необходимость в одном из промежуточных файлов (, а также избавляясь от другого промежуточного файла, который на самом деле всегда содержит только отметку даты):
#!/bin/sh
exec >/dev/null 2>&1
while true; do
if ! ping -q -c 1 -W 1 myserver.net; then
date | mutt -s "Server Down!" myemail@address.com
break
fi
sleep 10
done
В обоих вариантах вышеприведенного сценария я выбираю выход из цикла при невозможности связаться с хостом, просто чтобы свести к минимуму количество отправленных электронных писем.Вместо этого вы можете заменить break
, например, на. sleep 10m
или что-то в этом роде, если вы ожидаете, что сервер снова заработает.
Я также немного изменил параметры, используемые с ping
, так как -i 1
не имеет особого смысла с -c 1
.
Короче (, если вы не хотите, чтобы он продолжал отправлять электронные письма, когда хост недоступен):
#!/bin/sh
exec >/dev/null 2>&1
while ping -q -c 1 -W 1 myserver.net; do
sleep 10
done
date | mutt -s "Server Down!" myemail@address.com
Поскольку задание cron выполняется каждую минуту, (будет продолжать отправлять электронные письма каждую минуту, если сервер по-прежнему не работает):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )