Trên hệ thống GNU và nếu bạn có pv
, bạn có thể làm:
cmd='
that command | to execute &&
as shell code'
yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
Việc -P20
thực hiện tối đa 20 $cmd
cùng một lúc.
-L10
giới hạn tốc độ xuống còn 10 byte mỗi giây, vì vậy 5 dòng mỗi giây.
Nếu $cmd
s của bạn trở thành hai chậm và khiến giới hạn 20 đạt được, thì nó xargs
sẽ ngừng đọc cho đến khi một $cmd
trường hợp ít nhất trở lại. pv
vẫn sẽ tiếp tục ghi vào đường ống với cùng tốc độ, cho đến khi đường ống đầy (mà trên Linux với kích thước đường ống mặc định là 64KiB sẽ mất gần 2 giờ).
Tại thời điểm đó, pv
sẽ ngừng viết. Nhưng ngay cả khi đó, khi xargs
tiếp tục đọc,pv
sẽ cố gắng bắt kịp và gửi tất cả các dòng mà nó nên gửi sớm nhất có thể để duy trì tổng thể trung bình 5 dòng trên giây.
Điều đó có nghĩa là miễn là có thể với 20 quy trình để đáp ứng 5 lần chạy mỗi giây theo yêu cầu trung bình, nó sẽ thực hiện được. Tuy nhiên, khi đạt đến giới hạn, tốc độ bắt đầu các quá trình mới sẽ không bị điều khiển bởi bộ đếm thời gian của pv mà bởi tốc độ mà các trường hợp cmd trước đó quay trở lại. Chẳng hạn, nếu 20 hiện đang chạy và đã được 10 giây và 10 trong số chúng quyết định hoàn thành tất cả cùng một lúc, thì 10 cái mới sẽ được bắt đầu cùng một lúc.
Thí dụ:
$ 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
Trung bình, nó sẽ là 5 lần mỗi giây ngay cả khi độ trễ giữa hai lần chạy không phải lúc nào cũng chính xác là 0,2 giây.
Với ksh93
(hoặc với zsh
nếu sleep
lệnh của bạn hỗ trợ giây phân đoạn):
typeset -F SECONDS=0
n=0; while true; do
your-command &
sleep "$((++n * 0.2 - SECONDS))"
done
Điều đó không đặt ràng buộc vào số lượng your-command
s đồng thời mặc dù.