Запускать параллельные оболочки и собирать коды выхода - PullRequest
1 голос
/ 03 февраля 2020

С помощью сценариев оболочки я делю один длинный файл данных на 8 файлов и запускаю их параллельно в 8 экземплярах.

function_child()
{
while read -r record
do
 ###process to get the data by arsdoc get##
    exit 12  ## if get fails##
 ### fp2pdf ###
    EXIT 12  ## IF AFP2PDF FAILS ###
 ### logic ###
    exit 12  ## if logic fails####
done < $1
}

## main ##
for file in /$MY_WORK/CCN_split_files/*; do
   proceed_task "$file" &
   PID="$!"
   echo "$PID:$file" | tee $tmp_file
   PID_LIST+="$PID "
done

как можно \ отслеживать код завершения и pid дочернего процесса когда происходит сбой. Я попробовал это ниже. После того, как все процессы отправлены в фоновый режим, я использую функцию «wait» для ожидания выхода PID из нашего PID_LIST, а затем захвата и печати соответствующего состояния выхода.

for process in "${PID_LIST[@]}";do
   wait "$process"
   exit_status=$?
   file_name=`egrep $process $tmp_file | awk -F ":" '{print $2}' | rev | awk -F "/" '{print $2}' | rev`
   echo "$file_name exit status: $exit_status"
done

но выдает ошибку

 line 49: wait: `23043 23049 ': not a pid or valid job spec
grep: 23049: No such file or directory

Может ли кто-нибудь помочь мне в этом, спасибо.

Ответы [ 4 ]

0 голосов
/ 10 февраля 2020

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

doit()  {
  record="$1"
  ###process to get the data by arsdoc get##
     exit 12  ## if get fails##
  ### fp2pdf ###
     EXIT 12  ## IF AFP2PDF FAILS ###
  ### logic ###
     exit 12  ## if logic fails####
}
export -f doit

cat /$MY_WORK/CCN_split_files/* |
  parallel --joblog my.log doit
# Field 7 of my.log is the exit value

# If you have an unsplit version of the input you can have GNU Parallel process it:
# cat /$MY_WORK/CNN_big_file |
#   parallel --joblog my.log doit


0 голосов
/ 03 февраля 2020

Двойные кавычки вокруг аргумента wait создают одну строку. Удалите кавычки, чтобы оболочка разбила строку на отдельные идентификаторы PID.

0 голосов
/ 03 февраля 2020

Используйте wait для правильных номеров pid.

function_child() {
    while read -r record; do
        # let's return a random number!
        exit ${RANDOM}
    done <<<'a'
}

mkdir -p my-home/dir
touch my-home/dir/{1..9}

for file in my-home/dir/*; do
    function_child "$file" &
    pid=$!
    echo "Backgrounded: $file (pid=$pid)"
    pids[$pid]=$file
done

for i in "${!pids[@]}"; do
    wait "$i"
    ret=$?
    echo ${pids[$i]} returned with $ret
done

выходы на repl :

Backgrounded: my-home/dir/1 (pid=84)
Backgrounded: my-home/dir/2 (pid=85)
Backgrounded: my-home/dir/3 (pid=86)
Backgrounded: my-home/dir/4 (pid=87)
Backgrounded: my-home/dir/5 (pid=88)
Backgrounded: my-home/dir/6 (pid=89)
Backgrounded: my-home/dir/7 (pid=90)
Backgrounded: my-home/dir/8 (pid=91)
Backgrounded: my-home/dir/9 (pid=92)
my-home/dir/1 returned with 241
my-home/dir/2 returned with 59
my-home/dir/3 returned with 235
my-home/dir/4 returned with 11
my-home/dir/5 returned with 6
my-home/dir/6 returned with 222
my-home/dir/7 returned with 230
my-home/dir/8 returned with 189
my-home/dir/9 returned with 195

Но я думаю, что просто используйте xargs или другое инструмент, предназначенный для параллельного запуска таких заданий.

 printf "%s\n" my-home/dir/* | xargs -n$'\n' -P8 sh -c 'echo "$1"; ###process to get the data by arsdoc get' --

@ KamilCuk, appologies, обновил код.

PID_LIST+="$PID " создает одну длинную переменную с пробелами , "${PID_LIST[@]}" - это расширение, используемое для массивов. Это работает так, что ${PID_LIST[@]} просто расширяется до значения переменной PID_LIST, как если бы "$PID_LIST", поэтому он расширяется до "23043 23049 ". Поскольку он находится в кавычках, он выполняет итерации по одному элементу, следовательно, он запускается wait "23043 23049 ", поэтому вы видите сообщение об ошибке.

Не рекомендуется: вы можете зависеть от разбиения пространства оболочки

for process in $PID_LIST; do
     wait "$process"

Но просто используйте массив:

    PID_LIST+=("$PID")
done

for process in "${PID_LIST[@]}"; do
    wait "$process"

Если вы чувствуете себя небезопасно с вашим ассоциативным массивом pids[$pid]=$file, используйте вместо него два массива:

     onlypids+=("$pid")
     files+=("$files")
done

for i in "${!onlypids[@]}"; do
     pid="${onlypids[$i]}"
     file="${files[$i]}"
     wait "$pid"

Обратите внимание, что условно переменная верхнего регистра имена для экспортируемых переменных.

0 голосов
/ 03 февраля 2020

См .: help jobs и help wait

Соберите статус возврата в конце вашего кода

for pid in $(jobs -rp); do
  printf "Job %d handling file %q is still running\n" "$pid" "${pids[pid]}"
done

for pid in ${jobs -sp); do
  printf "Job %s handling file %q has returned with status %d\n" "$pid" "${pids[pid]}" "$(wait "$pid")"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...