MyTetra Share
Делитесь знаниями!
Отладочные опции в BASH-скриптах
Время создания: 01.03.2023 17:53
Автор: Dmitriy Sokolov
Текстовые метки: linux, bash, опции, set, отладка, ошибки
Раздел: Компьютер - Linux - Bash - Программирование на Bash
Запись: xintrea/mytetra_syncro/master/base/1677682418v327ops9ht/text.html на raw.github.com

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

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

set -e

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

Без -e:


#!/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.

Без -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. Благодаря ему оболочка проверяет инициализацию переменных в скрипте. Если переменной не будет, скрипт немедленно завершиться. Данный параметр достаточно умен, чтобы нормально работать с переменной по-умолчанию ${MY_VAR:-$DEFAULT} и условными операторами (if, while, и др).

Без -u:


#!/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 печатает в стандартный вывод все команды перед их исполнением. Стоит учитывать, что все переменные будут уже доставлены, и с этим нужно быть аккуратнее, к примеру если используете пароли.

Без -x:


#!/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.


Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования