Em um sistema GNU e, se houver pv, você pode fazer:
cmd='
that command | to execute &&
as shell code'
yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
O -P20é executar no máximo 20 $cmdao mesmo tempo.
-L10 limita a taxa a 10 bytes por segundo, portanto, 5 linhas por segundo.
Se seus $cmds se tornarem lentos e fizer com que o limite de 20 seja atingido, a xargsleitura será interrompida até que $cmdpelo menos uma instância retorne. pvainda continuará gravando no pipe na mesma taxa, até que o pipe fique cheio (o que no Linux com um tamanho de pipe padrão de 64KiB levará quase 2 horas).
Nesse ponto, pvparará de escrever. Mas mesmo assim, quando xargsretomar a leitura, pvtentará recuperar e enviar todas as linhas que deveria ter enviado mais cedo o mais rápido possível, para manter uma média geral de 5 linhas por segundo.
O que isso significa é que, contanto que seja possível, com 20 processos, atender a 5 rodadas por segundo no requisito médio, isso será feito. No entanto, quando o limite é atingido, a taxa na qual novos processos são iniciados não será conduzida pelo timer do pv, mas pela taxa na qual as instâncias anteriores do cmd retornam. Por exemplo, se 20 estão em execução no momento e duram 10 segundos, e 10 deles decidem terminar todos ao mesmo tempo, 10 novos serão iniciados ao mesmo tempo.
Exemplo:
$ 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
Em média, será 5 vezes por segundo, mesmo que o atraso entre duas execuções nem sempre seja exatamente de 0,2 segundos.
Com ksh93(ou zshse o seu sleepcomando suportar segundos fracionários):
typeset -F SECONDS=0
n=0; while true; do
your-command &
sleep "$((++n * 0.2 - SECONDS))"
done
Isso não vincula o número de your-commands concorrentes .