Запускать скрипты Bash в папке одновременно

10

Предположим, у меня есть пять .shскриптов Bash ( ) в папке ( my_folder), и они названы так:

script_1.sh
script_2.sh
script_3.sh
script_4.sh
script_5.sh

Как я могу написать шестой скрипт Bash или просто один лайнер, который начнет запускать все эти скрипты вместе?

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

ааааа
источник

Ответы:

12

GNU parallelидеально подходит для такого рода вещей. Установите с помощью sudo apt install parallelи затем:

parallel -j0 ::: my_folder/*sh

В -jконтролирует количество процессов т работать параллельно, а -j0значит «все из них». Установите другое значение (например -j20), чтобы вместо этого запускать сценарии партиями.

terdon
источник
1
примечание: есть также parallelкоманда из moreutilsпакета. Пример использования: parallel -j 20 -- my_folder/*.sh(В отличие от GNU parallel, -j0скрипты запускаются по одному).
JFS
1
@jfs хорошая мысль. Но обратите внимание, что sudo apt install parallelфайл будет заменен файлом /usr/bin/parallelиз параллельного GNU. Так что, пока вы устанавливаете его, как подсказывает мой ответ, он должен работать как положено.
тердон
Да, я обнаружил, что это трудный путь, когда я безуспешно пытаюсь выполнить parallelкоманды из руководства, когда пишу свой ответ, предлагая параллельную GNU.
JFS
9

Чтобы запустить все сценарии одновременно (параллельно), используйте:

script_1.sh &
script_2.sh &
script_3.sh &
script_4.sh &
script_5.sh &

Для запуска одного за другим (последовательно) используйте:

script_1.sh &&
script_2.sh &&
script_3.sh &&
script_4.sh &&
script_5.sh

Улучшение для комментариев

Если у вас есть 200 сценариев, которые вы хотите запустить в одно и то же время (что может помешать работе машины), используйте этот сценарий:

#!/bin/bash
for Script in my_folder/*.sh ; do
    echo bash "$Script" &
done

Установите атрибуты сценария на исполняемый с помощью команды:

chmod a+x /path/to/script.sh

При первом запуске сценария будут отображены только имена 200 сценариев, которые он будет выполнять. Когда вы счастливы, правильные имена выбираются, отредактируйте скрипт и измените эту строку:

    echo bash "$Script" &

чтобы:

    bash "$Script" &

Есть три способа вызвать bash-скрипт из другого, ответив здесь:

  1. Сделайте другой скрипт исполняемым, добавьте #!/bin/bashстроку вверху и путь к файлу к $PATHпеременной среды. Тогда вы можете вызвать его как обычную команду;

  2. Или вызовите его с помощью исходной команды (псевдоним.), Например source /path/to/script:;

  3. Или используйте команду Баша , чтобы выполнить его: /bin/bash /path/to/script;

В случае OP один или несколько из 200 сценариев не содержали #!/bin/bashпервую строку shebang в файле. Как таковой вариант 3. должен был использоваться.


200 скриптов, работающих одновременно

Был поднят комментарий о том, «работают ли они одновременно». В типичной системе с 8 ЦП 25 сценариев будут совместно использовать один ЦП одновременно, но только один сценарий будет выполняться за раз, пока не истечет его временной интервал (измеряемый в миллисекундах). Затем следующая работа получит свою долю в миллисекундах, затем следующую работу и т. Д. И т. Д.

В целом мы можем сказать, что 200 заданий выполняются «одновременно», но не «одновременно» на 8 процессорах, что соответствует 25 заданиям на процессор:

поток состояний.png

Выше изображение и комментарии ниже из планировщика ядра Linux

time slice.png

WinEunuuchs2Unix
источник
спасибо .. дело в том, что в моем реальном случае у меня есть более 200 сценариев для запуска. так есть ли способ, которым я могу запустить все из них с помощью одной команды (т.е. без записи их имен файлов)?
ааааа
@aaaaa Я изменил ответ для 200 сценариев.
WinEunuuchs2Unix
Спасибо. это работает .. единственное, что я должен был добавить к вашей последней строке, это 'bash'. в противном случае я получаю «разрешение отказано».
ааааа
1
@aaaaa Вы на самом деле предпочитаете, чтобы все 200+ сценариев запускались одновременно, или вы предпочитаете, чтобы какое-то меньшее количество (скажем, 10) запускалось одновременно, а другие ставились в очередь для запуска, когда один или несколько из них заканчиваются и количество запущенных в данный момент скриптов падает ниже этого числа? (Если вы заинтересованы в таких решениях, я предлагаю отредактировать ваш вопрос, указав информацию о том, сколько у вас есть сценариев, сколько времени они занимают, какую работу они выполняют и т. Д.)
Элия ​​Каган,
@aaaaa Спасибо за отзыв. Я обновил ответ, добавив bashпрефикс для вызова скрипта.
WinEunuuchs2Unix
3

Для этого есть инструмент, читай man run-parts.

Например, я делаю:

 run-parts ${visorhome}/pbackup.d/

в моем скрипте резервного копирования Palm Pilot. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks
waltinator
источник
1
@ eliah-kagan Запускать «более 200 сценариев» «одновременно» кажется неразумным. Это может быть хороший способ провести стресс-тестирование системы
вальтинатор
Хорошая точка зрения. Я думаю, что вы все еще можете упомянуть, что run-partsсценарии выполняются последовательно, а не все сразу, как запросил OP. Вы правы, однако, что запуск 200 сценариев за раз вряд ли будет выполнять то же самое, что и запуск 5 - и даже если запуск их всех одновременно не вызывает никаких проблем, он все равно может быть ненужным. Я прокомментировал, чтобы предложить ОП уточнить свои предпочтения в этом отношении.
Элия ​​Каган,
run-partsне будет запускать скрипты ( у них есть точка в названии:my_folder/*.sh
JFS
1
run-partsимеет очень_ определенные требования к имени файла по какой-то странной причине. Он не запускает имена файлов с расширениями, поэтому я боюсь, что здесь это не сработает.
Terdon
1

Чтобы запустить все *.shсценарии в my_folderкаталоге одновременно, используйте xargs:

$ ls my_folder/*.sh | xargs -P0 -n1 bash

Чтобы ограничить количество одновременно выполняемых сценариев 10:

$ ls my_folder/*.sh | xargs -P10 -n1 bash
JFS
источник
Это плохая практика - использовать вывод lsскрипта. Использование findнамного безопаснее. Это самый первый элемент здесь: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Джо,
@ В общем, правда. Я не вижу проблем в этом конкретном случае.
JFS
Это потому что ты уже знаешь об этом. Люди, приезжающие сюда позже, могут не
Джо
@ Джо, не следуй за догмой вслепую. Подумайте сами, чем один вариант лучше другого, каковы компромиссы в вашем случае.
JFS
Это не догма. Я настороженно отношусь к этим. Но я видел вещи, которые ls может испускать. Разбор читабельного вывода не является надежным. Нет никакого стимула для разработчиков
Джо