Есть ли краткий способ проверить состояние выхода набора команд в bash?

У меня есть простой скрипт для извлечения данных с удаленного сервера, поскольку процесс генерирует их с помощью rsync:

while :
do
    rsync -avz --remove-source-files -e ssh me@remote:path/to/foo* ./

    rsync -avz --remove-source-files -e ssh me@remote:path/to/bar* ./

    rsync -avz --remove-source-files -e ssh me@remote:path/to/baz* ./

    rsync -avz --remove-source-files -e ssh me@remote:path/to/qux* ./

    sleep 900 #wait 15 minutes, try again
done

Если нет файлов, rsync возвращает статус выхода 12 (по-видимому). В случае, если ни один из вышеперечисленных rsync находит любые данные, которые я хотел бы вырвать из цикла (процесс, генерирующий данные, вероятно, завершился). Чтобы избежать путаницы, я не хочу выходить из цикла, если хотя бы 1 из rsync процессы успешны.

Есть краткий способ сделать это в Bash?

3 ответа

Решение

Этот способ подсчитывает количество сбоев из-за отсутствия файла.

while :
do
    nofile=0

    rsync -avz --remove-source-files -e ssh me@remote:path/to/foo* ./
    (( $? == 12 )) && let nofile++

    rsync -avz --remove-source-files -e ssh me@remote:path/to/bar* ./
    (( $? == 12 )) && let nofile++

    rsync -avz --remove-source-files -e ssh me@remote:path/to/baz* ./
    (( $? == 12 )) && let nofile++

    rsync -avz --remove-source-files -e ssh me@remote:path/to/qux* ./
    (( $? == 12 )) && let nofile++

    # if all failed due to "no files", break the loop
    if (( $nofile == 4 )); then break; fi

    sleep 900 #wait 15 minutes, try again
done

Вы можете сделать это, сложив возвращаемые значения, так что если они все возвращают 12, сумма равна 48:

while :
do
    rc=0
    rsync -avz --remove-source-files -e ssh me@remote:path/to/foo* ./
    let rc+=$?

    rsync -avz --remove-source-files -e ssh me@remote:path/to/bar* ./
    let rc+=$?

    rsync -avz --remove-source-files -e ssh me@remote:path/to/baz* ./
    let rc+=$?

    rsync -avz --remove-source-files -e ssh me@remote:path/to/qux* ./
    let rc+=$?

    if [[ $rc == 48 ]]; then  # 48 = 4 * 12
         break;
    fi

    sleep 900 #wait 15 minutes, try again
done

Обратите внимание, что это может пострадать, если вы получите другую комбинацию кодов возврата сумм до 48, то есть 0 + 0 + 12 + 36

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

while :
do
    do_continue=0

    rsync -avz --remove-source-files -e ssh me@remote:path/to/foo* ./ && do_continue=1
    rsync -avz --remove-source-files -e ssh me@remote:path/to/bar* ./ && do_continue=1
    rsync -avz --remove-source-files -e ssh me@remote:path/to/baz* ./ && do_continue=1
    rsync -avz --remove-source-files -e ssh me@remote:path/to/qux* ./ && do_continue=1

    if [[ $do_continue == 0 ]]; then 
       break
    fi

    sleep 900 #wait 15 minutes, try again
done

который может быть реорганизован больше для удаления оператора разрыва и соответствующего условного теста:

do_continue=1
while [ do_continue -eq 1 ]; do
    do_continue=0
    rsync -avz --remove-source-files -e ssh me@remote:path/to/foo* ./ && do_continue=1
    #...
    sleep 900
done
Другие вопросы по тегам