Ставил я не так давно простой и легкий прокси-сервер tinyproxy, и с удивлением не обнаружил в комплекте запускающего (инициализационного) скрипта.
Что это за зверь такой, если кто не знает. Ко многим демонам в Linux в комплекте идет инициализационный скрипт, позволяющий демона запустить, «убить» или перезапустить из консоли командой вида daemonname start (stop, restart)
без необходимости вручную отлавливать идентификатор процесса, убивать его командой kill
и проверять, завершен ли процесс (или наоборот, стартовал ли он). К squid
, например, такой скрипт идет, называется (в Slackware) rc.squid
и лежит в /etc/rc.d
, а к tinyproxy
в комплекте не шло, но написать его оказалось не так и сложно.
Итак, скрипт будет получать из командной строки единственный параметр с командой:
start
— запускать прокси-сервер
stop
— останавливать его
restart
— перезапускать (останавливать, а после остановки запускать)
status
— отображать, запущен или не запущен прокси.
#!/bin/bash
PIDFILE="/home/provproxy/tinyproxy.pid"
TINYPROXYCMD="/usr/sbin/tinyproxy"
PIDVAL=0
WTIMEOUT=30
OK=0
CH_S[0]='-' #pseudographic items
CH_S[1]='/'
CH_S[2]='|'
CH_S[3]='\'
ITEM_ARR=0 #current item counter
PIDFILE
— переменная, в которой указан PID-файл, файл, содержащий идентификатор основного процесса прокси-сервера. Tinyproxy
при запуске создает сразу несколько процессов, позволяющих ему распараллеливать свою внутреннюю работу. Минимальное и максимальное число таких процессов задается в конфигурационном файле /etc/tinyproxy.conf
параметрами MinSpareServers
и MaxSpareServers
, а процесс, идентификатор которого указан в PID-файле основной, управляющий. Ему можно послать сигнал, например, командой kill
, и все остальные процессы тоже завершатся. Местоположение PID-файла также указывается в файле /etc/tinyproxy.conf
в параметре PidFile
. Конечно, правильнее читать сам конфигурационный файл, и выдергивать значение параметра оттуда, ну да ладно, параметр этот перенастраивается нечасто, посему пусть такое решение останется на моей совести -=^_^-=.TINYPROXYCMD
— путь к исполняемому файлу прокси-сервераPIDVAL
— здесь будет храниться значение PID, полученное из PID-файла.WTIMEOUT
— максимальное время ожидания запуска tinyproxy
, или его завершения.OK
— флаг, принимающий значение 1 в случае успешного запуска/завершения, или 0 — в случае неуспеха. Вообще-то, можно и без него обойтись, но мне с ним удобнее и нагляднее.
CH_S[0] - CH_S[3]
, массив с псевдографическими элементами, для украшательства, отображения хода процесса запуска. Подробности про украшательства тут или тут , и если кому не надо, выбросить лишние команды из скрипта — дело нехитрое. Переменная ITEM_ARR
предназначена для тех же целей.
Далее, определим в скрипте несколько функций.
см. описание функций под катом
Проверять параметры будем при помощи оператора
case
, после объявления функций.
case "$1" in
start)
start_proxy
;;
stop)
stop_proxy
;;
restart)
restart_proxy
;;
status)
status_proxy
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
esac
Если первый параметр, переданный из командной строки
start, stop, restart
или status
— выполняются соответствующие функции, если что-то еще (*
) — выводим краткую справку по использованию скрипта. В списке источников в конце заметки есть ссылка на более подробное описание оператора.
process_status()
. Вот ее код:
#Получаем PID
if [ -e $PIDFILE ];then #если файл существует
PIDVAL=`cat $PIDFILE` #читаем PID
TMPGREP=`ps -p $PIDVAL|grep "tinyproxy" -c` #процесс запущен - 1 иначе 0
if [ $TMPGREP -ge 1 ];then #процесс запущен
return #выходим из функции
else #pid-файл есть, процесса нет
rm $PIDFILE #удаляем pid-файл
fi
fi
PIDVAL=0
Сначала проверяется наличие PID-файла, если он существует, отправляем его содержимое (конструкция «), прочитанное с помощью команды
cat
в переменную PIDVAL
, далее, запрашиваем информацию о процессе (ps
) по его PID (ключ -p
). Если процесс существует, команда ps
отправит на стандартный вывод что-то типа:
PID TTY TIME CMD
2100 ? 00:00:00 tinyproxy
А если процесса не существует:
PID TTY TIME CMD
Далее, этот вывод передается команде grep
, которая фильтрует строки с именем искомого процесса (tinyproxy
) и подсчитывает их количество (ключ -c
). Если строк 1 процесс с данным PID существует, если 0 — процесса нет.
Если PID-файл существует, то в переменной $PIDVAL
остается идентификатор процесса и происходит выход из функции
[...] if [ $TMPGREP -ge 1 ];then #процесс запущен return #выходим из функции [...]
Если PID-файл существует, а процесс с данным PID не обнаружен, значит в PID-файле указан не тот PID, что, в большинстве случаев, может произойти из-за падения программы (с tinyproxy это случается довольно редко), либо из-за общего системного сбоя вызванного, например, отключением питания. Поэтому стоит PID-файл удалить.
Если процесс не обнаружен, или PID-файл не найден, то происходит выход из всех условных конструкций и переменной $PIDVAL
присваивается значение 0
[...]
PIDVAL=0
[...]
Таким образом, если процесс существует, то в переменной $PIDVAL
будет присутствовать его идентификатор, если не существует — значение 0.
Примечание о безопасности и стабильности использования PID-файлов. Конечно, есть более универсальный способ найти процесс не обращаясь к PID-файлу, например, получить список процессов командой ps ax
и отgrep’ать его, найдя нужное нам имя, и, если надо, то завершить его командой pkill имя_процесса
, и данный способ весьма неплохо будет работать с тем же tinyproxy
.
Но tinyproxy — это просто web-прокси сервер, и неизвестно, что произойдет, если применить такой метод, например, к серверу баз данных. Возможно, какие-то транзакции не завершатся, порушится сама база. Поэтому, информации, сохраняемой программами в PID-файлах, стоит доверять. Безопасность их использования и контроль доступа к ним других пользователей должны решаться другими средствами ОС. Посему я не вижу смысла загромождать скрипт дополнительными проверками.
За пояснение благодарю ketmar@ljr
Если функция
process_status()
используется для получения статуса (и PID) процесса для внутренних целей скрипта, то функция status_proxy()
выводит информацию пользователю. И хоть она очень проста, но лучше вынести ее отдельно, дабы не смешивать взаимодействие с пользователем со внутренней механикой программы.
Вот код этой функции:
status_proxy() { process_status if [ $PIDVAL -eq 0 ]; then echo "Tinyproxy not running" else echo "Tinyproxy running [PID=$PIDVAL]" fi }
Как я и говорил, функция очень проста, сначала вызывается функция process_status
, и если в переменной $PIDVAL
значение 0, то выводится сообщение о том, что tinyproxy не запущен, иначе, что запущен и дополнительно выводится его PID.
Выполняет его функция
start_proxy()
. Вот ее код:см. код и описание функции под катом
ПРИМЕЧАНИЕ: Если прокси не запускается, то для поиска неисправности удобно запустить прокси-сервер с ключом
-d
tinyproxy -d
В таком случае прокси запустится не в виде фонового процесса (демона), а в виде обычного, и выдаст ошибки на консоль. Например, если на файерволе закрыты порты, необходимые серверу, будет выведено сообщение:
tinyproxy: Could not create listening socket.
За остановку прокси-сервера отвечает функция
stop_proxy()
. Ее код:см. код и описание функции под катом
1. Запускаем функцию остановки
stop_proxy
.
2.
Сбрасываем флаг: $OK=0
Выполняем функцию запуска start_proxy
Вот нехитрый код функции restart_proxy()
:
restart_proxy()
{
stop_proxy
OK=0
start_proxy
}
С Pastebin
С Mega.nz
1.Bash. Функции.
2.Возврат значений из функции
3.Оператор
case
4.Tinyproxy
5.Коды завершения, имеющие предопределенный смысл
Pingback: Простая инструкция по установке Tinyproxy | Персональный блог Толика Панкова
Pingback: Домашний сервер на базе Slackware Linux | Персональный блог Толика Панкова