Як відключити set -e для окремої команди?


36

Команда set -e робить скрипт bash негайно, коли будь-яка команда повертає ненульовий код виходу.

  1. Чи є простий і елегантний спосіб відключити цю поведінку для окремої команди в сценарії?

  2. У яких місцях ця функціональність задокументована у Довідковому посібнику Bash ( http://www.gnu.org/software/bash/manual/bashref.html )?

Відповіді:


29
  1. Щось на зразок цього:

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line
    

    Виконати:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
    
  2. Це описано у setвбудованій довідці:

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.
    

Те ж саме задокументовано тут: https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin .


Спасибі! Я знайшов ще одну можливість: #! / Bin / bash set -e # Відмінити наступний рядок, щоб побачити ефект -e ефект: #blubb if blubb; потім відлуння "Командна лялька була успішною". else echo "Командна помилка помилка. Код виходу: $?" fi echo нормальний вихід сценарію
Gustave

22

Альтернативою невдачі застави на помилку було б примусити успіх незалежно від того. Ви можете зробити щось подібне:

cmd_to_run || true

Це поверне 0 (вірно), тому множину -e не слід запускати


3
faulty_cmd || :- це ще одна популярна ідіома для цього. (Команда :є синонімом до true).
ulidtko

3
@ulidtko - цікаво. Повели мене в кролячу нору, щоб знайти цей stackoverflow.com/questions/3224878/…, щоб отримати історію на істину проти:
Ерні

12

Якщо ви намагаєтеся зловити код повернення / помилки (функція або виделка), це працює:

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

Якщо застосовано "ігнорувати параметр оболонки негайно", це залежить від контексту виконуваної команди (див. Розділ Довідник керівництва Bash про Set Builtin - завдяки Аркадіушу Драбчику).

Особливо, варіант ігнорується, якщо команда є частиною тесту в операторі if. Тому можна виконати команду і перевірити її успіх чи невдачу в "контексті виходу негайно", використовуючи оператор if, як це:

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

Можна опустити оператор "тоді" і використовувати менше рядків:

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

Ще один підхід, який я вважаю досить простим (і стосується інших setваріантів на додаток до -e):

Скористайтеся $-для відновлення налаштувань.

Наприклад:

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

Хоча -eконкретно, варіанти, які інші розробляли ( || trueабо "помістили всередину if"), можуть бути більш ідіоматичними.


0

У мене насправді було подібне питання нещодавно (хоча я не публікував, я обійшов його), і, як я бачу, здається, що просто використання set + e перед командою і set -e згодом працює найелегантніше. Ось приклад, схопивши відповідь команди і не допустивши, щоб помилка викинула її.

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

Це захоплює висновок "фортуна", перевіряючи його вихідний стан, і лунає і каже це. Я думаю, це те, про що ви просили, або принаймні щось подібне? У будь-якому випадку, сподіваюся, що це допомагає.


Для уточнення, я вважаю, що біт у фігурних круглих дужках переспрямовується на / dev / null - це те, що ви шукаєте. Це змушує команду не мати вихід та перевіряє її стан помилок, не виходячи з програми.
Аддісон Кримп

0

Мені подобається запускати передплату, якщо хочете щось тимчасово змінити. Нижче команда демонструє, що перший bad_command ігнорується, а другий перериває виконання.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.