Искусство программирования на языке сценариев командной оболочки
Шрифт:
then
выполнить_ряд_специфичных_команд
...
else
выполнить_ряд_других_специфичных_команд
...
fi
В каталоге /proc вы наверняка заметите большое количество подкаталогов, с не совсем обычными именами, состоящими только из цифр. Каждый из них соответствует исполняющемуся процессу, а имя каталога -- это ID (идентификатор) процесса. Внутри каждого такого подкаталога находится ряд файлов, в которых содержится полезная информация о соответствующих процессах. Файлы stat
Пример 27-1. Поиск файла программы по идентификатору процесса
#!/bin/bash
# pid-identifier.sh: Возвращает полный путь к исполняемому файлу программы по идентификатору процесса (pid).
ARGNO=1 # Число, ожидаемых из командной строки, аргументов.
E_WRONGARGS=65
E_BADPID=66
E_NOSUCHPROCESS=67
E_NOPERMISSION=68
PROCFILE=exe
if [ $# -ne $ARGNO ]
then
echo "Порядок использования: `basename $0` PID-процесса" >&2 # Сообщение об ошибке на >stderr.
exit $E_WRONGARGS
fi
ps ax
pidno=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )
# Проверка наличия процесса с заданным pid в списке, выданном командой "ps", поле #1.
# Затем следует убедиться, что этот процесс не был запущен этим сценарием ('ps').
# Это делает последний "grep $1".
if [ -z "$pidno" ] # Если после фильтрации получается пустая строка,
then # то это означает, что в системе нет процесса с заданым pid.
echo "Нет такого процесса."
exit $E_NOSUCHPROCESS
fi
# Альтернативный вариант:
# if ! ps $1 > /dev/null 2>&1
# then # в системе нет процесса с заданым pid.
# echo "Нет такого процесса."
# exit $E_NOSUCHPROCESS
# fi
if [ !
– r "/proc/$1/$PROCFILE" ] # Проверить право на чтение.
then
echo "Процесс $1 найден, однако..."
echo "у вас нет права на чтение файла /proc/$1/$PROCFILE."
exit $E_NOPERMISSION # Обычный пользователь не имеет прав
# на доступ к некоторым файлам в каталоге /proc.
fi
# Последние две проверки могут быть заменены на:
# if ! kill -0 $1 > /dev/null 2>&1 # '0' -- это не сигнал, но
# команда все равно проверит наличие
# процесса-получателя.
# then echo "Процесс с данным PID не найден, либо вы не являетесь его владельцем" >&2
# exit $E_BADPID
# fi
exe_file=$( ls -l /proc/$1 | grep "exe" | awk '{ print $11 }' )
#
#
# /proc/pid-number/exe -- это символическая ссылка
# на исполняемый файл работающей программы.
if [ -e "$exe_file" ] # Если файл /proc/pid-number/exe существует...
then # то существует и соответствующий процесс.
echo "Исполняемый файл процесса #$1: $exe_file."
else
echo "Нет такого процесса."
fi
# В большинстве случаев, этот, довольно сложный сценарий, может быть заменен командой
# ps ax | grep $1 | awk '{ print $5 }'
# В большинстве, но не всегда...
# поскольку пятое поле листинга,выдаваемого командой 'ps', это argv[0] процесса,
# а не путь к исполняемому файлу.
#
# Однако, оба следующих варианта должны работать безотказно.
# find /proc/$1/exe -printf '%l\n'
# lsof -aFn -p $1 -d txt | sed -ne 's/^n//p'
# Автор последнего комментария: Stephane Chazelas.
exit 0
Пример 27-2. Проверка состояния соединения
#!/bin/bash
PROCNAME=pppd # демон ppp
PROCFILENAME=status # Что смотреть.
NOTCONNECTED=65
INTERVAL=2 # Период проверки -- раз в 2 секунды.
pidno=$( ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME | awk '{ print $1 }' )
# Найти идентификатор процесса 'pppd', 'ppp daemon'.
# По пути убрать из листинга записи о процессах, порожденных сценарием.
#
# Однако, как отмечает Oleg Philon,
#+ Эта последовательность команд может быть заменена командой "pidof".
# pidno=$( pidof $PROCNAME )
#
# Мораль:
#+ Когда последовательность команд становится слишком сложной,
#+ это повод к тому, чтобы поискать более короткий вариант.
if [ -z "$pidno" ] # Если получилась пустая строка, значит процесс не запущен.
then
echo "Соединение не установлено."
exit $NOTCONNECTED
else
echo "Соединение установлено."; echo
fi
while [ true ] # Бесконечный цикл.
do
if [ !
– e "/proc/$pidno/$PROCFILENAME" ]
# Пока работает процесс, файл "status" существует.
then
echo "Соединение разорвано."
exit $NOTCONNECTED
fi
netstat -s | grep "packets received" # Получить некоторые сведения о соединении.
netstat -s | grep "packets delivered"
sleep $INTERVAL