ESPNBarnwell on five important Week 3 losses and their aftermathThe Jerusalem PostIranians stagger under soaring cost of living after seven months of war with the USESPN DeportesAutoridades de Manchester City rebaten veredicto de Premier LeagueBollywood HungamaGondhal team meets Maharashtra CM Devendra Fadnavis, appeals for financial support ahead of Oscar 2027 journeyDaily MaverickStudent protests and French public sector strike heap pressure on MacronRTP DesportoSalvador diz que Sporting de Braga "exige mais" do que o que foi apresentadoPunchMeet Nigerian dancer attempting 168-hour Guinness World RecordBillboardElton John Opens London’s Apple Music Hall With Intimate, Hit-Packed PerformanceVariety‘GMA’ Anchor and Christopher Reeve’s Son Will Reveals Testicular Cancer Diagnosis: ‘I Was Raised to Share One’s Struggles’Egypt IndependentBritain’s PM is on a ‘Burnham bounce.’ When will he fall to earth?Antara NewsJakarta rises to 140th worldwide in Global Cities Index 2026Il Fatto Quotidiano“Mostrava i genitali e si masturbava di fronte a una 18enne”: giudice sospeso dal Csm. Lui: “Solo frasi volgari, mi scuso”
The Daily Newsstand · Free, Always
Tuesday, September 29, 2026

Я собрал себе курс по Linux (но сначала получился курс по .sh)

Translate

Первая версия получилась курсом по shell-скриптингу. А я не этого хотел: мне нужно было разобраться с Linux на практике, а не в теории по книге — права, службы, журналы, монтирование, сеть. На выходе же лежала полсотня заданий вида «напиши .sh, который…». Хотя каждое по отдельности выглядело нормально.

Заметил я это, когда стал считать, что человек физически делает в каждой серии. Почти везде одно и то же: открывает редактор и пишет скрипт.

Причина скучная и техническая. Скрипт легко проверить: запустил, посмотрел вывод, сравнил. Всё остальное проверять неудобно, поэтому всё остальное вымывается само, без чьего-либо умысла. Модель, которой я всё это надиктовывал, пошла по пути наименьшего сопротивления, опираясь на курс по языку C, который я дал ей как образец.

А администратор большую часть времени не автоматизирует. Он читает конфиг, смотрит, что запущено, и выясняет, почему оно работает не так, как написано в документации. Скрипты тоже пишет — но это следствие, а не основное занятие.

Стоп, я начал с середины

Речь про KERNEL SHADOWS: 101 серия в восьми сезонах, лежит на гитхабе под GPL v3, бесплатно. Это не видеокурс и не платформа: это репозиторий с текстом. Папка на серию, внутри README с теорией и заданием, каркас файла, тесты и эталонное решение. Проходишь в редакторе с терминалом — я прохожу в Cursor. Регистрации никакой.

Выглядит это так:

git clone https://github.com/gfazzz/kernel-shadows.git
cd kernel-shadows/season-01-shell-foundations/s01e01-terminal-awakening
less README.md
cp starter/whereami.sh artifacts/
bash tests/test.sh

В starter/ лежит не решение, а дырки:

set -euo pipefail

# TODO 1: получи текущий абсолютный путь (подсказка: команда из 3 букв)
#         и сохрани его в переменную here.
here="" # <-- замени на вызов нужной команды

# TODO 2: выведи текущую директорию и домашнюю директорию ($HOME).
echo "Текущая директория (pwd):   ${here}"

# TODO 3: определи, находишься ли ты в корне "/", и напечатай понятный статус.

Тест на нём сразу красный, и это нормально:

  PASS: whereami.sh найден
  PASS: синтаксис bash корректен
  PASS: есть shebang
  FAIL: в выводе нет текущего пути /home/max/ops/deep/place (скрипт должен печатать pwd)
  FAIL: в выводе нет $HOME (/home/max)
  FAIL: похоже, путь захардкожен: вывод не меняется при смене директории
  Итог: 3 passed, 3 failed

Третий FAIL — про то, ради чего вообще стоило писать тесты руками. Он не сверяет текст вывода, он запускает скрипт из двух разных каталогов и смотрит, меняется ли ответ. Захардкоженный путь так не пролезает.

Эталон лежит рядом в solution/, и открывать его до своей попытки — единственный способ испортить себе курс. make progress эталон не засчитывает: серия пройдена, только если зелёный тест прошёл на твоём файле.

Из софта нужны bash, git, make, python3. Ни один тест не просит root, сеть, докер или железо — про это дальше.

Правило, которое пришлось ввести насильно

Чтобы курс перестал скатываться в bash, я расписал Клоду типы серий и сделал баланс критерием приёмки сезона:

Тип

Что делаешь

Что смотрит тест

Automation

пишешь .sh

поведение скрипта на фикстуре

Configuration

правишь конфиг

свойства конфига, идемпотентность

Investigation

работаешь в CLI, собираешь отчёт

воспроизводимость находки

Code

пишешь .py или .c

поведение программы

Сезон, целиком собранный из Automation, не принимается. Сейчас по факту: 25 серий на автоматизацию, 38 на конфигурацию, 30 на разбор, 8 на код. Скрипты — четверть курса.

Investigation звучит хорошо ровно до первого теста

Как проверить, что человек разобрался в инциденте? Не «написал ли он скрипт», а именно разобрался. Плюс я себе заранее запретил тесты, которым нужен root, сеть, докер, кластер или железо.

Запрет не из аскетизма. Курс, для которого надо поднять Kubernetes, не пройдёт никто, включая автора, — а делался он в первую очередь как раз для автора. А тест, дёргающий живую сеть, падает через раз, и человек решает, что сломан он. Первая версия серии про доступность узлов честно вызывала ping, и от этого пришлось уйти.

Сейчас тест кладёт свой ping в начало PATH:

cat > "${FAKEBIN}/ping" <<'MOCK'
#!/usr/bin/env bash
host="${!#}"
case "${host}" in
  up-*|10.0.0.1) exit 0 ;;
  *)            exit 1 ;;
esac
MOCK

Проверяется не связность, а логика решения: сохранил ли код возврата, не захардкодил ли статус, отличает ли «не ответил» от «ответил, но без поля time=». То же самое сделано для ss, dig, ufw и dpkg.

Конфиг можно прочитать глазами той программы, которая его читает

Дальше был systemd, и вот тут ИИ довольно долго считал, что зашёл в тупик. Серия про юнит: человек пишет .service, а как убедиться, что он правильный, если systemd в тесте не запустить?

Оказалось, запускать и не надо. Юнит — это текст с известной семантикой, и семантику можно воспроизвести. Тест читает файл так, как читает его systemd: секции значимы, побеждает последнее присваивание, пустое значение сбрасывает настройку, комментарии не в счёт. Потом сверяет эффективные значения с требованиями к службе. Отдельно ловятся конвейер в ExecStart (оболочки-то нет), After без Wants и настройка, которую ниже по файлу сбросили пустым присваиванием.

Неожиданно это оказалось полезнее запуска. Запущенная служба отвечает на вопрос «стартовала ли она сейчас, в этой системе, с этим окружением». Разбор отвечает на «что здесь вообще написано», а это и есть навык, за которым человек пришёл. Тем же способом проверяются sshd_config, fstab, logrotate, compose.yaml, манифесты Kubernetes и правила auditd.

Побочный эффект приятный: тест ловит то, что в жизни всплывает недели спустя. Директиву, которая осталась внутри комментария. Директиву, заданную дважды. Host * в начале ~/.ssh/config, из-за которого все частные секции ниже перестают действовать.

Спорить с этим можно, и я заранее соглашусь: если тебе нужно убедиться, что служба реально поднимается на твоём дистрибутиве с твоим SELinux, разбор конфига этого не покажет. Для учебной задачи важнее первое, для продакшена — второе. Две серии, где без живого ядра совсем никак (сборка модуля, insmod, чтение /dev/shadow0), вынесены в отдельную цель и без Linux честно печатают SKIP.

А криминалистика и в жизни работает со снимком

Серии про разбор инцидентов гоняются на снятых состояниях: вывод ps, содержимое /proc, журналы, дамп /proc/net/tcp. Надо найти скрытый процесс, стёртый бинарник и адрес управляющего сервера, закодированный little-endian. Тут компромисса вообще нет: живой машине, на которой стоит руткит, нельзя задавать вопросы о ней самой.

Что ломалось

Тесты, зелёные на моей машине, — не тесты. Поэтому в Makefile завели три цели, каждая после конкретного позора.

make test-repeat гоняет всё дважды подряд. Ловит серии, где второй прогон видит мусор от первого.

make test-locale запускает под LC_ALL=C и под чужой таймзоной с немецкой локалью. Ловит проверки, которые сравнивают отсортированный вывод: в другой локали сортировка другая, и тест краснеет на верном решении.

make clean-clone разворачивает курс с нуля и прогоняет на свежем клоне. Самая обидная находка была именно тут: типовой .gitignore вычёркивает *.log, ключи и .env, а в курсе по Linux это ровно учебные материалы — фикстуры для разбора журналов, учебные ключи SSH и TLS, app.env контейнерных серий. Локально всё на месте, потому что оно у тебя уже есть, а в клоне задания остаются без входных данных. Сейчас игнорирование идёт по каталогу запуска, а не по расширению, и в .gitignore висит комментарий капслоком, чтобы мы не переписали это обратно.

Из чего это состоит

Восемь сезонов, восемь стран, шестьдесят дней операции. Ты — админ, которого наняли построить и защитить инфраструктуру на полсотни узлов, и по ходу выясняется, что защищать придётся всерьёз.

Сезон

Тема

Серий

1

Оболочка и основы

16

2

Сети

12

3

Администрирование

13

4

DevOps и автоматизация

12

5

Безопасность

12

6

Встраиваемый Linux

12

7

Эксплуатация

12

8

Финальная операция

12

Названия сезонов ничего не говорят, поэтому вот третий по темам серий:

s03e01  Список жильцов: «Кто есть на этой машине»
s03e02  Три буквы: «Кто что может»
s03e03  Заряженный пистолет: «Каждому ровно то, что нужно»
s03e04  PID 6623: «Имя, которое пишет себе сам»
s03e05  Служба, которая вернётся: «Кто их запускает»
s03e06  Пять минут по расписанию: «Кто догонит пропущенное»
s03e07  Вечер 14 октября: «Всё это было записано»
s03e08  Место, которого нет: «df говорит одно, du — другое»
s03e09  Пятьсот гигабайт, которых не видно: «Диск есть, места нет»
s03e10  Машина, которая не поднялась: «Кто скажет ей, что монтировать»
s03e11  Копия, которой не было: «Когда вы восстанавливались в последний раз»
s03e12  Строка, которой не было: «Кто скажет службе, что журнал повернули»
s03e13  03:47: «Третий вопрос»

Серия — это один концепт, одно задание, один проверяемый артефакт, 45–90 минут. Сезон собирает работающую вещь, а не набор упражнений: shadow_toolkit, netshield, fleet_admin, shadow_iac, hardening_kit, shadow_mesh, aurora, shadow_core. Финал новой темы не вводит, он принимает построенное: двенадцать фаз, по одной на навык каждого сезона.

Подсказок по ходу становится меньше. Первые три сезона дают полный каркас и эталон, четвёртый с пятым — каркас и эталон после попытки, шестой с седьмым — только интерфейсы, восьмой — договор вызова и всё.

Это спин-офф моего же курса по языку C, про который я писал три недели назад. Вселенная и персонажи общие, разница в том, что там пишешь программы, а здесь управляешь системами, на которых они крутятся. Идея была записана через три дня после первой, и тогда я ещё не знал, приквел это будет или спин-офф.

Про ИИ, раз уж без него ничего бы не было

Оба курса я собрал себе сам, с ИИ, руками почти не писал. Вывод из этого получился не тот, которого обычно ждут.

Код вместо меня ИИ тут не писал, а сделал две другие вещи.

Первая: помог составить программу под меня. Не «сгенерируй курс по Linux» — так получается оглавление учебника, я пробовал. А разговор о том, чему я хочу научиться, в каком порядке, на каком материале и что должно получиться в конце. Раньше такое было доступно тем, у кого есть живой наставник.

Вторая: помогает, пока я по этому курсу иду. В сюжете есть наставник по имени LILITH, и за ним стоит обычный чат в Cursor, открытый рядом с кодом. Проходить надо в режиме Ask. В Agent ассистент правит файлы сам: серия окажется решённой, а ты не наберёшь ни одной команды. Первый раздел .cursorrules запрещает ему писать в artifacts/, выдавать решение серии и пересказывать solution/ — но режим переключаешь ты, а не файл, так что это скорее напоминание, чем защита.

Поэтому в конце каждой серии ИИ выписал вопросы, которые стоит ему же и задать, и один запрещённый. Запрещённый всегда выглядит совершенно разумным и вредит именно здесь. В серии про разбор пакета это «разбери заголовок за меня»: зашитая длина IP-заголовка работает на девяти пакетах из десяти, и десятый надо найти самому. В серии про профилирование — «оптимизируй мой код»: сначала профиль, потом оптимизация, наоборот это гадание.

Обычно разговор про ИИ сводится к тому, что админы и программисты скоро не понадобятся. По-моему, наоборот. Подешевела не профессия, а персональная программа обучения: раньше между «хочу разобраться в Linux» и «разбираюсь» стояли поиск нормального курса, чужой темп и чужой порядок тем, теперь стоит вечер разговора с ассистентом. Человек, который умеет посмотреть в sshd_config и увидеть, что директива не действует, нужен ровно так же, как был нужен.

Репозитории: KERNEL SHADOWS — Linux, GPL v3 OPERATION MOONLIGHT — C, MIT

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.