- Bash: запускаем демон с дочерними процессами
- 10.4.1. Создание дочерних процессов
- Читайте также
- Обработка дочерних узлов
- Выбор дочерних элементов
- 10.4.2. Наблюдение за уничтожением дочерних процессов
- 10.4.4. Ускоренное создание процессов с помощью vfork()
- 15.1.1. Перезапуск процессов
- 15.1.2. Остановка процессов
- Эффект наличия слишком большого количества дочерних процессов
- Эффект наличия слишком большого количества дочерних процессов
- 5.7. Диаграммы процессов.
- Создание дочерних окон
- 3.2. Создание процессов
- 3.4.4. Асинхронное удаление дочерних процессов
- 4.14. Упражнение 14. Создание модели ТО-ВЕ (реинжиниринг бизнес-процессов)
- 1. Создание модели процессов в BPwin
Bash: запускаем демон с дочерними процессами
Доброго всем настроения!
Прочитал я вот эту статью, и решил немного сам взять в руки шашки, и попробовать сделать что-нибудь приятное для себя и для других.
Мой скрипт не делает никаких полезных вещей, но думаю для более менее начинающих писателей на bash он чему-нибудь научит, да и если будут комментарии, то и я научусь от тех людей которые укажут на мои ошибки.
Вводная
Скрипт будет запускаться в фоне демоном. Сразу думаю надо договориться что сам процесс который будет висеть в памяти постоянно я буду называть «Родителем». Родитель будет в определенном каталоге искать определенный файл, и если он существует, то файл будет удален и запущен процесс, который я буду называть «Потомок», целью которого будет просто спать какое-то время, и после чего завершиться. Но Родитель не должен будет запускать более одного Потомка в единицу времени. В принципе, если Вы прочитали вышеуказанную статью, то смысл я думаю понятен.
Начнем-с
# Имя файла который будем искать в каталоге FILE_NAME="run_Lola_run" # Каталог в котором будем искать файл WATCH_DIR="/home/mcleod/test" # Имя файла по которому будем определять запущен ли уже Родитель LOCK_FILE="$/monitor_file.lock" # Файл где будем хранить номер работающего процесса Родителя PID_FILE="$/monitor_file.pid" # Имя файла по которому будем определять запущен ли Потомок JOB_LOCK_FILE="$/job_monitor_file.lock" # В этот файл будем писать ход выполнения скрипта LOG="$/monitor_file_work.log" # В этот файл будут попадать ошибки при работе скрипта ERR_LOG="$/monitor_file_error.log" # Определяем максимельное время работы Потомка в секундах RANGE=100
Далее для удобного управления запуском и остановом Родителя напишем небольшое условие
case $1 in "start") start ;; "stop") stop ;; *) usage ;; esac exit
- start — функция запуска, которая переводит скрипт в режим демона
- stop — функция остановки демона
- usage — функция вывода на экран помощи
- _log — функция записи в лог файл
- run_job — функция запуска Потомка
Теперь опишу функции по мере их усложнения. Самая простая их них это функция usage, выглядит она так
# Функция остановки демона stop() < # Если существует pid файл, то убиваем процесс с номером из pid файла if [ -e $] then _pid=$(cat $) kill $_pid rt=$? if [ "$rt" == "0" ] then echo "Daemon stop" else echo "Error stop daemon" fi else echo "Daemon is't running" fi >
Здесь я не использую функцию логирования, т.к. здесь сообщения должны выводиться на консоль.
Теперь пожалуй приведу самую сложную функцию start. В ней находится вся логика работы и сам момент демонизации скрипта.
# Функция запуска демона start() < # Если существует файл с pid процесса не запускаем еще одну копию демона if [ -e $PID_FILE ] then _pid=$(cat $) if [ -e /proc/$ ] then echo "Daemon already running with pid = $_pid" exit 0 fi fi # Создаем файлы логов touch $ touch $ # переходим в корень, что бы не блокировать фс cd / # Перенаправляем стандартный вывод, вывод ошибок и стандартный ввод exec > $LOG exec 2> $ERR_LOG exec < /dev/null # Запускаем подготовленную копию процесса, вообщем форкаемся. Здесь происходит вся работа скрипта ( # Не забываем удалять файл с номером процесса и файл очереди при выходе trap "< rm -f $; exit 255; >" TERM INT EXIT # Основной цикл работы скрипта while [ 1 ] do # Просматриваем каталог на наличие файла if ls -1 $ | grep "^$$" 2>&1 >/dev/null then _log "parent" "File found" rm -f $/$ _log "parent" "File deleted" # Вычисляем сколько будет спать Потомок в секундах и запоминаем в массиве number=$RANDOM let "number %= $RANGE" _log "parent" "Genereated number $number" JOBS[$]=$number fi # Если размер массива больше 0, то запускаем Потомка, и удаляем первый элемент из массива if [ "$" -gt "0" ] then if [ ! -e $ ] then run_job _log "parent" "Running job with pid $!" unset JOBS[0] JOBS=("$") _log "parent" "Jobs in queue [$]" fi fi # Дадим процессору отдохнуть sleep 1 done exit 0 )& # Пишем pid потомка в файл, и заканчиваем работу echo $! > $ >
# Функция запуска Потомка. Потомок берет первый элемент из массива JOBS, и работает run_job() < # Здесь происходит порождение Потомка. Здесь уже ничего не подготавливаем и не переопределяем стандартный ввод/вывод, т.к. это уже сделано в Родителе ( # Не забываем удалять после окончания работы файл trap "< rm -f $; exit 255; >" TERM INT EXIT # Дополнительная проверка что бы убедиться что Потомок один if [ ! -e $ ] then # Пишем номер pid процесса в файл, на всякий случай echo "$$" > $ _log "child" "Job with pid $$" # Запоминаем первый элемент массива seconds=$ # Очищаем массив, хоть память сейчас и дешевая, но зачем ее занимать зря unset JOBS _log "child" "Sleep seconds $seconds" sleep $ else _log "child" "Lock file is exists" fi # Выходим exit 0 )& >
Ну и теперь если все вышеприведенное объеденить в файл и дать ему права на выполнение, думаю у Вас это не составит труда. Кстати перед запуском советую изменить значение переменной WATCH_DIR на путь к каталогу, в котором скрипт будет искать файл с именем run_Lola_run.
Вот мой вывод лог файла
parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 96 parent[32338]: Running job with pid 32385 parent[32338]: Jobs in queue [0] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 96 parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 46 parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 1 parent[32338]: Running job with pid 32694 parent[32338]: Jobs in queue [1] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 46 parent[32338]: Running job with pid 371 parent[32338]: Jobs in queue [0] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 1
Надеюсь кому-нибудь данный пост поможет в освоении bash.
ЗЫ: Внимательный читатель наверняка увидел что в логе везде один и тот-же номер процесса. Т.к. в bash нет чистого форк, здесь происходит его, можно сказать, эмулирование через запуск необходимого кода в ()&, что запускает его в отдельном процессе, но при этом сохраняет переменные неизменными. А мы знаем что номер текущего процесса в bash хранится в переменной $$. Поэтому в лог файле и отображается один и тот же номер процесса. Именно поэтому функция start заканчивается строкой echo $! > $.
10.4.1. Создание дочерних процессов
В Linux предусмотрены два системных вызова, которые создают новые процессы: fork() и clone(). Как упоминалось ранее, clone() используется для создания потоков, и этот вызов будет кратко описан далее. А сейчас мы сосредоточимся на fork() — наиболее популярном методе создания процессов.
Этот системный вызов имеет уникальное свойство возвращать управление не один раз, а дважды: один раз в родительском процессе и другой — в дочернем. Обратите внимание, что мы не говорим «первый — в родительском» — написание кода, который делает какие-то предположения относительно предопределенного порядка — очень плохая идея.
Каждый из двух возвратов системного вызова fork() имеет разные значения. В родительский процесс этот системный вызов возвращает pid вновь созданного дочернего процесса, а в дочернем он возвращает 0.
Разница возвращаемых значений — это единственное отличие, видимое процессам. Оба имеют одинаковые образы памяти, права доступа, открытые файлы и обработчики сигналов[19]. Рассмотрим простой пример программы, порождающей дочерний процесс.
printf(«в родительском — дочерний: %d «, child);
Читайте также
Обработка дочерних узлов
Обработка дочерних узлов Элемент <xsl:apply-templates> дает указание процессору XSLT обрабатывать все совпадающие шаблоны для дочерних узлов контекстного узла. Элемент <xsl:apply-templates> дает возможность явно указать, когда следует закончить обработку дочерних узлов, а это имеет
Выбор дочерних элементов
Выбор дочерних элементов При доступе к дочернему узлу определенного узла для разделения имен элементов можно использовать операцию шага /. Пусть, например, требуется создать правило, которое должно применяться только к тем элементам <NAME>, которые являются дочерними
10.4.2. Наблюдение за уничтожением дочерних процессов
10.4.2. Наблюдение за уничтожением дочерних процессов Сбор состояний возврата дочернего процесса называется ожиданием процесса. Это можно делать четырьмя способами, хотя только один из вызовов предоставляется ядром. Остальные три метода реализованы в стандартной
10.4.4. Ускоренное создание процессов с помощью vfork()
10.4.4. Ускоренное создание процессов с помощью vfork() Обычно процессы, в которых вызывается fork(), немедленно вызывают exec() для другой программы (это то, что оболочка делает всякий раз, когда вы вводите команду), что делает полную семантику fork() более расточительной по
15.1.1. Перезапуск процессов
15.1.1. Перезапуск процессов Каждый процесс может пребывать в трех состояниях: выполнение, останов и «зомби». Выполняющиеся процессы завершаются системным вызовом exit() или отправкой сигнала фатального завершения. Процессы перемещаются между состояниями работы и остановки
15.1.2. Остановка процессов
15.1.2. Остановка процессов Четыре сигнала перемещают работающий процесс в состояние останова. SIGSTOP никогда не генерируется ядром. Он предназначен для остановки произвольных процессов. Его невозможно захватить или проигнорировать; он всегда останавливает целевой процесс.
Эффект наличия слишком большого количества дочерних процессов
Эффект наличия слишком большого количества дочерних процессов В табл. 30.1 (строка 2) указано время (1,8 с), затрачиваемое центральным процессором в случае наличия 15 дочерних процессов, обслуживающих не более 10 клиентов. Мы можем оценить эффект «общей побудки», увеличивая
Эффект наличия слишком большого количества дочерних процессов
Эффект наличия слишком большого количества дочерних процессов Мы можем проверить, возникает ли в данной версии сервера эффект «общей побудки», рассмотренный в предыдущем разделе. Как и раньше, время работы ухудшается пропорционально числу избыточных дочерних
5.7. Диаграммы процессов.
5.7. Диаграммы процессов. Существенное: процессоры, устройства и соединения Диаграммы процессов используются, чтобы показать распределение процессов по процессорам в физическом проекте системы. Отдельная диаграмма процессов показывает один ракурс структуры процессов
Создание дочерних окон
Создание дочерних окон Заключительным шагом должно быть создание подходящей реализации обработчика событий Файл?Создать родительской формы. Теперь, когда дочерняя форма определена, соответствующая программная логика оказывается очень простой: нужно создать и
3.2. Создание процессов
3.2. Создание процессов Существуют два способа создания процессов. Первый из них относительно прост, но применяется редко, поскольку неэффективен и связан со значительным риском для безопасности системы. Второй способ сложнее, но избавлен от недостатков
3.4.4. Асинхронное удаление дочерних процессов
3.4.4. Асинхронное удаление дочерних процессов Если дочерний процесс просто вызывает другую программу с помощью функции exec(), то в родительском процессе можно сразу же вызвать функцию wait() и пассивно дожидаться завершения потомка. Но очень часто нужно, чтобы родительский
4.14. Упражнение 14. Создание модели ТО-ВЕ (реинжиниринг бизнес-процессов)
4.14. Упражнение 14. Создание модели ТО-ВЕ (реинжиниринг бизнес-процессов) Модель ТО-ВЕ создается на основе анализа модели AS-IS. Анализ может проводиться как по формальным признакам (отсутствие выходов или управлений у работ, отсутствие обратных связей и т. д.), так и по
1. Создание модели процессов в BPwin
1. Создание модели процессов в BPwin 1.1. Инструментальная среда BPwin BPwin имеет достаточно простой и интуитивно понятный интерфейс пользователя, дающий возможность аналитику создавать сложные модели при минимальных усилиях. Ниже будет описан интерфейс версии 2.5. Рис. 1.1.