Как запустить команду в среднем 5 раз в секунду?

У меня есть сценарий командной строки, который выполняет вызов API и обновляет базу данных с результатами.

У меня есть ограничение на 5 вызовов API в секунду с поставщиком API. Для выполнения сценария требуется более 0,2 секунды.

  • Если я буду запускать команду последовательно, она не будет работать достаточно быстро, и я буду делать только 1 или 2 вызова API в секунду.
  • Если я буду запускать команду последовательно, но одновременно с нескольких терминалов, я могу превысить 5 вызовов / второй лимит.

Если есть способ упорядочить потоки, чтобы мой скрипт командной строки выполнялся почти ровно 5 раз в секунду?

Например, что-то, что будет работать с 5 или 10 потоками, и ни один поток не выполнит скрипт, если предыдущий поток выполнил его менее 200 мс назад.

  • Является ли crontab многопоточным?
  • Каждый процесс считается нитью?
  • Почему top и ps показывают разные PID для тех же процессов?
  • Является ли какая-либо часть программного обеспечения X.org многопоточной?
  • Как указать, какое ядро ​​порождается pthread
  • запустить команду для нескольких потоков
  • Может ли одно ядро ​​процессора обрабатывать более одного процесса?
  • Как скопировать три файла одновременно, а не один файл за один раз в сценарии оболочки bash?
  • 5 Solutions collect form web for “Как запустить команду в среднем 5 раз в секунду?”

    В системе 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 s становятся двумя медленными и приводят к достижению 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 .

    Упрощенно, если ваша команда длится менее 1 секунды, вы можете просто запускать 5 команд каждую секунду. Очевидно, это очень сильно.

     while sleep 1 do for i in {1..5} do mycmd & done done 

    Если ваша команда может занять более 1 секунды, и вы хотите разложить команды, которые вы можете попробовать

     while : do for i in {0..4} do sleep .$((i*2)) mycmd & done sleep 1 & wait done 

    Кроме того, вы можете иметь 5 отдельных циклов, которые запускаются независимо, с минимальным 1 секундой.

     for i in {1..5} do while : do sleep 1 & mycmd & wait done & sleep .2 done 

    С программой C,

    Например, вы можете использовать поток, который спит в течение 0,2 секунды

     #include<stdio.h> #include<string.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> pthread_t tid; void* doSomeThing() { While(1){ //execute my command sleep(0.2) } } int main(void) { int i = 0; int err; err = pthread_create(&(tid), NULL, &doSomeThing, NULL); if (err != 0) printf("\ncan't create thread :[%s]", strerror(err)); else printf("\n Thread created successfully\n"); return 0; } В #include<stdio.h> #include<string.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> pthread_t tid; void* doSomeThing() { While(1){ //execute my command sleep(0.2) } } int main(void) { int i = 0; int err; err = pthread_create(&(tid), NULL, &doSomeThing, NULL); if (err != 0) printf("\ncan't create thread :[%s]", strerror(err)); else printf("\n Thread created successfully\n"); return 0; } 

    используйте его, чтобы знать, как создать поток: создать поток (это ссылка, которую я использовал для вставки этого кода)

    Используя node.js, вы можете запустить один поток, который выполняет скрипт bash каждые 200 миллисекунд, независимо от того, как долго ответ будет возвращаться, потому что ответ приходит через функцию обратного вызова .

     var util = require('util') exec = require('child_process').exec setInterval(function(){ child = exec('fullpath to bash script', function (error, stdout, stderr) { console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); if (error !== null) { console.log('exec error: ' + error); } }); },200); 

    Этот javascript запускается каждые 200 миллисекунд, и ответ получен через функцию функции обратного вызова function (error, stdout, stderr) .

    Таким образом, вы можете контролировать, чтобы он никогда не превышал 5 вызовов в секунду независимо от того, насколько медленным или быстрым является выполнение команды или сколько она должна ждать ответа.

    Я использовал какое-то время на основе pv решения Stéphane Chazelas, но выяснил, что он вышел случайно (и молча) через некоторое время, от нескольких минут до нескольких часов. – Edit: Причина в том, что мой скрипт PHP иногда умирал из-за превышения максимального времени выполнения, выходящего со статусом 255.

    Поэтому я решил написать простой инструмент командной строки, который делает именно то, что мне нужно.

    Достижение моей первоначальной цели так же просто, как:

     ./parallel.phar 5 20 ./my-command-line-script 

    Он запускает почти ровно 5 команд в секунду, если нет уже 20 параллельных процессов, и в этом случае он пропускает следующее выполнение (ы), пока не станет доступным слот.

    Этот инструмент не чувствителен к выходу статуса 255.

    Interesting Posts

    Пространства в назначениях переменных в сценариях оболочки

    Функциональные клавиши больше не доступны для переключения рабочих областей

    Создание файлов tar из сценария оболочки с текущей меткой времени

    Я случайно удалил своего пользователя из нескольких групп, как узнать, какими они были?

    что является разделителем по умолчанию для опции sort -k

    Как получить строки, содержащие -R с grep

    Компиляция и установка ядра kernel.org на пользовательский том на диске

    Tmux идентифицирует, масштабируется ли панель и активируется

    Невозможно установить любые пакеты

    Oh-My-Zsh переопределяет мою функцию?

    Просмотр системных вызовов / активности ядра для ввода-вывода из работающего процесса

    Установите файловую систему samba в RHEL 5.5

    Как переместить журнал ext4

    Linux: восстановление файлов из файла .vdi

    Легко распаковывать DEB, редактировать postinst и повторно упаковывать DEB

    Linux и Unix - лучшая ОС в мире.