W systemie GNU, a jeśli tak pv, możesz:
cmd='
that command | to execute &&
as shell code'
yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
Należy -P20wykonać najwyżej 20 $cmdjednocześnie.
-L10 ogranicza szybkość do 10 bajtów na sekundę, więc 5 linii na sekundę.
Jeśli twoje $cmds stają się dwa wolne i powodują osiągnięcie limitu 20, wtedy xargsprzestaną czytać, aż $cmdprzynajmniej jedna instancja powróci. pvnadal będzie zapisywać do potoku z tą samą szybkością, aż potok się zapełni (co w systemie Linux z domyślnym rozmiarem potoku 64KiB zajmie prawie 2 godziny).
W tym momencie pvprzestanie pisać. Ale nawet wtedy, gdy xargswznowi czytanie, pvspróbuje nadrobić zaległości i wyśle wszystkie wiersze, które powinien był wysłać wcześniej, tak szybko, jak to możliwe, aby utrzymać ogólną średnią 5 linii na sekundę.
Oznacza to, że tak długo, jak to możliwe, przy 20 procesach, aby spełnić te wymagania średnio 5 uruchomień na sekundę, będzie to robić. Jednak gdy limit zostanie osiągnięty, szybkość, z jaką uruchamiane są nowe procesy, nie będzie sterowana przez timer pv, ale przez szybkość, z jaką wracają wcześniejsze instancje cmd. Na przykład, jeśli 20 jest aktualnie uruchomionych i działało przez 10 sekund, a 10 z nich decyduje się zakończyć wszystkie w tym samym czasie, wtedy 10 nowych zostanie uruchomionych jednocześnie.
Przykład:
$ 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
Średnio będzie to 5 razy na sekundę, nawet jeśli opóźnienie między dwoma cyklami nie zawsze będzie wynosić dokładnie 0,2 sekundy.
Za pomocą ksh93(lub za pomocą, zshjeśli twoje sleeppolecenie obsługuje ułamkowe sekundy):
typeset -F SECONDS=0
n=0; while true; do
your-command &
sleep "$((++n * 0.2 - SECONDS))"
done
Nie ogranicza to jednak liczby współbieżnych your-command.