Запустите набор команд и верните код ошибки, если какой-либо сбой - PullRequest
0 голосов
/ 18 января 2019

В проекте nodejs у меня есть ярлык yarn lint, который запускает пару линтеров таким образом:

lint_1 && lint_2 && lint_3

Если кто-либо из них находит ошибку, он возвращает код ошибки, в результате yarn lint сам возвращает код ошибки, в результате - сборка завершается неудачей.

Работает несколько отлично, перехватывает все ошибки, хотя есть небольшая проблема: если с кодом ошибки происходит сбой linter - остальные компоненты не будут выполняться.

Что бы я хотел - выполнить все из них (чтобы все они печатали все ошибки) и только после этого потерпеть неудачу.

Я знаю, что могу создать скрипт bash (который я буду запускать в yarn lint), запустить каждый из линтеров один за другим, собирая коды возврата, а затем проверить, не является ли какой-либо из кодов ненулевым - exit 1 и это не удастся yarn lint. Но мне интересно, есть ли более элегантный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Что бы я хотел - выполнить все из них (чтобы все они печатали все ошибки), и только после этого выполнить ошибку

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

result=0
if ! lint_1; then result=1; fi
if ! lint_2; then result=1; fi
if ! lint_3; then result=1; fi
exit "$result"

Как программист, я вижу, что у нас здесь есть шаблон. Таким образом, мы можем использовать массив, но bash не имеет двухмерных массивов. Это был бы обходной путь с eval для обхода указанных параметров. Это выполнимо. Вы должны использовать eval, чтобы дважды вычислить массив «указатель» / имя, но работает. Обратите внимание, что eval это evil.

cmds_1=(lint_1 "arg with spaces you pass to lint_1")
cmds_2=(lint_2)
cmds_3=(lint_3)

result=0
# compgen results list of variables starting with `cmds_`
# so naming is important
for i in $(compgen -v cmds_); do
    # at first, `$i` is only expanded
    # then the array is expanded `"${cmds_?[@]}"`
    if ! eval "\"\${$i[@]}\""; then
        result=1
    fi
done
exit "$result"

Мы также можем пойти с xargs . Из руководства EXIT STATUS есть 123 if __any__ invocation of the command exited with status 1-125. Если вы знаете, что ваши программы будут выходить из состояния выхода 1-125, то вы можете (обычно xargs в любом случае корректно обрабатывает различные состояния выхода (возвращает 123), но давайте оставаться в соответствии):

xargs -l1 -- bash -c '"$@"' -- <<EOF
lint_1 "arg with spaces you pass to lint_1"
lint_2
lint_3
EOF
result=$?          # or just exit "$?"
exit "$result"

, который выглядит странно чистым. Кстати, передав только -P <number of jobs> в xargs, вы можете выполнить всю команду параллельно. Вы можете приспособиться к диапазону ошибок 1-125, обработав ошибку внутри скрипта bash, т. Е.

xargs -l1 -- bash -c '"$@" || exit 1' -- <<EOF
lint_1 "arg with spaces you pass to lint_1"
lint_2
lint_3
EOF
result=$?
exit "$result"

И у меня есть другая идея. После каждой команды мы можем вывести возвращаемый статус по выделенному файловому дескриптору. Затем из всех возвращаемых статусов отфильтруйте нули и проверьте, есть ли в потоке другие статусы. Если они есть, мы должны выйти с ненулевым статусом. Это похоже на проделанную работу и в основном соответствует первому фрагменту кода, но if ! ....; then result=1; fi упрощено до ; echo $? >&10.

tmp=$(mktemp)
(
    lint_1 "arg with spaces you pass to lint_1"; echo $? >&10
    lint_2; echo $? >&10
    lint_3; echo $? >&10
) 10> >(
    [ -z "$(grep -v 0)" ]
    echo $? > "$tmp"
)
result="$(cat "$tmp"; rm "$tmp")"
exit "$result"

Из представленных вариантов я бы пошел с другим ответом;) или со вторым отсеченным xargs.

0 голосов
/ 18 января 2019

Вы можете перехватить ERR и установить флаг. Это запустит каждый из линтеров и завершит работу с ошибкой, если произойдет сбой любого из них:

#!/bin/bash
result=0
trap 'result=1' ERR
lint_1
lint_2
lint_3
exit "$result"         
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...