Виклик декількох скриптів bash та запуск їх паралельно, а не послідовно


19

Припустимо , що у мене є три (або більше) Баш сценаріїв: script1.sh, script2.shі script3.sh. Я хотів би зателефонувати всім цим сценаріям і запустити їх паралельно . Один із способів зробити це - просто виконати такі команди:

nohup bash script1.sh &
nohup bash script2.sh &
nohup bash script3.sh &

(Як правило, сценарії можуть зайняти кілька годин або днів, тому я хотів би використовувати nohupтак, щоб вони продовжували працювати, навіть якщо моя консоль закривається.)

Але чи існує спосіб виконання цих трьох команд паралельно з одним викликом?

Я думав про щось подібне

nohup bash script{1..3}.sh &

але це, здається, виконується script1.sh, script2.shі script3.shв послідовності, не паралельно.


2
Що означає "єдиний дзвінок"?
jw013

1
Який випадок використання? У вас є мільйон сценаріїв для запуску?
l0b0

@ jw013 Я маю на увазі щось подібне до однієї команди з короткими рядками. Якщо у мене є 100 сценаріїв для початку, я хотів би мати можливість ввести щось коротке (наприклад, nohup bash script{1..100}.sh &або for i in {1..100}; do nohup bash script{1..100} &; done), а не вводити nohup bash script*.sh &100 різних разів.
Андрій

1
Якщо сценарії мають корисний вихід: Ви також можете їх запустити всередині screen(або tmux), щоб вирішити проблему консолі, але зберегти доступ до виводу (та вводу).
Хоуке Лагінг

1
Ніщо не заважає вам вводити всі 3 команди в одному рядку. nohup ... & nohup ... & nohup ... &. Якщо ви маєте на увазі, що ви хочете запустити всі сценарії, не вводячи кожне ім'я скрипта окремо, це зробить простий цикл.
jw013

Відповіді:



14

Кращим способом було б використання паралельної GNU . Паралель GNU проста і за допомогою неї ми можемо контролювати кількість завдань, які потрібно виконати паралельно, з більшим контролем над робочими місцями.

У нижченаведеній команді script{1..3}.shрозширюється і bashпаралельно надсилається як аргументи . Тут -j0вказується, що потрібно виконати якомога більше завдань. За замовчуванням parallelвиконує одне завдання для одного ядра процесора.

$ parallel -j0 bash :::: <(ls script{1..3}.sh)

І ви також можете спробувати використовувати

$ parallel -j0 bash ::: script{1..3}.sh

Під час виконання другого методу, якщо ви отримуєте повідомлення про помилку, це означає, що цей --tollefпараметр встановлений, /etc/parallel/configі його потрібно видалити, і кожна річ буде працювати нормально.

Ви можете прочитати довідкову GNU Parallelsсторінку тут для багатших можливостей.

І якщо ви виконуєте завдання з віддаленої машини, краще використовуйте screenтак, щоб сеанс не закривався через проблеми з мережею. nohupце не обов'язково, оскільки останні версії bash, що надходять з huponexitas, offі це не дозволить батьківській оболонці надсилати HUPсигнал своїм дітям під час виходу. У випадку, якщо його не встановлено, зробіть це

$ shopt -u huponexit  

Якщо ви збираєтесь використовувати, bashоскільки оболонку parallel -j0 bash :::: <(ls script{1..3}.sh)можна звести parallel -j0 bash :::: script{1..3}.sh, ні?
iruvar

Ні його немає, коли '::::' використовується паралельно, це означає, що аргумент - це файл, який містить команди, які потрібно виконати, а не саму команду. Тут ми використовуємо підстановку процесу для перенаправлення імен скриптів у дескрипторі файлів.
Каннан Мохан

Ер .. у такому випадку чому б і ні parallel -j0 bash ::: script{1..3}.sh?
iruvar

Це bash ::: script{1..3}.shпередається parallel, ні ::: script{1..3}.sh. Таким чином , це має першим розширюватися parallel bash ::: script1.sh script2.sh script3.shоболонкою і потім parallelзакликання bash script1.sh, bash script2.sh, bash script3.sh. Я спробував це
iruvar

1
Ні, я не плутаюсь, я лише констатую, що проблема ОП краще вирішуватись parallel -j0 bash ::: script{1..3}.sh- це краще, ніж ::::підхід, оскільки це дозволяє уникнути необхідності заміни процесу. Також розбір виходу ls
прокочується

9

Ми також можемо використовувати xargsпаралельний запуск декількох скриптів.

$ ls script{1..5}.sh|xargs -n 1 -P 0 bash

тут кожен сценарій передається в bash як аргумент окремо. -P 0вказує на те, що кількість паралельного процесу може бути максимально можливим. Так само безпечніше використання bash за замовчуванням job control feature (&).


5

Рішення для однієї лінії :

$ nohup bash script1.sh & nohup bash script2.sh & nohup bash script3.sh &

Менш грамотно, просто використовуйте обгортковий сценарій:

$ cat script.sh
#!/usr/bin/env bash
script1.sh &
script2.sh &
script3.sh &
$ nohup script.sh &

Або петлю над ними:

for script in dir/*.sh
do
    nohup bash "$script" &
done

2

Якщо ви хочете заощадити собі певні зусилля

eval "nohup bash "script{1..3}.sh" &"

Або по другій думці, може, ні


1

Оформити цей інструмент: https://github.com/wagoodman/bashful

Скажімо , у вас є mytasks.yamlз

tasks:
    - name: A title for some tasks
      parallel-tasks:
        - cmd: ./script1.sh
        - cmd: ./script2.sh -x an-arg
        - cmd: ./script3.sh -y some-other-arg

І ви запускаєте це так:

nohup bashful run mytasks.yaml

Ваші сценарії виконуватимуться паралельно вертикальній смузі прогресу (+ ета, якщо ви запустили її раніше і час визначається). Ви можете налаштувати, скільки завдань, які ви хочете виконувати паралельно, якщо ви почнете виконувати більше, ніж лише дані 3:

config:
    max-parallel-commands: 6
tasks:
    ...

Відмова: Я автор.


0

Я пропоную набагато простішу утиліту, яку я щойно написав. Наразі він називається par, але незабаром буде перейменований у parl або pll, ще не вирішив.

https://github.com/k-bx/par

API настільки ж простий, як:

par "script1.sh" "script2.sh" "script3.sh"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.