Изучаем Bash. Как не отправить все в /dev/null

2 minutes read in Linux

В скрипте инициализации RHEL допущена ошибка, приводящая к удалению всех файлов

Не делать assert’ов в критических точках приложения – отличный способ выстрелить в ногу с рикошетом в голову.

Пример из новости выше:

stop
rm -rf $SQUID_PIDFILE_DIR/*
start

Без контекста заметить проблему трудно, но точно известно если переменная SQUID_PIDFILE_DIR не будет определена мы выполним:

rm -rf /*

Веселого в этом мало, a для того чтобы избежать таких ситуаций (которые могут легко возникнуть в большом BASH скрипте) нужно было использовать следующую проверку:

stop
[ -z "$SQUID_PIDFILE_DIR" ] || exit 42
rm -rf $SQUID_PIDFILE_DIR/*
start

При таком подходе мы бы никогда не вызвали команду rm на корне файловой системы.

Про контрактное программирование на Java можно почитать здесь.

Bonus: ShellCheck

ShellCheck – замечательная тулза, обязательна для использования как начинающими, так и продолжающмим скрипто писателями.

Чтобы показать полезность, прогоним кусок показанный выше, через ShellCheck:

$ cat myscript.sh
rm -rf $SQUID_PIDFILE_DIR/*
$ shellcheck myscript.sh

Line 1:
rm -rf $SQUID_PIDFILE_DIR/*
^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
       ^-- SC2115: Use "${var:?}" to ensure this never expands to /* .
       ^-- SC2086: Double quote to prevent globbing and word splitting.

$ 

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

Выводы:

  1. Bash коварен
  2. Не пишите на Bash
  3. Если все же пишите, используйте ShellCheck

← Use of '_' as an identifier might not be supported in releases after Java SE 8 Семантика Enum в Java →