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 для параллельных заданий.

Другие вопросы по тегам