Эффективная проверка состояния выхода Bash для нескольких команд - PullRequest
247 голосов
/ 04 марта 2011

Есть ли что-то похожее на pipefail для нескольких команд, например оператор try, но внутри bash. Я хотел бы сделать что-то вроде этого:

echo "trying stuff"
try {
    command1
    command2
    command3
}

И в любой момент, если какая-либо команда завершится неудачно, выпадет и отобразит ошибку этой команды. Я не хочу делать что-то вроде:

command1
if [ $? -ne 0 ]; then
    echo "command1 borked it"
fi

command2
if [ $? -ne 0 ]; then
    echo "command2 borked it"
fi

И так далее ... или что-то вроде:

pipefail -o
command1 "arg1" "arg2" | command2 "arg1" "arg2" | command3

Потому что аргументы каждой команды, которой я верю (поправьте меня, если я ошибаюсь), будут мешать друг другу. Эти два метода кажутся мне ужасно скучными и неприятными, поэтому я призываю к более эффективному методу.

Ответы [ 14 ]

2 голосов
/ 25 октября 2015

Для рыбных раковин пользователей, которые наткнулись на эту тему.

Пусть foo будет функцией, которая не "возвращает" (эхо) значение, но устанавливает код выхода как обычно.
Чтобы избежать проверки $status после вызова функции, вы можете сделать:

foo; and echo success; or echo failure

А если он слишком длинный, чтобы поместиться в одну строку:

foo; and begin
  echo success
end; or begin
  echo failure
end
1 голос
/ 15 января 2019

Вы можете использовать потрясающее решение @ john-kugelman , найденное выше в системах, отличных от RedHat, закомментировав эту строку в своем коде:

. /etc/init.d/functions

Затем вставьте нижеприведенноекод в конце.Полное раскрытие: Это просто прямое копирование и вставка соответствующих битов вышеупомянутого файла, взятых из Centos 7.

Протестировано на MacOS и Ubuntu 18.04.


BOOTUP=color
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"

echo_success() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
    echo -n $"  OK  "
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 0
}

echo_failure() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo -n $"FAILED"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}

echo_passed() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo -n $"PASSED"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}

echo_warning() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo -n $"WARNING"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
} 
1 голос
/ 18 января 2018

Когда я использую ssh, мне нужно различать проблемы, вызванные проблемами подключения, и коды ошибок удаленной команды в режиме errexit (set -e). Я использую следующую функцию:

# prepare environment on calling site:

rssh="ssh -o ConnectionTimeout=5 -l root $remote_ip"

function exit255 {
    local flags=$-
    set +e
    "$@"
    local status=$?
    set -$flags
    if [[ $status == 255 ]]
    then
        exit 255
    else
        return $status
    fi
}
export -f exit255

# callee:

set -e
set -o pipefail

[[ $rssh ]]
[[ $remote_ip ]]
[[ $( type -t exit255 ) == "function" ]]

rjournaldir="/var/log/journal"
if exit255 $rssh "[[ ! -d '$rjournaldir/' ]]"
then
    $rssh "mkdir '$rjournaldir/'"
fi
rconf="/etc/systemd/journald.conf"
if [[ $( $rssh "grep '#Storage=auto' '$rconf'" ) ]]
then
    $rssh "sed -i 's/#Storage=auto/Storage=persistent/' '$rconf'"
fi
$rssh systemctl reenable systemd-journald.service
$rssh systemctl is-enabled systemd-journald.service
$rssh systemctl restart systemd-journald.service
sleep 1
$rssh systemctl status systemd-journald.service
$rssh systemctl is-active systemd-journald.service
0 голосов
/ 31 мая 2017

Проверка состояния функциональным образом

assert_exit_status() {

  lambda() {
    local val_fd=$(echo $@ | tr -d ' ' | cut -d':' -f2)
    local arg=$1
    shift
    shift
    local cmd=$(echo $@ | xargs -E ':')
    local val=$(cat $val_fd)
    eval $arg=$val
    eval $cmd
  }

  local lambda=$1
  shift

  eval $@
  local ret=$?
  $lambda : <(echo $ret)

}

Использование:

assert_exit_status 'lambda status -> [[ $status -ne 0 ]] && echo Status is $status.' lls

Выход

Status is 127
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...