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 -P20
wykonać najwyżej 20 $cmd
jednocześnie.
-L10
ogranicza szybkość do 10 bajtów na sekundę, więc 5 linii na sekundę.
Jeśli twoje $cmd
s stają się dwa wolne i powodują osiągnięcie limitu 20, wtedy xargs
przestaną czytać, aż $cmd
przynajmniej jedna instancja powróci. pv
nadal 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 pv
przestanie pisać. Ale nawet wtedy, gdy xargs
wznowi czytanie, pv
spró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ą, zsh
jeśli twoje sleep
polecenie 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
.