Я сталкивался с этим вопросом, когда искал решение проблемы с очередями. Для всех, кто ищет здесь, мое решение.
Добавьте к этому cron, который запускает задания по расписанию (даже если они запланированы на одновременное выполнение) и решает проблему, которую вы также описали.
Проблема
- Должно быть запущено не более одного экземпляра скрипта.
- Мы хотим отслеживать запросы, чтобы обрабатывать их как можно быстрее.
т. Нам нужен конвейер к скрипту.
Решение:
Создать конвейер для любого скрипта. Закончено с помощью небольшого скрипта bash (далее).
Сценарий можно назвать
./pipeline "<any command and arguments go here>"
Пример: * * тысяча двадцать-пять
./pipeline sleep 10 &
./pipeline shabugabu &
./pipeline single_instance_script some arguments &
./pipeline single_instance_script some other_argumnts &
./pipeline "single_instance_script some yet_other_arguments > output.txt" &
..etc
Сценарий создает новый именованный канал для каждой команды. Таким образом, приведенное выше создаст именованные каналы: sleep
, shabugabu
и single_instance_script
В этом случае начальный вызов запустит считыватель и запустит single_instance_script
с some arguments
в качестве аргументов. Как только вызов завершится, читатель получит следующий запрос с конвейера и выполнит с помощью some other_arguments
, завершит, получит следующий и т. Д. ...
Этот скрипт блокирует запрашивающие процессы, поэтому вызывайте его как фоновое задание (и в конце) или как отдельный процесс с at
(at now <<< "./pipeline some_script"
)
#!/bin/bash -Eue
# Using command name as the pipeline name
pipeline=$(basename $(expr "$1" : '\(^[^[:space:]]*\)')).pipe
is_reader=false
function _pipeline_cleanup {
if $is_reader; then
rm -f $pipeline
fi
rm -f $pipeline.lock
exit
}
trap _pipeline_cleanup INT TERM EXIT
# Dispatch/initialization section, critical
lockfile $pipeline.lock
if [[ -p $pipeline ]]
then
echo "$*" > $pipeline
exit
fi
is_reader=true
mkfifo $pipeline
echo "$*" > $pipeline &
rm -f $pipeline.lock
# Reader section
while read command < $pipeline
do
echo "$(date) - Executing $command"
($command) &> /dev/null
done