Пушыстый (_winnie) wrote,
Пушыстый
_winnie

потому что в кузнице не было гвоздя

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


В свои bash-скрипты я вставляю
#!/usr/bin/env bash
set -euo pipefail



Опция -e останавливает скрипт если процесс вернул не 0 (и пишет в stderr на какой строке ошибка).

Это предотвращает беду, если в списке команд одна из фейлится:
svn up
build
copy some files
delete secret files
deploy build to external server

Опция -u останавливает скрипт, если используется неопределённая переменная. Это предотвращает беду например в таких случаях:

tar -czf download.tarball.tar.gz "$PROJECT_DIR/bin"

Если почему-то PROJECT_DIR не определена, то пакуется и отправляется пользователям системная /bin, вместо скомпилированых файлов проекта. И есть менеее забавные фейлы, превращение rm -rf "$1/$2" в rm -rf "/" со стиранием всего.

В комбинации с предыдущей опцией - опечатки в переменных окружения перестают быть непредсказуемым каскадно-гвоздевым фейерверком.
опция -o pipefail фейлит выполнение пайпа, если один из подкомпонентов выполняется с ошибкой. Например,
cat файл_который_не_существует | iconv -f cp1251 -t UTF-8 > результирующий файл.


Ожидаемые ошибки я игнорирую явно.
Если мне похрен на результат команды, вставляю || true после неё
cmd || true #'||' запускает вторую команду, если первая вернула не ноль. '||' можно читать "а иначе".

Если я удаляю папку, которая может не существовать, я явно проверяю что она есть перед удалением:
test -d dir_to_delete && rm -r dir_to_delete.

grep с пустым выводом возвращает код 1, и код ошибки 2 если есть реальная ошибка. Игнорирую коды меньше 2 явно:
cmd1 | (grep c || test $? -lt 2) | cmd2. # $? - код возврата,  test A -lt B - сравнение


Я не знаю, как удобным образом проверить ошибки в cmd2 в таком коде:
cmd1 $(cmd2)
. Подскажите?

Я не эксперт по "портабельному sh", поэтому если используете #!/bin/sh который ссылка на ksh/dash/bash/некий лже-POSIX, то надо смотреть в манах/гуглах какие есть опции.

В bat-файлах программировать надёжно сложно, и я не хочу внимательно вникать в cmd.exe, боюсь за свою психику.
Тем не менее, если я загоняю в bat-файл простой список команд, я в конце каждой команды ставлю || goto error или || exit /b 1 (или || pause если скрипт интерактивный, запускается всегда мышкой).

build || pause
copy some files || pause
delete secret files || pause
deploy build to external server || pause


Данная техника позволила в скрипте апдейта арта для дизайнеров найти тупые и хитрые ошибки в первые два месяца проекта (иначе бы мы с ними жили два года).

Ничего сложного на bat-файлах я стараюсь не писать, они в пять коварней чем C++, bash, assembler и perl вместе взятые.

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








Tags: release, shell, soft-dev
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 26 comments