Когда bash заканчивается: выбор инструмента
Урок курса «Курс подготовки DevOps-инженеров»
Хронометраж: занятие 60 минут — теория 30 минут, практика 30 минут. Домашняя работа: 1–2 часа.
Кратко о чём урок: Критерии перехода на Python: структуры данных, сетевые вызовы, обработка ошибок, тестируемость, размер скрипта. Стоимость поддержки как главный аргумент.
1. Что изучаем
- Выбирать между bash и Python по признакам задачи, а не по привычке.
- Узнавать признаки того, что bash-скрипт вырос за свои границы.
- Измерять то, что можно измерить: время запуска, объём кода, поведение на неожиданном входе.
- Переписывать скрипт, не меняя его интерфейс, чтобы переписывание не разрослось.
- Объяснять решение так, чтобы через год его можно было пересмотреть осознанно.
2. Зачем это нужно и где применяется
Блок 04 закончился скриптами, которые не страшно поставить в cron. Этот блок про то, что происходит дальше: скрипт живёт, обрастает условиями, и в какой-то момент дописывать его становится дороже, чем переписать. Задача урока — научиться замечать этот момент и не путать его с двумя ошибочными крайностями.
Первая крайность — переписывать рано. Скрипт из пяти строк, который вызывает curl и grep, переписывают на Python «чтобы по-нормальному», и получают двадцать строк, зависимость от окружения и более медленный запуск. Работы стало больше, пользы — никакой.
Вторая, и более дорогая, — не переписывать никогда. Bash-скрипт разрастается до трёхсот строк, внутри уже jq со своей логикой и awk со своей, кавычки расставлены методом подбора, а || true стоит в пяти местах, потому что иначе set -e мешает. Такой скрипт работает, пока его не нужно менять. Первое же изменение занимает день и ломает что-то в другом месте.
Третья задача урока — уметь объяснить решение. «Мне так привычнее» не годится: скрипт переживёт вас в этой роли, и человек, который его унаследует, должен понимать, почему выбран этот инструмент и при каком условии решение стоит пересмотреть.
3. Теория (30 минут)
У чего какая сильная сторона
Bash — это язык склейки программ. Его сила в том, что вызов внешней команды выглядит как обычное слово, а конвейер соединяет программы без кода вообще. Пока задача формулируется как «взять вывод одной программы, отфильтровать и отдать другой», bash не имеет конкурентов по краткости.
Python — язык работы с данными и логикой. Его сила в том, что данные остаются структурами, а не текстом: словарь остаётся словарём, число — числом, ошибка — исключением с типом и местом возникновения.
Отсюда первый практический признак: посмотрите, что делает ваш скрипт между вызовами внешних программ. Если почти ничего — это bash. Если между вызовами идёт разбор, накопление, ветвление по данным — это уже Python, даже если сейчас скрипт короткий.
Сколько стоит запуск
Начнём с того, что легко измерить и что обычно переоценивают. Три прогона по 50 повторов в контейнере:
прогон bash python python+импорты
1 5 мс 36 мс 100 мс
2 3 мс 21 мс 97 мс
3 2 мс 21 мс 98 мс
Python запускается в 7–10 раз дольше bash, а с импортами json, csv, pathlib, urllib.request — в 30–40 раз. Первый прогон всегда хуже: файлы ещё не в кэше страниц.
Когда это имеет значение? Только если скрипт вызывается часто: в цикле по тысяче файлов, в хуке на каждый коммит, в проверке мониторинга раз в десять секунд. Тысяча вызовов — это 2 секунды на bash и полторы минуты на Python с импортами. А если скрипт запускается раз в сутки, разница в 100 мс не значит ничего, и выбирать надо по другим признакам.
Скорость работы: результат против ожиданий
Теперь то, что обычно ожидают наоборот. Файл из 20 000 строк лога, две задачи, одинаковый ответ в обоих вариантах:
| Задача | bash | Python |
|---|---|---|
посчитать строки с ERROR |
grep -c — 7 мс |
56 мс |
| сгруппировать по сервису и коду, посчитать среднее | awk — 40 мс |
189 мс |
Bash и awk быстрее в 4–8 раз. Это честное сравнение: обе версии дали одинаковый результат (1449 записей, среднее 446.6), а сравнивать по скорости можно только способы, дающие одинаковый ответ — иначе быстрее оказывается тот, кто делает меньше работы.
Вывод, который стоит запомнить: переход на Python оправдан не скоростью. grep и awk написаны на C и десятилетиями оптимизировались под обработку текста построчно. Аргумент за Python другой — стоимость поддержки.
Объём кода: и здесь bash короче, но не всегда
Возьмём одну задачу — разобрать ответ API и посчитать работающие машины по зонам — и напишем обе версии аккуратно. Не «как получится», иначе сравнение нечестное.
| Файл | Строк кода (без пустых и комментариев) |
|---|---|
summary.sh |
7 |
summary.py |
33 |
Bash короче в 4,7 раза. Часть разницы — документация и аннотации типов, которых в bash-версии нет вовсе, но и это показательно: в Python их естественно писать, в bash — некуда.
А теперь задача чуть сложнее: запрос к API с повторами при временных ошибках, с разбором кодов ответа и экспоненциальной отсрочкой.
| Файл | Строк кода |
|---|---|
fetch-retry.sh |
28 |
fetch_retry.py |
52 |
Соотношение упало с 4,7 до 1,9. Вот это и есть критерий перехода, выраженный числом: чем больше в задаче логики, а не склейки, тем меньше преимущество bash в объёме. В какой-то точке кривые пересекаются, и дальше bash-версия становится длиннее и заметно менее понятной.
Пять мест, где bash ломается
Это не придирки, а измеренное поведение — каждое встречается в работе.
Арифметика. Bash умеет только целые числа:
bash: 7/2 = 3
bash: 0.1+0.2 → syntax error: invalid arithmetic operator
python: 7/2 = 3.5
python: 0.1+0.2 = 0.30000000000000004
У Python своя особенность двоичных дробей (последняя строка), но он хотя бы считает. Любой процент, среднее время ответа или размер в гигабайтах в bash требует внешней программы.
Имена файлов. Три файла, у одного пробел в имени, у другого перевод строки:
файлов создано: 4 ← ls | wc -l насчитал 4 вместо 3
через for в подстановке: 5 элементов ← for f in $(ls *.log)
через шаблон: 3 ← for f in *.log
python: 3 ← pathlib.Path.glob('*.log')
Первая строка сама по себе поучительна: ls | wc -l соврал из-за перевода строки в имени. Второй способ — классическая ошибка, разбитая по пробелам. Правильный способ в bash есть (шаблон), но помнить о нём надо всегда, а в Python перебор безопасен по умолчанию.
Структуры данных. В bash есть массивы и ассоциативные массивы, но только со строками и без вложенности: массив внутри массива невозможен. Как только данные становятся деревом — ответ API, конфигурация, разбор YAML — представлять их в bash нечем.
Форматы. JSON без внешних программ в bash не разобрать. С jq можно, но это уже второй язык в вашем скрипте, со своим синтаксисом и своими ловушками (в блоке 04 мы видели, как подстановка значения прямо в фильтр меняет смысл запроса). В Python это одна строка стандартной библиотеки.
Обработка ошибок. Самое неприятное. Вот скрипт с полным набором предохранителей:
set -euo pipefail
f() { grep -c 'нет-такой-строки' /etc/hostname; }
if f > /dev/null; then echo "найдено"; else echo "не найдено"; fi
count=$(f || true)
Результат: count='0'. Значение есть, скрипт продолжился, и всё выглядит нормально. Но grep -c вернул 0 совпадений и код 1, а || true этот код замаскировал. Если бы grep упал по-настоящему — не нашёл файл, не хватило прав, — count тоже оказался бы пустым или нулевым, и отличить «ноль совпадений» от «ошибки» уже невозможно.
В Python неудача — это исключение с типом и местом:
bash+jq: jq: error (at instances-broken.json:1): Cannot iterate over null (null) код 5
python: TypeError: 'NoneType' object is not iterable код 1
Оба сообщили об ошибке, и это важно отметить честно: jq тоже не молчит. Разница в том, что в Python видно тип ошибки, и на разные ошибки можно ответить по-разному, а не только «упало — вышли».
Тестируемость — самый недооценённый аргумент
Функция в Python-версии вызывается напрямую:
python: функция summarize вызвана напрямую из теста, утверждение прошло
Это два десятка символов в тесте: импортировать модуль, вызвать функцию, сравнить результат. Логику можно проверить без запуска скрипта целиком и без обращения к сети.
В bash функцию из конвейера отдельно не вызвать. Тестировать можно (в блоке 04 мы делали это через bats), но это тестирование скрипта целиком с подменой внешних команд — заметно дороже и хрупче.
Почему это важно именно для эксплуатации: скрипт, который что-то удаляет или отправляет запросы в облако, хочется проверить до того, как он это сделает. Тест на функции даёт такую возможность, а «запустить и посмотреть» — нет.
Заодно в Python-версии видно ещё одно свойство: список повторяемых кодов ответа — это данные, множество {429, 500, 502, 503, 504}, а не текст внутри case. Данные можно проверить в тесте, вывести в журнал, вынести в конфигурацию.
Красные флаги: когда пора
Собранный по опыту список признаков, что скрипт вырос из bash. Каждый — сигнал, что стоимость поддержки растёт быстрее пользы.
- внутри есть
jqилиawkсо своей логикой — то есть уже два языка в одном файле; - есть
|| true, чтобыset -eне мешал, и непонятно, что при этом маскируется; - кавычки расставлены методом подбора, и страшно менять;
- функции нельзя проверить отдельно, только запуском всего скрипта;
- при странном входе скрипт продолжает работать и портит данные;
- число вложенных
ifвforвнутриwhileбольше двух; - разбор JSON или YAML сделан через
grepиsed.
Три и больше — задача уже за границей, где bash дешевле.
И обратный список, признаки того, что переписывать не надо: скрипт короче пятидесяти строк, логики между вызовами почти нет, он не менялся полгода и запускается часто. Работающий короткий bash-скрипт — не долг, а нормальный инструмент.
Цена Python, о которой надо знать заранее
Выбирая Python, вы берёте на себя вопрос зависимостей. В стандартной библиотеке есть многое, но не всё:
| Модуль | Где |
|---|---|
json, csv, pathlib, sqlite3, urllib.request |
стандартная библиотека |
tomllib |
стандартная библиотека, с версии 3.11, только чтение |
yaml |
внешний пакет PyYAML |
requests, httpx |
внешние пакеты |
Разница существенная: скрипт, которому хватает стандартной библиотеки, запускается на любом сервере без подготовки. Как только появляется requests, добавляется работа — виртуальное окружение, фиксация версий, установка на целевой машине. Причём просто поставить пакет в системный Python в Debian не получится:
$ python3 -m pip install PyYAML
error: externally-managed-environment
This environment is externally managed
Это не поломка, а защита от смешивания системных и своих пакетов (PEP 668). Правильный путь разбирается в уроке 06.04. Здесь важно другое: при выборе инструмента учитывайте не только удобство языка, но и то, что придётся сделать для запуска на сервере.
3.1. Примеры и варианты реализации
Одна задача — три среды. Если вариант в этом уроке неприменим, это указывается явно с объяснением причины.
| Среда | Как решается | Что нужно иметь |
|---|---|---|
| Локальный стенд (Docker / VM / kind) | оба варианта пишутся и сравниваются рядом, замеры повторяются | bash, python3, jq; образ блока |
| VPS / bare-metal | здесь решение проверяется на практике: что уже установлено и что придётся ставить | доступ к серверу, где скрипт будет работать |
| Yandex Cloud | выбор часто определён тем, есть ли готовый SDK и как устроен API | доступ к облаку, токен |
Локальный стенд. Примеры к уроку — две пары скриптов, решающих одну задачу на bash и на Python, плюс скрипт для замера времени запуска. Смысл не в том, чтобы прочитать их, а в том, чтобы запустить, сравнить вывод командой diff и посмотреть на числа. Образ описан в examples/docker/ — там же jq, ruff и mypy, которыми проверяются примеры.
VPS / bare-metal. На сервере выбор упирается в то, что там уже есть. Bash есть всегда. Python 3 в современных дистрибутивах тоже есть почти всегда, но без pip и без venv: в Debian это отдельные пакеты (python3-pip, python3-venv), и на минимальной установке их нет. Значит скрипт на стандартной библиотеке скопируется и запустится, а скрипт с requests потребует подготовки — и это надо учесть при выборе, а не обнаружить при развёртывании.
Второй практический момент: если скрипт запускается из cron, помните про урезанное окружение из урока 04.08. Python это не лечит — PATH там будет таким же коротким, и путь к интерпретатору лучше указывать полностью.
Yandex Cloud. Здесь выбор часто решается за вас наличием готовых средств. Для облачных API есть CLI (yc), который отдаёт JSON, и есть SDK для Python. Практическое правило: если задача — «вызвать одну команду и посмотреть результат», берите CLI и bash. Если задача — «пройти по всем ресурсам, сопоставить с данными из другого источника, собрать отчёт», берите SDK и Python: обход пагинации и обработка ошибок на bash быстро превращаются в тот самый скрипт с семью красными флагами.
Отдельно: у CLI и SDK разные способы аутентификации и разные форматы ошибок. Это ещё один аргумент не смешивать их в одном скрипте — выбрать что-то одно.
Что выбрать. Правило, которое работает: пишите на bash, пока задача остаётся склейкой готовых программ, и переходите на Python, когда появляется логика между вызовами. Не по числу строк, а по характеру работы. И фиксируйте решение письменно — с условием, при котором его стоит пересмотреть.
4. Практика на занятии (30 минут)
Курс проходят самостоятельно, поэтому каждый шаг говорит, что ввести, зачем, что должно получиться и что делать при неудаче.
Что делаем. Измеряем то, о чём обычно спорят, сравниваем две реализации одной задачи и учимся замечать границу.
Файлы для работы: blocks/06-python/examples/06.01-bash-or-python/
Шаг 1 (5 минут). Измерьте время запуска на своей машине.
-
Что ввести:
cd blocks/06-python/examples/06.01-bash-or-python ./bench-startup.shСтавить что-либо не обязательно: образ с оснасткой блока описан в
examples/docker/— соберитеcourse-py:13и запуститеdocker run --rm -it -v "$PWD:/work" -w /work course-py:13 bash. -
Зачем: увидеть своими числами, во сколько раз запуск Python дороже запуска bash.
-
Ожидаемый результат: bash в единицах миллисекунд, Python в десятках, Python с импортами — около сотни. Абсолютные числа у вас будут свои, важно соотношение.
-
Если не так: если Python вышел быстрее bash — почти наверняка мешает холодный кэш страниц; повторите прогон, первый всегда хуже. Команда не найдена — вы не в каталоге примера или не собран образ
course-py:13.
Шаг 2 (5 минут). Сравните две реализации одной задачи.
-
Что ввести:
./summary.sh instances.json ./summary.py instances.json diff <(./summary.sh instances.json) <(./summary.py instances.json) && echo "вывод совпадает" -
Зачем: убедиться, что обе версии дают одинаковый результат — только тогда их честно сравнивать по объёму кода.
-
Ожидаемый результат: одинаковый вывод и строка
вывод совпадаетотdiff. -
Если не так:
diffпоказал строки — версии разошлись; сначала найдите, какая права, сравнивать объём рано. -
Ответьте: посмотрите оба файла и посчитайте строки:
grep -vcE '^\s*$|^\s*#' summary.sh summary.py.
Шаг 3 (5 минут). Посмотрите, что происходит на битом входе.
-
Что ввести:
./summary.sh instances-broken.json; echo "код: $?" ./summary.py instances-broken.json; echo "код: $?" -
Зачем: увидеть, чем отличается реакция на ошибку у bash+jq и у Python.
-
Ожидаемый результат: обе версии сообщают об ошибке, но по-разному — разные сообщения и коды возврата. Обратите внимание, что
jqтоже не молчит: разница не в наличии ошибки, а в том, что с ней можно сделать дальше. -
Если не так: если какая-то версия завершилась с кодом 0 и без сообщения — битый вход не дошёл до разбора; проверьте, что подан именно
instances-broken.json.
Шаг 4 (6 минут). Сравните задачу посложнее.
-
Что ввести:
./fetch-retry.sh https://example.com/ | head -3 ./fetch_retry.py https://example.com/ | head -3 ./fetch-retry.sh https://example.com/net-takoy-stranicy ./fetch_retry.py https://example.com/net-takoy-stranicy -
Зачем: проверить, как меняется соотношение объёма кода, когда в задаче появляется логика — повторы и разбор кодов ответа.
-
Ожидаемый результат: на живом адресе обе работают, на
404обе не повторяют запрос. -
Если не так: нет доступа в сеть наружу — обе версии не получат ответ; тогда сравнивайте только объём кода, а не поведение.
-
Ответьте: посчитайте строки в обеих версиях и сравните соотношение с шагом 2 — оно должно заметно упасть.
Шаг 5 (5 минут). Вызовите функцию из Python-версии напрямую.
-
Что ввести:
python3 -c " import sys; sys.path.insert(0, '.') from summary import summarize counts, cores = summarize('instances.json') assert counts['ru-central1-a'] == 2, counts print('логика проверена без запуска скрипта целиком')" -
Зачем: показать, что логику Python-версии можно проверить тестом, не запуская скрипт целиком и не обращаясь к сети.
-
Ожидаемый результат: проверка проходит, печатается
логика проверена без запуска скрипта целиком. -
Если не так:
ModuleNotFoundError— вы не в каталоге примера (вернитесьcdиз шага 1);AssertionError— во входных данных не два узла в зоне, посмотритеinstances.json. -
Ответьте: подумайте, как сделать то же с
summary.sh, и во что это превратится.
Шаг 6 (4 минуты). Заполните таблицу критериев на своей задаче.
- Что ввести: возьмите любой свой bash-скрипт (или скрипт из блока 04) и пройдите
criteria-table.md, включая список красных флагов. - Зачем: перенести критерии урока на реальную задачу и получить обоснованное решение, а не ощущение.
- Ожидаемый результат: таблица заполнена, отмечено число красных флагов; три и больше — задача уже за границей, где bash дешевле.
- Если не так: если ни один флаг не отметился и скрипт короткий — это нормальный ответ «оставить на bash», а не ошибка эксперимента.
Проверка результата. К концу занятия вы должны уметь ответить: во сколько раз дольше запускается Python и когда это важно; почему grep и awk быстрее и что из этого следует; как меняется соотношение объёма кода с ростом сложности задачи; какие три признака в вашем скрипте означают, что пора переписывать; чем count='0' после || true опасен.
5. Домашняя работа (1–2 часа)
Задание. Принять и обосновать решение по своей задаче, а затем проверить его на практике.
-
Разбор своего скрипта. Возьмите свой bash-скрипт (или из блока 04:
backup-reference.sh,log-report.sh,pods-report.shподойдут) и заполнитеcriteria-table.mdцеликом: признаки, подсчёт, измерения, красные флаги. Обязательно посчитайте накладные расходы на запуск за сутки исходя из реальной частоты вызовов. -
Карточка решения. Заполните
decision-card.mdпо этой же задаче. Главные строки — «главный аргумент» и «при каком условии решение стоит пересмотреть»: без второй карточка бесполезна через полгода. -
Ядро задачи на двух языках. Выберите самую сложную часть своего скрипта (разбор данных, ветвление, обработка ошибок) и напишите её на обоих языках — по 20–40 строк. Посчитайте строки, сравните вывод командой
diff, проверьте поведение на неожиданном входе. -
Переписывание по плану. Если по итогам пунктов 1–3 решение «переписать», заполните
rewrite-plan.mdи выполните шаги 1–5. Особое внимание шагу 2: прогоните старый скрипт по своим же проверкам до переписывания. Если решение «оставить как есть» — заполните раздел «что стало лучше» словами о том, почему переписывание не даст выигрыша. -
Проверка примеров линтерами. Прогоните свои новые файлы через те же инструменты, которыми проверены примеры урока:
docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable /mnt/ваш.sh /opt/tools/bin/ruff check ваш.py /opt/tools/bin/mypy --ignore-missing-imports ваш.pyЗамечания линтера не игнорируйте: в примере
fetch_retry.pyruff нашёл перехватExceptionвслепую (правило BLE001), и это было справедливо — исключения теперь перечислены явно.
Критерии приёмки.
-
criteria-table.mdзаполнена по конкретному скрипту, названо, какой признак перевесил - Измерено время запуска на своей машине и посчитаны накладные расходы за сутки
- Пройден список красных флагов, указано число отмеченных
-
decision-card.mdзаполнена, включая условие пересмотра решения - Перечислены зависимости и указано, есть ли они на целевой машине
- Ядро задачи написано на обоих языках, приведено число строк в каждой версии
- Вывод обеих версий сравнён
diff; при расхождении объяснено, какая версия права - Проверено поведение обеих версий на неожиданном входе, приведены сообщения и коды возврата
- Если решение «переписать» — заполнен
rewrite-plan.mdи выполнен шаг 2 (прогон старого скрипта по проверкам до переписывания) - Если решение «оставить» — обосновано, почему переписывание не даст выигрыша
- Новые файлы проходят
shellcheckиruffбез замечаний
6. Частые ошибки и подводные камни
Переписывают из-за длины, а не из-за характера задачи. Симптом: скрипт из 80 строк переписан на Python и стал 200. Причина: длина сама по себе ничего не говорит — 80 строк последовательных вызовов утилит нормальны для bash. Что делать: смотреть, сколько логики между вызовами.
Считают, что Python быстрее. Симптом: переписали разбор лога и получили пятикратное замедление. Причина: grep и awk написаны на C и оптимизированы под построчную обработку. Что делать: измерять; выигрыш Python в поддержке, а не в скорости.
Сравнивают неаккуратно написанные версии. Симптом: «на Python вышло вдвое короче» при сравнении со скриптом, где на bash всё сделано через sed вручную. Причина: сравнивались не языки, а качество кода. Что делать: писать обе версии аккуратно, иначе сравнение бессмысленно.
Оставляют || true, чтобы set -e не мешал. Симптом: скрипт работает, ошибки не видно, данные испорчены. Причина: код возврата замаскирован, «ноль результатов» и «сбой» стали неразличимы. Что делать: разбирать код возврата явно; если это тяжело — признак, что пора переходить.
Тащат requests в скрипт, которому хватает стандартной библиотеки. Симптом: скрипт не запускается на сервере, потому что там нет пакета. Причина: удобство библиотеки перевесило вопрос запуска. Что делать: для простых запросов достаточно urllib.request; внешние зависимости берут осознанно, вместе с работой из урока 06.04.
Пытаются поставить пакет в системный Python. Симптом: error: externally-managed-environment. Причина: PEP 668 запрещает смешивать системные и свои пакеты. Что делать: виртуальное окружение (урок 06.04), а не --break-system-packages.
Переписывают и меняют интерфейс заодно. Симптом: переписывание превратилось в переделку всего, что вызывает скрипт. Причина: вместе с языком поменяли аргументы и формат вывода. Что делать: интерфейс фиксировать, менять его отдельным изменением потом.
Не проверяют старый скрипт до переписывания. Симптом: новая версия «не совпадает со старой», спорят, какая права. Причина: никто не знал, как старая ведёт себя на краевых случаях. Что делать: сначала записать проверки и прогнать старую версию, потом писать новую.
Смешивают в одном скрипте bash, jq и awk с логикой в каждом. Симптом: чтобы понять скрипт, надо знать три языка. Причина: логика расползлась по фильтрам. Что делать: считать это красным флагом, а не нормой.
Игнорируют замечания линтера в Python. Симптом: except Exception проглатывает опечатку в имени переменной, и скрипт «работает». Причина: перехват вслепую скрывает не те ошибки, которых ждали. Что делать: перечислять исключения явно; ruff это ловит правилом BLE001.
7. Проверка усвоения
- Во сколько раз дольше запускается Python и при каком условии это имеет значение?
grep -c ERRORна файле из 20 000 строк быстрее Python-версии в восемь раз. Значит ли это, что переписывать на Python не надо?- Как меняется соотношение объёма кода при переходе от простой задачи к задаче с повторами и разбором ошибок?
- Почему
for f in $(ls *.log)дал пять элементов вместо трёх и как правильно? - Что означает
count='0'послеcount=$(f || true)и почему это опасно? - Назовите три красных флага, после которых bash-скрипт стоит переписать.
- Какие модули для работы с данными есть в стандартной библиотеке Python, а какие придётся устанавливать?
- Что нельзя менять при переписывании скрипта на другой язык и почему?
8. Материалы
Минимум два варианта на выбор: официальная документация плюс книга/статья/видео.
- Стандартная библиотека Python — то, что доступно без установки пакетов. Просмотрите оглавление целиком один раз: половина задач эксплуатации закрывается тем, что уже есть.
- Учебник Python — официальный, короткий и без воды. Если Python вы не знаете, читать стоит главы 3–5 и 8 перед уроком 06.02.
- Модуль json — пример того, как выглядит работа с форматом, когда она встроена в язык. Сравните с разбором того же JSON в bash.
- Google Shell Style Guide — раздел «When to use Shell» отвечает на тот же вопрос, что этот урок, и отвечает жёстче: авторы предлагают переходить на другой язык уже после ста строк или при первом появлении сложных структур данных.
- Wiki shellcheck — каталог того, чем bash опасен. Полезно как аргумент: каждое правило здесь появилось из настоящей ошибки.
- PEP 20 «The Zen of Python» — двадцать строк, из которых для этого урока важна одна: «явное лучше неявного». Именно этим Python отличается от bash в обработке ошибок.
← Предыдущий: 05.14. Защищённый доступ к инфраструктуре: WireGuard, bastion · Блок 06 · Следующий: 06.02. Основы языка: типы, структуры данных, функции, исключения →
Материалы для практики
Скрипты, шпаргалки и заготовки к заданиям урока. Текст урока — на этой странице.
-
Материалы к уроку 06.01 «Когда bash заканчивается выбор инструмента».zip