В системе GNU, и если у вас есть pv
, вы можете сделать:
cmd='
that command | to execute &&
as shell code'
yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
-P20
Это выполнить не более 20 $cmd
одновременно.
-L10
ограничивает скорость до 10 байтов в секунду, поэтому 5 строк в секунду.
Если у вас $cmd
два медленных и приводит к достижению предела 20, то xargs
чтение прекратится, пока $cmd
не вернется хотя бы один экземпляр. pv
будет продолжать запись в канал с той же скоростью, пока канал не заполнится (что в Linux с размером канала по умолчанию 64 КБ займет почти 2 часа).
В этот момент pv
перестану писать. Но даже тогда, когда xargs
возобновит чтение, pv
попытается перехватить и отправить все строки, которые должны были быть отправлены ранее, как можно быстрее, чтобы поддерживать среднее значение 5 строк в секунду.
Это означает, что до тех пор, пока это будет возможно с 20 процессами, удовлетворяющими этим 5 запускам в секунду в среднем требовании, он будет делать это. Однако при достижении предела скорость запуска новых процессов будет зависеть не от таймера pv, а от скорости, с которой возвращаются более ранние экземпляры cmd. Например, если 20 в данный момент работают и были в течение 10 секунд, и 10 из них решили завершить все одновременно, то 10 новых будут запущены одновременно.
Пример:
$ cmd='date +%T.%N; exec sleep 2'
$ yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
09:49:23.347013486
09:49:23.527446830
09:49:23.707591664
09:49:23.888182485
09:49:24.068257018
09:49:24.338570865
09:49:24.518963491
09:49:24.699206647
09:49:24.879722328
09:49:25.149988152
09:49:25.330095169
В среднем это будет 5 раз в секунду, даже если задержка между двумя запусками не всегда будет ровно 0,2 секунды.
С ksh93
(или с, zsh
если ваша sleep
команда поддерживает доли секунды):
typeset -F SECONDS=0
n=0; while true; do
your-command &
sleep "$((++n * 0.2 - SECONDS))"
done
Это не ограничивает число одновременных your-command
s.