Linux/Bash, как запланировать команды в очереди FIFO?
Я хочу, чтобы возможность планировать команды для запуска в очереди FIFO. Я не хочу, чтобы они запускались в указанное время в будущем, как в случае с командой "at". Я хочу, чтобы они начали работать сейчас, но не одновременно. Следующая запланированная команда в очереди должна быть выполнена только после завершения выполнения первой команды. В качестве альтернативы было бы неплохо, если бы я мог указать максимальное количество команд из очереди, которые могли бы выполняться одновременно; например, если максимальное количество одновременных команд равно 2, то из очереди будет выполнено только самое большее 2 команды, запланированные в очереди, способом FIFO, который будет выполняться, причем следующая команда в оставшейся очереди запускается только тогда, когда одна из в настоящее время 2 выполняющиеся команды заканчиваются.
Я слышал, что диспетчер задач может делать что-то подобное, но этот пакет, похоже, не поддерживается и не тестируется и не входит в стандартные репозитории Ubuntu (Ubuntu - то, что я использую). Если это лучшая альтернатива, дайте мне знать, и я буду использовать диспетчер задач, в противном случае мне будет интересно узнать, каков наилучший, самый простой, самый проверенный, без ошибок, канонический способ сделать такое с bash.
ОБНОВИТЬ:
Простые решения, такие как; или && из bash не работают. Мне нужно запланировать эти команды из внешней программы, когда происходит событие. Я просто не хочу, чтобы сотни экземпляров моей команды выполнялись одновременно, поэтому мне нужна очередь. Есть внешняя программа, которая будет запускать события, где я могу запускать свои собственные команды. Я хочу обрабатывать ВСЕ инициируемые события, я не хочу пропустить ни одного события, но я также не хочу, чтобы моя система зависала, поэтому я хочу, чтобы очередь обрабатывала мои команды, запущенные из внешней программы.
7 ответов
Диспетчер задач:
http://vicerveza.homeunix.net/~viric/soft/ts/
https://launchpad.net/ubuntu/+source/task-spooler/0.7.3-1
Делает трюк очень хорошо. Надеюсь, он будет включен в репозиторий Ubuntu.
Использование ;
Например: ls ; touch test ; ls
Это будет список каталога. Только после ls
побежал, он побежит touch test
который создаст файл с именем test. И только после этого будет запущена следующая команда. (В этом случае другой ls
который покажет старое содержимое и вновь созданный файл).
Подобные команды ||
а также &&
,
;
всегда будет запускать следующую команду.
&&
будет запускаться только следующая команда, если первый возвращенный успех.
Пример: rm -rf *.mp3 && echo "Success! All MP3s deleted!"
||
будет выполнять следующую команду, только если первая команда вернула ошибочное (ненулевое) возвращаемое значение. Пример: rm -rf *.mp3 || echo "Error! Some files could not be deleted! Check permissions!"
Если вы хотите выполнить команду в фоновом режиме, добавьте амперсанд (&
).
Пример: make bzimage &
mp3blaster sound.mp3
make mytestsoftware ; ls ; firefox ; make clean
Запустит две команды в фоновом режиме (в этом случае сборка ядра, которая займет некоторое время, и программу для воспроизведения музыки). И на переднем плане он запускает другую задачу компиляции и, как только она будет завершена, ls, firefox и make clean (все последовательно)
Для получения более подробной информации см. man bash
[Изменить после комментария]
в псевдокоде, что-то вроде этого?
Программа run_queue: В то время как (истина) { Wait_for_a_signal(); Пока (очередь не пустая) { запустить следующую команду из очереди. удалить эту команду из очереди. // Если команды были добавлены в очередь во время выполнения, то // очередь не пустая, продолжаем обрабатывать их все. } // Очередь теперь пуста, возвращаясь к wait_for_a_signal }
// // Ждем команд вечно и добавляем их в очередь // Сигнал run_quueu, когда что-то добавляется. // программа add_to_queue() { В то время как (истина) { Wait_for_event(); Добавить команду в очередь сигнал run_queue } }
Самый простой способ - просто запустить команды последовательно:
cmd1; cmd2; cmd3; cmdN
Если вы хотите, чтобы следующая команда выполнялась только в случае успешного завершения предыдущей команды, используйте &&
:
cmd1 && cmd2 && cmd3 && cmdN
Это единственный родной способ работы с Bash, который я знаю, делать то, что вы хотите. Если вам нужен контроль заданий (настройка количества параллельных заданий и т. Д.), Вы можете попробовать установить менеджер очередей, такой как TORQUE, но это кажется излишним, если все, что вы хотите сделать, - это запускать задания последовательно.
За исключением диспетчера задач, я буквально не нашел ничего другого, что бы удовлетворить эту потребность. Tsp - это здорово, но я не всегда в состоянии скомпилировать или установить на каждый сервер, с которым мне нужно работать.
Некоторое время я боролся с этим, и после 3 итераций (начиная с более сложных до менее сложных) я придумал чистую реализацию bash, которая до сих пор работала нормально. Вы можете найти его по адресу https://github.com/sitaramc/bq.
Bq использует тот факт, что в Unix "mv" (в пределах одной и той же файловой системы) является атомарной операцией для всех ее потребностей в блокировке.
Это всего лишь один сценарий bash, поэтому установка тривиальна.
Сценарий подробно прокомментирован, и вы сможете просмотреть его через несколько минут, если хотите.
Ты ищешь at
брат-близнец: batch
, Он использует тот же демон, но вместо того, чтобы планировать определенное время, задания ставятся в очередь и будут запускаться всякий раз, когда средняя загрузка системы низкая.
Помимо специализированных систем массового обслуживания (таких как Sun Grid Engine), которые вы также можете использовать локально на одной машине и которые предлагают десятки возможностей, вы можете использовать что-то вроде
command1 && command2 && command3
что является другой крайностью - очень простой подход. Последний не обеспечивает ни множественных одновременных процессов, ни постепенного заполнения "очереди".
Я пошел по тому же маршруту в поисках, опробовал диспетчер задач и так далее. Лучшие из лучших это:
GNU Parallel --semaphore --fg У него также есть -j для параллельных заданий.