?

Log in

No account? Create an account
nyaload

Журнал Пушыстого

Журнал Пушыстого

Previous Entry Share Flag Next Entry
потому что в кузнице не было гвоздя
nyaload
_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 вместе взятые.

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










  • 1
s/что оно падает/что команда внутри возвращает ошибку/

  • 1