Как использовать GNU Parallel

Как использовать параллель GNU с командой синхронизации aws?

У меня есть файл со следующими командами:

aws s3 cp ./test s3://test --recursive --content-encoding "gzip" --content-type "text/html" --cache-control "max-age=$MAXAGE" --exclude "*" --include "*.html" --profile $PROFILE

aws s3 cp ./test s3://test  $S3BUCKET --recursive --content-encoding "gzip" --content-type "text/html" --cache-control "max-age=$MAXAGE" --exclude "*" --include "*.css" --profile $PROFILE

Как я могу использовать GNU parallel для параллельного запуска этих команд?

Что я сделал, так это добавил команды в файл с именем test.sh.

и я запускаю следующую команду

parallel < test.sh

] Как передать аргументы в файл test.sh? Например, я хочу передать имя корзины aws.


person James Umeris    schedule 16.11.2015    source источник
comment
Если вы просто хотите запустить несколько команд параллельно, используйте & вместо GNU parallel.   -  person that other guy    schedule 17.11.2015
comment
который запускает его в фоновом режиме. Мне нужен GNU-параллель, чтобы при сбое одной команды не удавалось все   -  person James Umeris    schedule 17.11.2015
comment
Вы имеете в виду, что хотите поведения --halt 2?   -  person that other guy    schedule 17.11.2015
comment
Что делает останов --2?   -  person James Umeris    schedule 17.11.2015
comment
--halt 2 — это параллельная опция GNU, которая уничтожает все задания в случае сбоя одного из них. --halt 1 просто больше не выполняет никаких заданий, а это то, что & выполнит.   -  person that other guy    schedule 17.11.2015
comment
Это не отвечает на мой вопрос. Как я могу использовать GNu parallel для запуска вышеуказанных команд?   -  person James Umeris    schedule 17.11.2015
comment
Вы понимаете, что можете использовать &, и сделать так, чтобы ваш сценарий не работал, если какая-либо из команд не работает? Легко даже.   -  person Charles Duffy    schedule 17.11.2015
comment
... то есть: для этого вам не нужна параллель GNU; это огромный шар сложности (взгляните на источник, если вы сомневаетесь в этом!), и не добавляет никакой ценности для вашего непосредственного варианта использования.   -  person Charles Duffy    schedule 17.11.2015
comment
(Кроме того, что вы имеете в виду под плагином? Parallel не является плагином bash; существует поддержка расширений C для оболочки, которые добавляют новые встроенные модули, но их очень и очень мало).   -  person Charles Duffy    schedule 17.11.2015
comment
Чтобы было ясно, почему вы получаете ответы, которые не относятся к вашему буквальному вопросу: подумайте о ответе, который вы ожидаете, если кто-то спросит в Woodworking SE о том, как закручивать шурупы с помощью молотка.   -  person Charles Duffy    schedule 17.11.2015
comment
... что касается ответа на вопрос о том, как передавать аргументы, разве ответ @thatotherguy не отвечает на него адекватно?   -  person Charles Duffy    schedule 17.11.2015
comment
Если вам не нравится использовать export, вы можете просто сделать следующее (все в одной строке): S3BUCKET=foo MAXAGE=42 PROFILE=bar parallel --gnu <test.sh.   -  person Charles Duffy    schedule 17.11.2015


Ответы (2)


Если ваша цель состоит в том, чтобы вызвать сбой сценария в случае сбоя любого члена набора написанных от руки команд, GNU parallel не лучший инструмент для этой работы: сама оболочка уже предоставляет все необходимое с помощью команды wait, который указан в POSIX и присутствует во всех оболочках, совместимых со стандартами (см. также спецификацию , требующую, чтобы он был реализован как встроенный).

#!/bin/bash
#      ^^^^- Important! /bin/sh doesn't have arrays; bash, ksh, or zsh will work.

# For readability, put common arguments in an array
common_args=(
  --recursive
  --content-encoding "gzip"
  --content-type "text/html"
  --cache-control "max-age=$MAXAGE"
  --exclude "*"
  --profile "$PROFILE"
)

# Record PIDs of the various jobs in an array
pids=( )
aws s3 cp ./test s3://test             --include='*.html' "${common_args[@]}" & pids+=( $! )
aws s3 cp ./test s3://test "$S3BUCKET" --include='*.css'  "${common_args[@]}" & pids+=( $! )

# If either background job failed, exit the script with the same exit status
for pid in "${pids[@]}"; do
  wait "$pid" || exit
done

Обратите внимание, что массивы используются выше для удобства, а не по необходимости; вы можете предоставить общие аргументы с помощью функции и/или создать массив PID в скалярной переменной или переопределив "$@" внутри функции оболочки, если вашей целью было написать код, который будет работать на любой базовой оболочке POSIX.

person Charles Duffy    schedule 17.11.2015
comment
У меня есть около 10+ этих команд aws для запуска. Мне нужно, чтобы они работали одновременно - person James Umeris; 17.11.2015
comment
Приведенное выше действительно запускает команды aws s3 cp одновременно. Если вы хотите, чтобы на самом деле правильный цикл запускал эти задания, это тоже было бы легко, но ваш вопрос не дает многого для продолжения: настройка ответа сверх того, что я уже сделал. - person Charles Duffy; 17.11.2015
comment
(Вы, например, пытаетесь перебрать пары значений S3BUCKET и PROFILE?) - person Charles Duffy; 18.11.2015
comment
Нет, у меня есть 18 команд синхронизации aws. У них не у всех одинаковый S3bucket. 6 из них имеют одинаковое ведро S3 - person James Umeris; 18.11.2015
comment
... поэтому, если вы хотите использовать ответ здесь, вы можете скопировать шаблон с aws s3 ... & pids+=( $! ) для каждой команды, которую вы хотите запустить, и циклом wait для проверки состояния выхода после и выхода с ошибкой, если что-то не удалось. - person Charles Duffy; 18.11.2015
comment
Как мы выходим из 1, если есть ошибка с одной из команд? - person James Umeris; 18.11.2015
comment
@JamesUmeris, wait "$pid" || exit завершает работу с тем же статусом выхода, что и фоновая команда aws, pid которой обрабатывается, если это значение не равно нулю. (Я думал, что ясно понял это в комментариях к первоначально опубликованному сценарию). Если вы хотите exit 1 вместо копирования статуса выхода неудачной команды, это будет wait "$pid" || exit 1 вместо этого. - person Charles Duffy; 18.11.2015
comment
просто чтобы я понимал, что в случае сбоя команды код, который вы написали как есть (wait "$pid" || exit), завершится с 1 (для отказа). - person James Umeris; 18.11.2015
comment
Вам не нужны скобки - они их сломают. И, как я уже сказал, несколько раз он завершается с тем же статусом неудачной команды, который может быть или не быть 1. - person Charles Duffy; 18.11.2015
comment
... итак, если rsync завершается со статусом 8, то wait "$pid" || exit, получив PID этого rsync, закроет ваш скрипт со статусом 8. Очистить? - person Charles Duffy; 18.11.2015

Вы можете сделать это, экспортировав все необходимые переменные, а затем передав команды в parallel с цитируемой здесь документацией:

#!/bin/bash
export S3BUCKET="$1"
export MAXAGE=42
export PROFILE=foobar

parallel --gnu << 'EOF'
aws s3 cp ./test s3://test --recursive --content-encoding "gzip" --content-type "text/html" --cache-control "max-age=$MAXAGE" --exclude "*" --include "*.html" --profile $PROFILE
aws s3 cp ./test s3://test  $S3BUCKET --recursive --content-encoding "gzip" --content-type "text/html" --cache-control "max-age=$MAXAGE" --exclude "*" --include "*.css" --profile $PROFILE
EOF
person that other guy    schedule 17.11.2015