Использование GNU Parallel — как перевести текущую переданную строку в параллельную версию?

Использование GNU Parallel — как перевести текущую переданную строку в параллельную версию?

Я использую GNU Parallel и хочу понять — как мне передать отдельную строку каждой параллельной команде?

В качестве примера,Параллельная документация GNUпоказано, как переместить файлы из текущего каталога в другой:

ls | parallel mv {} destdir

Так есть ли способ получить/распечатать каждый файл по отдельности, который был передан в параллель?

Случай параллельной обработки

Мне нужно выполнить параллельную обработку проверки нескольких сайтов и записать

  • код возврата http (2xx, 4xx, 5xx)
  • Исходный URL-адрес
  • Конечный целевой URL
  • код выхода curl

Вот код, который это делает:

    unset return_code_array
    unset destination_url_array
    unset exit_code_array

    while read -r return_code_var destination_url_var exit_code_var; do

        destination_url_array+=("$destination_url_var")
        exit_code_array+=("$exit_code_var")
        return_code_array+=("$return_code_var")

    done < <(printf '%s\n' "${all_valid_URLs_array[@]}" | parallel -j 20 -k 'curl --max-time 20 -sL -o /dev/null -w "%{response_code} %{url_effective} " {}; printf "%s %s\n" "$?" ')

В результате у меня есть три массива, и они содержат код возврата HTTP, конечный целевой URL и статус кода выхода curl для каждой соответствующей строки для all_valid_URLs_arrayзаписей. В то же время мне нужно выполнить некоторую обработку для каждого destination_url_var— например, сравнить, соответствует ли он исходному URL, но я понятия не имею, как получить строку, которая была передана в parallels.

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

Спасибо.

решение1

В вашем примере 'curl … {}; printf "%s %s\n" "$?" '(почему второй %s?) есть кусок кода оболочки в одинарных кавычках. В нем вы можете использовать {}более одного раза:

curl … {}; printf "%s %s\n" "$?" {}

Альтернативно создайте переменную и используйте ее столько раз, сколько захотите. Имя переменной может быть описательным, это преимущество. Есть еще одно преимущество: в общем случае то, что заменяется, {}может быть длинной строкой, многократная замена может раздуть код, parallelкоторый будет передан определенным оболочкам. ИМХО, лучше заменить один раз и позволить оболочке сохранить строку и использовать ее повторно:

source_URL={}; curl … "$source_URL"; printf "%s %s\n" "$?" "$source_URL"

В случае GNU parallelбезопасно встраивать {}в код оболочки. Это исключение, явно упомянутое в этом ответе:Никогда не встраивайте {}в шелл-код!. Вы, вероятно, уже знаете это, замечание адресовано широкой аудитории.

Обратите внимание, что вам нужно настроить ваш readосновной цикл, теперь он должен считыватьсячетырепеременные. Таким образом вы перенесете исходный URL изнутри parallelв основной цикл, где вы сможете его сравнить destination_url_varили сделать с ним все, что захотите.

Однако при таком подходе «все, что вы хотите» не распараллеливается.

Если вы захватите вывод из curlотдельных переменных внутри кода оболочки, запущенного parallel(вместо того, чтобы просто вывести его для захвата за пределами parallel), то вы сможете выполнить сравнение (или что-то еще, что вам нужно)там, параллельно. И напримерprintf условно. Вам решать, где реализовать желаемую логику, главное, чтобы внутренняя часть parallelгенерировала вывод в форме, ожидаемой внешней частью read.

Переданный код оболочки parallelвсе еще должен быть заключен в одинарные кавычки. По мере его роста вам может потребоваться использовать (внедрять) одинарные кавычки в этот самый код; тогда цитирование станет несколько сложным и менее читаемым. В такой ситуации рассмотрите возможность перемещения кода в отдельный скрипт, где вы сможете цитировать независимо. Вы вызовете его из основного скрипта следующим образом:

while read … ; done < <( … | parallel -j 20 -k 'path/to/separate_script {}' )

Внутри separate_scriptзаменяемая строка {}будет доступна как $1(не забудьтезаключить его в двойные кавычки).

Связанный контент