spanasik
@spanasik
программист

Пул периодических задач на сервере

Приветствую!

Есть скрипт, который выполняется достаточно долгое время. Его задача собрать данные, поэтому запускается несколько экземпляров с разными параметрами, по крону.

Проблема в том, что он отрабатывает за разное время, поэтому, например, если мы запускаем 4 экземпляра скрипта в 12.00, а следующие 4 экземпляра в 18.00 — не факт, что те, которые запущены в 12.00, закончили работу.

Сам по себе скрипт работает очень хорошо, как надо. Проблема в том, чтобы как-то организовать пул или очередь, чтобы не запускать новые экземпляры, пока работают старые.

Есть ли какой-то инструмент, чтобы каждый момент времени работало скажем не более 4 рабочих процессов, и запускались новые по очереди с определёнными параметрами? Или надо писать своё что-то на основе gearman например? Я думал, что есть готовый инструмент, но не могу найти.

Решение с makefile -j, которое описано тут stackoverflow.com/questions/463963/parallel-processing-from-a-command-queue-on-linux-bash-python-ruby-whateve, непонятно как поставить на поток.
  • Вопрос задан
  • 4564 просмотра
Пригласить эксперта
Ответы на вопрос 6
Wott
@Wott
unix way — положить в /var/run/ pid файл и проверять его наличие. при наличии не стартовать задачу
4 разных задачи — 4 pid файла, не стоит их смешивать, если они четко разделяются, а не просто 4 разных потока одной задачи.
Ответ написан
AGvin
@AGvin
Как я вижу, все изобретают свои велосипеды, вместо того, что бы использовать готовое решение =)

Я же, в данном случае, пользуюсь flock.

Вот пример:
/usr/bin/flock -x -w 0 /var/lock/my_events/event_name -c /path/to/your/script.sh


А вот, краткое описание параметров:
Usage:
 flock [-sxun][-w #] fd#
 flock [-sxon][-w #] file [-c] command...
 flock [-sxon][-w #] directory [-c] command...

Опции:
 -s  --shared     Get a shared lock
 -x  --exclusive  Get an exclusive lock
 -u  --unlock     Remove a lock
 -n  --nonblock   Fail rather than wait
 -w  --timeout    Wait for a limited amount of time
 -o  --close      Close file descriptor before running command
 -c  --command    Run a single command string through the shell
 -h  --help       Display this text
 -V  --version    Display version
Ответ написан
Комментировать
mktums
@mktums
У ребят сверху более unix-way решения, а я использовал бы RabbitMQ/0MQ и так далее…
Ответ написан
Комментировать
Anonym
@Anonym
Программирую немного )
ps aux | grep script.sh
не?
Ответ написан
opium
@opium
Просто люблю качественно работать
Использую всегда вот такую обертку для всех скриптов для защиты от повторного запуска.
#!/bin/sh

PIDFILE=/var/run/rsync_deploy.pid
if [! -e $PIDFILE ]; then
touch $PIDFILE

rm $PIDFILE
fi
Ответ написан
gouranga
@gouranga
Используйте lock-файлы.

Как-то так:
#!/bin/bash

DEFAULT_LOCK="/tmp/.somelock"

lock() {
	LOCK=${1:-$DEFAULT_LOCK}
	lockfile -r 0 $LOCK 1>/dev/null 2>&1
	return $?
}

unlock() {
	LOCK=${1:-$DEFAULT_LOCK}
	[ -f $LOCK ] && rm -f $LOCK
	return $?
}

После можно писать:
lock && echo "lock ok test"
lock || echo "lock not ok test"
unlock && echo "unlock ok test"
unlock || echo "unlock not ok test"

И оно будет использовать стандартный lock-файл (удобно когда нужно запустить один скрипт).

В вашем случае можно указать свой lock-файл, для каждого скрипта в зависимости от параметра(-ов):
# $PARAM -- что-то уникальное для каждого из 4 запусков скрипта. Например:
# PARAM=`echo -n "$@" | openssl dgst -sha1 -binary | base64`
LOCK="${DEFAULT_LOCK}_${PARAM}"

if ! lock $LOCK ; then
	echo "Locked"
	exit 1
fi

# ваши действия

unlock $LOCK
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы