Bash set e что это
Перейти к содержимому

Bash set e что это

  • автор:

Безопасные bash-скрипты или set -euxo pipefail

В 2020 году когда есть такие языки как python, ruby и go, использовать bash приходится редко, но иногда без него не обойтись.

Bash не похож на высокоуровневые языки программирования, он не предоставляет привычных гарантий. К примеру, если в python обратиться к неинициализированной переменной, то скрипт тут же завершиться, не выполнив ни одной инструкции. В bash это не так, любая переменная, к которой вы обратились, но не инициализировали, будет заменена на пустую строку. Только представьте сколько можно наворотить дел, если подобная переменная была в параметрах у команды rm -rf .

К счастью, можно изменить поведение оболочки используя встроенные функции, в частности set. С ее помощью, можно значительно повысить безопасность.

set -e

Указав параметр -e скрипт немедленно завершит работу, если любая команда выйдет с ошибкой. По-умолчанию, игнорируются любые неудачи и сценарий продолжет выполнятся. Если предполагается, что команда может завершиться с ошибкой, но это не критично, можно использовать пайплайн || true .

#!/bin/bash ./non-existing-command echo "RUNNING" # output # ------ # line 3: non-existing-command: command not found # RUNNING 

С использованием -e :

#!/bin/bash set -e ./non-existing-command || true ./non-existing-command echo "RUNNING" # output # ------ # line 4: non-existing-command: command not found # line 5: non-existing-command: command not found 

set -o pipefail

Но -e не идеален. Bash возвращает только код ошибки последней команды в пайпе (конвейере). И параметр -e проверяет только его. Если нужно убедиться, что все команды в пайпах завершились успешно, нужно использовать -o pipefail .

#!/bin/bash set -e ./non-existing-command | echo "PIPE" echo "RUNNING" # output # ------ # PIPE # line 4: non-existing-command: command not found # RUNNING 

С использованием -o pipefail :

#!/bin/bash set -eo pipefail ./non-existing-command | echo "PIPE" echo "RUNNING" # output # ------ # PIPE # line 4: non-existing-command: command not found 

set -u

Наверно самый полезный параметр — -u . Благодаря ему оболочка проверяет инициализацию переменных в скрипте. Если переменной не будет, скрипт немедленно завершиться. Данный параметр достаточно умен, чтобы нормально работать с переменной по-умолчанию $ и условными операторами ( if , while , и др).

#!/bin/bash echo "$MY_VAR>" echo "RUNNING" # output # ------ # # RUNNING 

С использованием -u :

#!/bin/bash set -u echo "$MY_VAR>" echo "RUNNING" # output # ------ # line 4: MY_VAR: unbound variable 

set -x

Параметр -x очень полезен при отладке. С помощью него bash печатает в стандартный вывод все команды перед их исполнением. Стоит учитывать, что все переменные будут уже доставлены, и с этим нужно быть аккуратнее, к примеру если используете пароли.

#!/bin/bash MY_VAR="a" echo "$MY_VAR>" echo "RUNNING" # output # ------ # a # RUNNING 

С использованием -x :

#!/bin/bash set -x echo "$MY_VAR>" echo "RUNNING" # output # ------ # + MY_VAR=a # + echo a # a # + echo RUNNING # RUNNING 

Вывод

Не стоит забывать, что все эти параметры можно объединять и комбинировать между собой! Думаю, при работе с bash будет хорошим тоном начинать каждый сценарий с set -euxo pipefail .

What does set -e mean in a bash script?

I’m studying the content of this preinst file that the script executes before that package is unpacked from its Debian archive (.deb) file. The script has the following code:

#!/bin/bash set -e # Automatically added by dh_installinit if [ "$1" = install ]; then if [ -d /usr/share/MyApplicationName ]; then echo "MyApplicationName is just installed" return 1 fi rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf rm -Rf $HOME/.local/share/file-manager/actions/* fi # End automatically added section 

My first query is about the line:

set -e 

I think that the rest of the script is pretty simple: It checks whether the Debian/Ubuntu package manager is executing an install operation. If it is, it checks whether my application has just been installed on the system. If it has, the script prints the message «MyApplicationName is just installed» and ends ( return 1 mean that ends with an “error”, doesn’t it?). If the user is asking the Debian/Ubuntu package system to install my package, the script also deletes two directories. Is this right or am I missing something?

3,101 2 2 gold badges 31 31 silver badges 48 48 bronze badges
asked Oct 27, 2013 at 19:06
AndreaNobili AndreaNobili
41.2k 107 107 gold badges 327 327 silver badges 605 605 bronze badges
Oct 27, 2013 at 19:07

reason why you couldn’t find this in google: -e in your query is interpreted as negation. Try following query: bash set «-e»

Oct 31, 2014 at 22:08
@twalberg When I’ve asked myself the same question, I was looking at man set
Sep 3, 2017 at 17:09
if you’re looking how to turn it off, swap the dash to a plus prefix: set +e
Mar 13, 2018 at 6:37

@twalberg but asking real people is so much more interesting than just making a request from a robot ;-).

Apr 29, 2018 at 2:45

10 Answers 10

 -e Exit immediately if a command exits with a non-zero status. 

But it’s considered bad practice by some (bash FAQ and irc freenode #bash FAQ authors). It’s recommended to use:

trap 'do_something' ERR 

to run do_something function when errors occur.

720 1 1 gold badge 12 12 silver badges 29 29 bronze badges
answered Oct 27, 2013 at 19:39
Gilles Quénot Gilles Quénot
176k 41 41 gold badges 227 227 silver badges 226 226 bronze badges

What would the do_something be if I wanted the same semantics as «Exit immediately if a command exits with a non-zero status»?

May 14, 2014 at 2:37

The ERR trap is not inherited by shell functions, so if you have functions, set -o errtrace or set -E will allow you to just set the trap once and apply it globally.

Jul 17, 2015 at 18:21
does trap ‘exit’ ERR do anything different from set -e ?
Jul 11, 2016 at 20:58
if it’s bad practice then why it’s used in Debian packages?
Dec 7, 2016 at 6:35

It’s not universally considered bad practice. As with many disfavored language construct, it has its place. The main problem with it is that the behavior in edge cases is somewhat non-intuitive.

Dec 23, 2016 at 21:26

set -e stops the execution of a script if a command or pipeline has an error — which is the opposite of the default shell behaviour, which is to ignore errors in scripts. Type help set in a terminal to see the documentation for this built-in command.

answered Oct 27, 2013 at 19:14
Robin Green Robin Green
32.2k 16 16 gold badges 104 104 silver badges 187 187 bronze badges

It only stops execution if the last command in a pipeline has an error. There’s a Bash specific option, set -o pipefail which can be used to propagate errors so that the return value of the pipeline command is non-zero if one of the preceding commands exited with a non-zero status.

Nov 9, 2015 at 22:25

Keep in mind that -o pipefail means only that the exit status of the first non-zero (i.e. erroring in -o errexit terms) command of the pipeline is propagated to the end. The remaining commands in the pipeline still run, even with set -o errexit . For example: echo success | cat — <(echo piping); echo continues , where echo success represents a successful, but fallible command, will print success , piping , and continues , but false | cat - <(echo piping); echo continues , with false representing the command now erroring silently, will still print piping before exiting.

Aug 23, 2019 at 7:26

I found this post while trying to figure out what the exit status was for a script that was aborted due to a set -e . The answer didn’t appear obvious to me; hence this answer. Basically, set -e aborts the execution of a command (e.g. a shell script) and returns the exit status code of the command that failed (i.e. the inner script, not the outer script).

For example, suppose I have the shell script outer-test.sh :

#!/bin/sh set -e ./inner-test.sh exit 62; 

The code for inner-test.sh is:

#!/bin/sh exit 26; 

When I run outer-script.sh from the command line, my outer script terminates with the exit code of the inner script:

$ ./outer-test.sh $ echo $? 26 

3 2 2 bronze badges
answered Aug 5, 2016 at 22:54
10.2k 8 8 gold badges 47 47 silver badges 68 68 bronze badges
Thanks for the detail about the return status code :+1:.
Mar 8 at 20:57

As per bash — The Set Builtin manual, if -e / errexit is set, the shell exits immediately if a pipeline consisting of a single simple command, a list or a compound command returns a non-zero status.

By default, the exit status of a pipeline is the exit status of the last command in the pipeline, unless the pipefail option is enabled (it’s disabled by default).

If so, the pipeline’s return status of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.

If you’d like to execute something on exit, try defining trap , for example:

trap onexit EXIT 

where onexit is your function to do something on exit, like below which is printing the simple stack trace:

onexit()

There is similar option -E / errtrace which would trap on ERR instead, e.g.:

trap onerr ERR 

Examples

Zero status example:

$ true; echo $? 0 

Non-zero status example:

$ false; echo $? 1 

Negating status examples:

$ ! false; echo $? 0 $ false || true; echo $? 0 

Test with pipefail being disabled:

$ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $? 1 

Test with pipefail being enabled:

$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $? 1 

1 1 1 silver badge
answered Dec 20, 2015 at 13:31
157k 88 88 gold badges 680 680 silver badges 747 747 bronze badges

This is an old question, but none of the answers here discuss the use of set -e aka set -o errexit in Debian package handling scripts. The use of this option is mandatory in these scripts, per Debian policy; the intent is apparently to avoid any possibility of an unhandled error condition.

What this means in practice is that you have to understand under what conditions the commands you run could return an error, and handle each of those errors explicitly.

Common gotchas are e.g. diff (returns an error when there is a difference) and grep (returns an error when there is no match). You can avoid the errors with explicit handling:

diff this that || echo "$0: there was a difference" >&2 grep cat food || echo "$0: no cat in the food" >&2 

(Notice also how we take care to include the current script’s name in the message, and writing diagnostic messages to standard error instead of standard output.)

If no explicit handling is really necessary or useful, explicitly do nothing:

diff this that || true grep cat food || : 

(The use of the shell’s : no-op command is slightly obscure, but fairly commonly seen.)

Just to reiterate,

something || other 

is shorthand for

if something; then : nothing else other fi 

i.e. we explicitly say other should be run if and only if something fails. The longhand if (and other shell flow control statements like while , until ) is also a valid way to handle an error (indeed, if it weren’t, shell scripts with set -e could never contain flow control statements!)

And also, just to be explicit, in the absence of a handler like this, set -e would cause the entire script to immediately fail with an error if diff found a difference, or if grep didn’t find a match.

On the other hand, some commands don’t produce an error exit status when you’d want them to. Commonly problematic commands are find (exit status does not reflect whether files were actually found) and sed (exit status won’t reveal whether the script received any input or actually performed any commands successfully). A simple guard in some scenarios is to pipe to a command which does scream if there is no output:

find things | grep . sed -e 's/o/me/' stuff | grep ^ 

It should be noted that the exit status of a pipeline is the exit status of the last command in that pipeline. So the above commands actually completely mask the status of find and sed , and only tell you whether grep finally succeeded.

(Bash, of course, has set -o pipefail ; but Debian package scripts cannot use Bash features. The policy firmly dictates the use of POSIX sh for these scripts, though this was not always the case.)

In many situations, this is something to separately watch out for when coding defensively. Sometimes you have to e.g. go through a temporary file so you can see whether the command which produced that output finished successfully, even when idiom and convenience would otherwise direct you to use a shell pipeline.

Как использовать set и pipefail в сценариях Bash в Linux

Терминал Linux на экране ноутбука на синем фоне.

Фатмавати Ачмад Заэнури/Shutterstock.com

Команды Linux set и pipefail определяют, что произойдет, если в сценарии Bash произойдет сбой. Есть о чем подумать, чем остановиться или продолжаться.

Сценарии Bash и условия ошибок

Сценарии оболочки Bash великолепны. Они быстро пишутся и не требуют компиляции. Любое повторяющееся или многоэтапное действие, которое вам нужно выполнить, можно завернуть в удобный сценарий. А поскольку сценарии могут вызывать любые стандартные утилиты Linux, вы не ограничены возможностями самого языка оболочки.

Программы для Windows, мобильные приложения, игры — ВСЁ БЕСПЛАТНО, в нашем закрытом телеграмм канале — Подписывайтесь:)

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

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

Команды set и pipefile позволяют решить, что произойдет при возникновении подобных ошибок. Они также позволяют обнаруживать ошибки, даже если они происходят в середине цепочки конвейеров.

Вот как их использовать.

Демонстрация проблемы

Вот тривиальный скрипт Bash. Он выводит на терминал две строки текста. Вы можете запустить этот скрипт, если скопируете текст в редактор и сохраните его как «script-1.sh».

#!/bin/bash echo Это произойдет первым echo Это произойдет вторым

Чтобы сделать его исполняемым, вам нужно использовать chmod:

chmod +x скрипт-1.sh

Вам нужно будет запустить эту команду для каждого скрипта, если вы хотите запустить их на своем компьютере. Запустим скрипт:

Запуск простого скрипта без ошибок.

Две строки текста отправляются в окно терминала, как и ожидалось.

Немного изменим скрипт. Мы попросим ls указать сведения о несуществующем файле. Это не удастся. Мы сохранили это как «script-2.sh» и сделали его исполняемым.

#!/bin/bash echo Это произойдет первым ls imaginary-filename echo Это произойдет вторым

Когда мы запускаем этот скрипт, мы видим сообщение об ошибке от ls.

Запуск сценария и создание условия отказа.

Несмотря на сбой команды ls, сценарий продолжал выполняться. И хотя при выполнении скрипта произошла ошибка, код возврата из скрипта в оболочку равен нулю, что говорит об успехе. Мы можем проверить это, используя echo и $? переменная, которая содержит последний код возврата, отправленный в оболочку.

Проверка кода возврата для последнего выполненного скрипта.

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

Опция set -e

Параметр set -e (выход) вызывает завершение сценария, если какой-либо из процессов, которые он вызывает, генерирует ненулевой код возврата. Все, что не равно нулю, считается ошибкой.

Добавив опцию set -e в начало скрипта, мы можем изменить его поведение. Это «script-3.sh».

#!/bin/bash set -e echo Это произойдет первым ls imaginary-filename echo Это произойдет вторым

Если мы запустим этот скрипт, мы увидим эффект set -e.

Завершение скрипта при возникновении ошибки и правильная установка кода возврата.

Сценарий останавливается, и код возврата, отправляемый в оболочку, имеет ненулевое значение.

Устранение неполадок в трубах

Трубопровод усложняет задачу. Код возврата, который выходит из переданной по конвейеру последовательности команд, является кодом возврата последней команды в цепочке. Если произойдет сбой с командой в середине цепочки, мы вернемся к исходной точке. Этот код возврата будет потерян, и сценарий продолжит обработку.

Мы можем видеть эффекты конвейерных команд с разными кодами возврата, используя встроенные функции оболочки true и false. Эти две команды не более чем генерируют код возврата, равный нулю или единице соответственно.

истинное эхо $? ложное эхо $?

Встроенные команды оболочки bash true и false.

Если мы направим false в true — где false представляет неудачный процесс — мы получим код возврата true, равный нулю.

ложный | истинное эхо $?

Преобразование лжи в истину.

В Bash есть переменная массива с именем PIPESTATUS, которая фиксирует все коды возврата каждой программы в цепочке конвейеров.

Использование PIPESTATUS для просмотра кода возврата всех программ в цепочке каналов.

PIPESTATUS хранит коды возврата только до тех пор, пока не запустится следующая программа, и попытка определить, какой код возврата соответствует той или иной программе, может очень быстро привести к путанице.

Вот тут-то и появляются set -o (параметры) и pipefail. Это «script-4.sh». Это попытается передать содержимое несуществующего файла в wc.

#!/bin/bash set -e echo Это произойдет сначала cat script-99.sh | wc -l echo Это произойдет через секунду

Это терпит неудачу, как мы и ожидали.

Запуск скрипта с ошибкой в ​​цепочке каналов.

Первый ноль — это вывод wc, говорящий нам, что он не прочитал ни одной строки для отсутствующего файла. Второй ноль — это код возврата из второй эхо-команды.

Мы добавим -o pipefail , сохраним его как «script-5.sh» и сделаем исполняемым.

#!/bin/bash set -eo pipefail echo Это произойдет сначала cat script-99.sh | wc -l echo Это произойдет через секунду

Давайте запустим это и проверим код возврата.

Запуск сценария, который перехватывает ошибки в цепочках каналов и правильно устанавливает код возврата.

Сценарий останавливается, а вторая команда echo не выполняется. Код возврата, отправленный в оболочку, равен единице, правильно указывающей на сбой.

Перехват неинициализированных переменных

Неинициализированные переменные может быть трудно обнаружить в реальном скрипте. Если мы попытаемся вывести значение неинициализированной переменной, echo просто напечатает пустую строку. Это не вызывает сообщение об ошибке. Остальная часть скрипта будет продолжать выполняться.

#!/bin/bash set -eo pipefail echo “$notset” echo “Другая эхо-команда”

Мы запустим его и понаблюдаем за его поведением.

Запуск скрипта, который не захватывает неинициализированные переменные.

Сценарий обходит неинициализированную переменную и продолжает выполняться. Код возврата равен нулю. Попытка найти подобную ошибку в очень длинном и сложном сценарии может быть очень сложной.

Мы можем перехватить этот тип ошибки, используя опцию set -u (unset). Мы добавим это в нашу растущую коллекцию установленных параметров в верхней части скрипта, сохраним его как «script-7.sh» и сделаем его исполняемым.

#!/bin/bash set -eou pipefail echo “$notset” echo “Другая команда echo”

Запуск скрипта, который захватывает неинициализированные переменные.

Обнаружена неинициализированная переменная, сценарий останавливается, а код возврата устанавливается равным единице.

Опция -u (unset) достаточно интеллектуальна не срабатывать ситуациями, когда вы можете законно взаимодействовать с неинициализированной переменной.

В «script-8.sh» скрипт проверяет, инициализирована ли переменная New_Var или нет. Вы не хотите, чтобы сценарий останавливался на этом, в реальном сценарии вы будете выполнять дальнейшую обработку и разбираться с ситуацией самостоятельно.

Обратите внимание, что мы добавили параметр -u в качестве второй опция в операторе set. Опция -o pipefail должна быть последней.

#!/bin/bash set -euo pipefail, если [ -z “$” ]; затем эхо “New_Var не имеет назначенного значения”. фи

В «script-9.sh» проверяется неинициализированная переменная, и если она неинициализирована, вместо нее предоставляется значение по умолчанию.

#!/bin/bash set -euo pipefail default_value=484 Value=$ echo “New_Var=$Value”

Сценарии разрешено выполнять до их завершения.

Запуск двух сценариев, в которых неинициализированные переменные обрабатываются внутри, а параметр -u не срабатывает.

Запечатанный топором

Еще одна удобная опция — set -x (выполнить и распечатать). Когда вы пишете сценарии, это может быть спасением. он печатает команды и их параметры по мере их выполнения.

Это дает вам быструю «грубую и готовую» форму трассировки выполнения. Выделение логических ошибок и обнаружение ошибок становится намного проще.

Мы добавим параметр set -x в «script-8.sh», сохраним его как «script-10.sh» и сделаем исполняемым.

#!/bin/bash set -euxo pipefail, если [ -z “$” ]; затем эхо “New_Var не имеет назначенного значения”. фи

Запустите его, чтобы увидеть линии трассировки.

Запуск сценария со строками трассировки -x, записанными на терминал.

Выявить ошибки в этих тривиальных примерах скриптов несложно. Когда вы начнете писать более сложные сценарии, эти опции окажутся полезными.

Программы для Windows, мобильные приложения, игры — ВСЁ БЕСПЛАТНО, в нашем закрытом телеграмм канале — Подписывайтесь:)

unixforum.org

патченный БАШ / bash — стал вести себя странно с оператором «set -e»
точнее, стал выбрасывать из скрипта по непонятным причинам, не смотря на то, что оператор, на котором происходил выход из скрипта — отрабатывал без ошибок

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

#!/bin/sh clear; set -e HOST=xxx.xxx.xxx.xxx PTR=~/tmp/mnt_$ ( mkdir -p $ sudo umount -l $ > /dev/null ) sshfs root@$:/ $ -p XXXXX -o allow_other # . другие команды $ mount | grep $

сначал а установил самый последний БАШ
bash-4.3.0 patch to 4.3.30

и заметил, что перестали нормально работать slackBuild-скрипты, которые раньше нормально отрабатывали

подумал, что навый БАШ непереваривает старые оси, ладно, установил заплаты на «свой родной баш»
bash-3.2.48 patch to 3.2.57

и та же самая история, slackBuild-скрипты перестали отрабатывать. доходят до команды make — и вываливаются, несмотря на то, что сама команда отрабатывает без ошибок

в конечном итоге перестали работать около 100 пользовательских баш-скриптов
откатился на старый-дырявый баш

на десктопе такой откат — не существеннен, а вот на сервере.

что то случилось в мире опенсорса пока я отсутствовал? :о)
какие будут комментарии?

slackware 12.2
kernel 2.6.32.63-smp
kde-tde 3.5.12

bash-3.2.48
with patches: bash32-049 — bash32-057

bash-4.3
with patches: bash43-001 — bash43-030

основная проблема решена, остался один вопрос

>> видимо у меня наследование «set -e» в «Bashe» отключено
>> AFAIK зависит от дистрибутива.
как это «регулируется», ни кто не подскажет?

если я ошибаюсь, то поправьте а не критикуйте :о)
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: патченный bash & set -e, странное поведение

Сообщение Bizdelnick » 11.11.2014 10:21

11.11.2014 04:46

Во-первых, ! пропущен, во-вторых, если скрипт завязан на типичное только для bash поведение, то пишите

#!/bin/bash

Вы на 100% уверены, что /bin/sh у Вас — это bash?

P. S. Попозже поисследую поведение bash’а у себя.

Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:
SLEDopit Модератор Сообщения: 4817 Статус: фанат консоли (= ОС: GNU/Debian, RHEL

Re: патченный bash & set -e, странное поведение

Сообщение SLEDopit » 11.11.2014 10:50

11.11.2014 04:46
а сейчас вываливается из скрипта после команды монтирования

а вы не пробовали эту команду отдельно запустить и посмотреть exit code?
ну или отключить set -e и выводить exit code в скриптах?

UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don’t do mistakes, the more bugs are in your code.

Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: патченный bash & set -e, странное поведение

Сообщение Bizdelnick » 11.11.2014 12:13

Посмотрел на скрипт более внимательно.
11.11.2014 04:46

mkdir -p $ sudo umount -l $ > /dev/null

Если в каталог $ ничего не смонтировано (в том числе если он только что создан), то umount завершится с ненулевым статусом, и в случае set -e завершится и сам скрипт. Чтобы работало, как Вы хотели, надо делать как-то так:

sudo umount -l $ 2> /dev/null || true

Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: патченный bash & set -e, странное поведение

Сообщение Bizdelnick » 11.11.2014 12:59

Что могло измениться в bash — это наследование сабшеллом опции -e. Если Ваш скрипт раньше работал, значит, она не наследовалась (или /bin/sh был не bash, а другим шеллом, в котором в принципе нет такой опции). Теперь наследуется (у меня тоже).

GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu)
bash 4.2+dfsg-0.1+deb7u3

Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:
sunjob Сообщения: 314 Контактная информация:

Re: патченный bash & set -e, странное поведение

Сообщение sunjob » 13.11.2014 07:09

1.
#!/bin/sh — правильно написано, конечно же была опечатка

2.
on slackware sh —> bash

эти строки взяты в скобки, раньше я думал (а собственно так и работало) что скобки
— сохраняют текущий каталог, при выходе из скобок
— не выбрасывают из скрипта, если внутри скобок произошла «ошибка»

и все время, пока я «писал скрипты» — «это правило» так и работала (да, собственно оно и сейчас так же работает, т.е. ошибка «umount» — не приводит к выходу из скрипта, скрипт далее работает, монтирует удаленную папку итд.

ошибку и выход вызывала далее идущая команда (я ее не показал в начале)

которая не была взята в скобки (далее вооще темная история)

дело в том, что вместе с башем был обнавлен и пакет
fuse-2.8.5
—>
fuse-2.9.3

все идущие следом за вер. 2.8.5 вт.ч. и последняя ver. fuse-2.9.3 — не показывавет точку
монтирования, точнее вывод точки монтирования в команде «mount» (если удаленный каталог был смонтирован с пом. «sshfs»)

ни чего не показывала, т.е. на этом мы и вываливались из скрипта

как только не крутил ключи конфигуратора, пересобирал, все равно не вернул «нормальное поведение» для «fuse» — точка монтирования не показывалась командой «mount»

ладушки, обновил, по рекомендациям сообщений конфигуратора «fuse»
util-linux-ng-2.14.1
—>
util-linux-2.19-i486

пересобрал все зависимости — итог, все равно fuse — не кажет точку монтирования

в итоге откатился до работающих версий

далее, как выяснилось большинство скриптов перестали работать из-за такого поведения команды «fuse-mount» (т.е. данная проблема решилась)

остались неск. скриптов, с непонятным «новым поведением», с ними разбираюсь (далее отпишусь)

появился новый вопрос:
КАК ВЕРНУТЬ ПРАВИЛЬНОЕ ПОВЕДЕНИЕ FUSE-MOUNT (т.е. что бы команда «mount» — нормально показывала смонтированный «sshfs» удаленный каталог)

спасибо за участие

если я ошибаюсь, то поправьте а не критикуйте :о)
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: патченный bash & set -e, странное поведение

Сообщение Bizdelnick » 13.11.2014 10:19

13.11.2014 07:09

эти строки взяты в скобки, раньше я думал (а собственно так и работало) что скобки
— сохраняют текущий каталог, при выходе из скобок
— не выбрасывают из скрипта, если внутри скобок произошла «ошибка»

Всё, что делают скобки, — это запускают то, что в них заключено, в отдельном сабшелле. Что там происходит с наследованием опции -e, из документации мне не понятно, но, как я писал выше, у меня на данный момент она наследуется.
Да, если нужно просто сохранить текущий каталог, более эффективно использовать pushd/popd.

13.11.2014 07:09

все идущие следом за вер. 2.8.5 вт.ч. и последняя ver. fuse-2.9.3 — не показывавет точку
монтирования, точнее вывод точки монтирования в команде «mount» (если удаленный каталог был смонтирован с пом. «sshfs»)

ни чего не показывала, т.е. на этом мы и вываливались из скрипта

А покажите-ка ls -l /etc/mtab .
Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:
sunjob Сообщения: 314 Контактная информация:

Re: патченный bash & set -e, странное поведение

Сообщение sunjob » 13.11.2014 15:45

$ ls -l /etc/mtab
-rw-r—r— 1 root root 505 2014-11-13 19:41 /etc/mtab

$ cat /etc/mtab
/dev/sda1 / reiserfs rw,noatime,data=writeback 0 0
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
/dev/sda6 /home reiserfs rw,noatime,data=writeback 0 0
/dev/sda2 /mnt/hdd2 reiserfs rw,noatime,data=writeback 0 0
tmpfs /dev/shm tmpfs rw,noatime,size=8192m,mode=1777 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,noatime,mode=1777 0 0
tmpfs /var/lock tmpfs rw,noexec,nosuid,nodev,noatime,mode=1777,size=10m 0 0
root@192.168.0.251:/ /home/sun/tmp/mnt_192.168.0.251 fuse.sshfs rw,nosuid,nodev,allow_other,user=sun 0 0

это вывод с нормально работающим sshfs
т..е не понятно что должно было быть или наоборот.
поясните ваши подозрения или мысли

p.s.
долго вспоминал, что где то проскакивала нечто связанное с «mtab»
проблема решена, короче, надо было
— установить новый «util-linux-2.19»
— пересобрать «fuse-2.8.5» с опцией разрешающей работу с «mtab»
— пересобрать «sshfs-fuse-2.5»

так что проблема с поведением «fuse» решена

осталось некоторое непонятное поведение баша с неск. скриптами
разбираюсь.

Всё, что делают скобки, — это запускают то, что в них заключено, в отдельном сабшелле. Что там происходит с наследованием опции -e, из документации мне не понятно, но, как я писал выше, у меня на данный момент она наследуется.
видимо у меня наследование отключено

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *