amarao (amarao_san) wrote,
amarao
amarao_san

Categories:

unix way

Идея: утилита делает одну вещь, но делает её хорошо.

Что значит "хорошо"? Что нам не надо прикладывать специальных усилий для борьбы с этой вещью ради того, что она делает. Утрируя: мне нужно запаковать файл, я делаю |gzip, а выходе имею запакованный файл. Утилита чуть-чуть присыпана опциями по вкусу, но сама идея от этого не меняется - на входе данные, на выходе архив.

С учётом, что паковка - математическая операция (чистая), ошибки от gzip мы можем получить только если у нас в системе что-то плохо (ENOMEM), либо что-то плохо "до/после" в пайпе. И нас это полностью устраивает, потому что gzip в режиме паковки не может генерировать ошибок, ассоциированных с входными данными. Мы можем смело полагать, что gzip нам не добавит сложности в обработке ошибок - ошибка либо системная (фатальная), либо на входе/выходе. Если мы считаем вход/выход тоже системными (cat, редирект), то ошибки становятся системными все. Нам достаточно увидеть ненулевой код возврата, чтобы знать, что "была системная ошибка и операция не удалась". Более того, за вычетом мелкого нюанса с ENOSPACE (где-то дальше по пайпу), мы можем считать, что операция транзакционная - либо сработало и запаковало, либо нет. То есть gzip в режиме паковки нам не добавляет головной боли. Берёшь и используешь. Идеальная утилита.

А теперь смотрим на распаковку. Что должен делать gzip при фигне на входе? "not in gzip format", errno = 1, " Operation not permitted". Эта ошибка крайне отличается от enomem, либо ошибок чтения/записи из/в stdin/out. У нас появляется ошибка пользовательских данных. На одной и той же машине в тех же самых условиях с одним файлом всё отработает, а с другим нет.

Получается, что у нас есть два разных типа ошибок, которые мы должны обработать: системные ошибки (ENOMEM, broken pipe), и ошибки обработки данных (not in gzip format).

Мы можем начать играться с set -o pipefail, но мы всё равно не можем обработать эту ошибку отдельно. Мы получаем в пайпа код 1, и даже не знаем, кто его выставил без чтения stderr.

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

Опытный админ знает мерзкий хак:

set -o pipefail
cat /proc/cpuinfo |sort|(gzip -d || exit 33) |sort|wc -l
echo $?
33

Мы не можем различить ошибку пользовательских данных от системной ошибки, но мы уже можем узнать, что именно gzip нам испортил жизнь, а не кто-то вокруг.

Если мы хотим иметь разное поведение для системной ошибки и пользовательских данных, то инструмент 'bash pipe' уже не работает. Более того, к gzip, внезапно, вопросы, потому что он возвращает 1 на системные ошибки и на ошибки пользовательского ввода.

И возникает вопрос: можно ли считать unix-way'ным использование gzip -d? Делает ли он "одну вещь, но делает её хорошо"?
Tags: философия администрирования
Subscribe

  • systemd-networkd, netlink и arp флуд

    Нереально странный баг пофикшен с помощью eBPF затычки. Для меня большой неожиданностью является реакция на него.…

  • Rust soundness

    Каждый раз, когда я сталкиваюсь с маленькими "но" в Rust'е, это ощущение тщательной продуманности. Например, простейшие fold-функции для итераторов:…

  • still_ntp

    В ходе локального мозгового штурма у меня родилась суперидея. Надо написать ntp сервер, который может отдавать указанную дату. Т.е. сказали при…

  • Post a new comment

    Error

    default userpic

    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.
  • 6 comments