Perl с нуля до эксперта: от новичка до аса в DevOps-скриптинге

Интерактивный практико-ориентированный курс (100+ часов) для опытных DevOps-инженеров без опыта Perl: от базового синтаксиса до экспертных практик (CPAN, OOP, оптимизация, безопасность) и production-ready DevOps-скриптов. Внутри: прогресс-трекер, чаты по темам, визуалы (диаграммы синтаксиса, flowcharts задач), геймификация (бейджи, лидерборд), проекты и подготовка к собеседованиям.

1. Старт: установка Perl на Ubuntu, окружение, первый скрипт

Старт: установка Perl на Ubuntu, окружение, первый скрипт

Зачем DevOps-инженеру Perl в 2026

Perl по-прежнему часто встречается в инфраструктуре: старые, но критичные скрипты, утилиты для обработки логов, glue-code вокруг legacy-систем, плагины к мониторингу, системные инструменты на Unix. Цель этого урока — быстро и безопасно поднять окружение на Ubuntu, понять как запускать Perl-код, и написать первый скрипт в стиле production.

Что будет дальше по курсу

В этом курсе мы пойдём от базового синтаксиса к продвинутым темам и DevOps-практикам:

  • Сейчас: установка, окружение, первый скрипт.
  • Скоро: скаляры, строки, массивы, хэши, управляющие конструкции.
  • Затем: регулярные выражения, файлы, исключения, модули CPAN.
  • Финал: OOP, производительность, сети, автоматизация, большие проекты.
  • Чеклист готовности

    К концу урока у вас должно быть:

  • Рабочий Perl на Ubuntu и понимание, какой Perl вы используете.
  • IDE (VS Code) или минимальная конфигурация редактора.
  • Умение запускать скрипты через perl script.pl и через shebang.
  • Базовая дисциплина: use strict; use warnings; и проверка синтаксиса perl -c.
  • Установка Perl на Ubuntu

    Вариант A: системный Perl из репозитория Ubuntu

    На Ubuntu Perl обычно уже установлен. Проверим версию:

    Если Perl не установлен:

    Важно для DevOps: не ломайте системный Perl, который использует сама ОС и пакеты. Мы будем аккуратно.

    Полезные команды:

    Примечание про -E: он включает более современный режим однострочников, включая say.

    Вариант B: отдельный Perl под пользователя через perlbrew

    Если вам нужна другая версия Perl (например, новее, чем в Ubuntu), используйте perlbrew — это безопасно, не трогает системный Perl.

    Официальный репозиторий проекта: perlbrew (App::perlbrew) на GitHub

    Быстрый старт (прочитайте вывод команд, они подскажут следующие шаги):

    Установка конкретной версии (пример):

    Про Perl 7

    Perl 7 как идея и направление обсуждается, но в продакшене вы почти наверняка будете работать с Perl 5.x. В рамках курса мы учимся так, чтобы ваши знания были применимы к реальным системам прямо сейчас.

    IDE и окружение разработки

    VS Code

    Ставим VS Code удобным для Ubuntu способом и добавляем расширения.

    Документация: Visual Studio Code Docs

    Рекомендуемые расширения:

  • Perl (язык/подсветка)
  • Perl Navigator (навигация, диагностика, интеграции)
  • Padre

    Padre — специализированная IDE для Perl, встречается реже, но может быть полезна.

    Справка по дистрибутиву: Padre на MetaCPAN

    Минимальная конфигурация для терминала

    Для DevOps-работы важно уметь быстро проверить код без IDE:

    Если perldoc не найден:

    Документация Perl онлайн: perldoc.perl.org

    Структура Perl-скрипта: базовый шаблон

    Ниже — минимальный production-friendly шаблон: строгий режим, предупреждения, аккуратный вывод.

    Создайте файл hello.pl:

    Запуск:

    Запуск как исполняемого файла (shebang)

    Сделайте файл исполняемым:

    Что делает строка #!/usr/bin/env perl:

  • env ищет perl в вашем PATH.
  • Это удобно, если вы используете perlbrew или разные окружения.
  • use strict; use warnings; — почему это важно

    Эти директивы заставляют Perl быть дисциплинированным:

  • strict запрещает неявные переменные и часть опасных практик.
  • warnings показывает подозрительные места, которые часто становятся багами.
  • Это особенно критично для DevOps-скриптов, где ошибка может затронуть инфраструктуру.

    Быстрые однострочники (one-liners) для DevOps

    Perl часто используют как “швейцарский нож” в пайплайнах.

    Вывести строку:

    То же, но с say:

    Печать строк из stdin с нумерацией (похоже на nl):

    Проверка версии и путей:

    Где ] — числовая версия (исторически, иногда встречается в старом коде).

    Как читать документацию: perldoc

    В Perl документация — часть инструментария.

    Команды, которые реально помогают каждый день:

    Если вы видите неизвестную функцию, начните с perldoc -f имя_функции.

    Практикум-лабораторная

    Ниже не “вопросы”, а пошаговые действия, как в реальном DevOps-lab. Делайте в отдельной папке, например ~/perl-labs/module-1/.

  • Создайте директорию:
  • Убедитесь, какой Perl используется по умолчанию:
  • Создайте hello.pl по шаблону из урока и запустите через perl hello.pl.
  • Сделайте скрипт исполняемым и запустите через ./hello.pl.
  • Сломайте код намеренно (например, удалите кавычку) и проверьте синтаксис:
  • Верните скрипт в рабочее состояние.
  • Создайте env.pl, который печатает значение PATH и текущего пользователя, используя переменные окружения:
  • Запустите и сравните вывод с:

  • Сделайте one-liner: посчитайте количество строк во вводе, используя переменную .\n" }'
  • `

  • Выведите версию Perl двумя способами (]) и сравните.
  • Откройте документацию по print и chomp через perldoc -f ... и найдите: чем print отличается от say, и что делает chomp.
  • Типовой flow для запуска и проверки Perl-скрипта

    !Блок-схема, которая фиксирует рабочий цикл DevOps при написании и проверке Perl-скриптов

    Прогресс-трекер урока и геймификация

    Трекер

    | Активность | Статус | |---|---| | Проверил
    perl -v и which perl | ☐ | | Установил (или подтвердил) Perl на Ubuntu | ☐ | | Настроил VS Code или рабочий терминальный workflow | ☐ | | Запустил hello.pl через perl hello.pl | ☐ | | Запустил hello.pl через chmod +x и ./hello.pl | ☐ | | Выполнил perl -c и понял смысл проверки синтаксиса | ☐ | | Использовал perldoc -f для функции | ☐ | | Сделал минимум 2 one-liner | ☐ |

    Бейджи

  • Badge: Environment Ready — окружение готово, hello.pl работает двумя способами.
  • Badge: CLI Tinkerer — сделал 2+ one-liner и применил perldoc -f.
  • Лидерборд

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

    Чаты по темам

    Чтобы не смешивать вопросы разных уровней:

  • #setup-ubuntu — установка, PATH, пакеты, права.
  • #vscode-perl — плагины, линтинг, форматирование.
  • #cli-oneliners — однострочники, пайпы, текстовая обработка.
  • #course-announcements — обновления и важные объявления.
  • Домашний проект

    Проект: bootstrap-скрипт диагностики Perl-окружения для DevOps

    Напишите скрипт
    perl_doctor.pl, который запускается и так:

  • perl perl_doctor.pl
  • ./perl_doctor.pl
  • Требования:

  • В начале: use strict; use warnings;.
  • Печатает:
  • - путь к Perl (
    ^V) - текущего пользователя ($ENV{USER} или альтернативно из окружения) - текущую директорию (используйте системный вызов через backticks или модуль будет позже, поэтому пока допустим простой вариант)
  • Завершает работу кодом 0 при успехе.
  • Если переменная окружения USER не определена, печатает предупреждение через warn и всё равно продолжает.
  • Формат сдачи:

  • один файл perl_doctor.pl
  • пример вывода (копипаст из терминала)
  • команда, которой вы запускали (оба варианта)
  • Рекомендация для DevOps-стиля: вывод должен быть читабельным и стабильным, чтобы его можно было прикрутить к CI.

    Что закрепляем перед следующим уроком

    Дальше мы начнём синтаксис со скаляров и строк. Перед этим важно уверенно владеть:

  • запуском Perl-скриптов
  • strict/warnings
  • perldoc`
  • базовыми one-liners
  • Полезные ссылки:

  • The Perl Programming Language
  • perldoc.perl.org
  • perlbrew (App::perlbrew) на GitHub
  • Visual Studio Code Docs
  • Padre на MetaCPAN
  • 2. База языка: скаляры, строки, операторы, массивы и хэши

    База языка: скаляры, строки, операторы, массивы и хэши

    Как этот урок связан с предыдущим

    В предыдущем уроке вы подняли окружение (Perl на Ubuntu, запуск через perl script.pl и через shebang), закрепили production-стиль с use strict; use warnings; и научились проверять синтаксис через perl -c.

    Дальше вы будете читать и писать реальный Perl-код. Для этого нужно понять базовые типы данных и правила работы с ними:

  • скаляры (scalar)
  • строки (strings)
  • операторы (operators)
  • массивы (arrays)
  • хэши (hashes)
  • Основной DevOps-вывод: в Perl часто решают инфраструктурные задачи через быструю работу со строками, коллекциями и контекстом.

    Справочники, к которым вы будете возвращаться:

  • perldata
  • perlsyn
  • perlfunc
  • Сигилы и базовые структуры данных

    Perl отличает тип данных по сигилу (sigil) в имени переменной:

  • `:
  • Скаляр: что это и как с ним жить в DevOps

    Скаляр (scalar) хранит одно значение: число, строку, undef (отсутствие значения), ссылку (позже).

    Минимальный шаблон скрипта, который мы продолжаем использовать:

    Объявление переменных и область видимости

    Используйте
    my для лексических переменных. Это базовая дисциплина под strict.

    defined отвечает на вопрос: значение определено или это undef.

    Истина и ложь

    Ложными (false) обычно считаются:

  • undef
  • 0 (число ноль)
  • "" (пустая строка)
  • "0" (строка, содержащая ноль)
  • Остальное обычно истинно (true).

    Строки: кавычки, интерполяция и безопасная сборка

    Perl очень силён в строках, но важно понимать различия кавычек.

    Одинарные и двойные кавычки

  • '' — почти без интерполяции (переменные не подставляются)
  • "" — с интерполяцией (подставляются переменные, \n, \t и часть escape-последовательностей)
  • qw// для списков слов

    qw// создаёт список строк, разделённых пробелами.

    length, substr, index часто встречаются в утилитных скриптах:

    sprintf помогает делать стабильный формат вывода (удобно для логов и CI):

    Операторы: самое нужное для первых скриптов

    Конкатенация и повтор

  • . — конкатенация строк
  • x — повтор строки
  • Числовые и строковые сравнения

    В Perl есть разные операторы для чисел и строк. Это один из самых частых источников багов у новичков.

  • Числовые: ==, !=, <, >, <=, >=
  • Строковые: eq, ne, lt, gt, le, ge
  • Логические операторы и defined-or

  • && и || — логические операторы
  • // — defined-or: берёт правую часть, только если слева undef
  • perl my @hosts = ("app-1", "app-2", "db-1"); print hosts[-1] . "\n"; # последний элемент

    my n\n"; perl my @q = ("a");

    push @q, "b"; # добавить в конец my first = shift @q; # снять с начала perl my @parts = ("10.0.0.1", "10.0.0.2"); my csv\n";

    my k, line, 2); print "k=v\n"; perl my %ports = ( nginx => 80, ssh => 22, );

    print cfg{region} = "eu-central-1"; h{a}; print "c exists\n" if exists h{b};

    delete h{key} проверяет наличие ключа

  • defined ENV{USER} // ""),
  • PATH => (k (sort keys %env) { print "env{line = <STDIN>) { chomp line eq ""; next if k, line, 2); k} = k (sort keys %kv) { print "kv{code = "0200";

    print "numeric ok\n" if code eq "200"; # строго по строке bash printf "# comment\nUSER = deploy\nEMPTY=\nUSER=ops\n" | perl env_norm.pl `

    Ожидаемое свойство результата: стабильный порядок и одинаковый вывод при повторных запусках.

    Подсказка: для сборки строк используйте конкатенацию ., для защиты кавычек пока достаточно заменить " на \" (полноценное экранирование мы улучшим позже).

    Что нужно уверенно знать перед следующим уроком

    В следующих уроках вы начнёте управляющие конструкции и подпрограммы, поэтому база должна быть автоматической:

  • объявление переменных через my
  • понимание undef и defined
  • строки и интерполяция
  • операторы . eq == //`
  • базовые операции с массивами и хэшами
  • Полезно перечитать:

  • perldata
  • perlop
  • 3. Управление потоком: if/else, циклы, подпрограммы, scope

    Управление потоком: if/else, циклы, подпрограммы, scope

    Как этот урок связан с предыдущими

    В прошлых уроках вы настроили окружение, закрепили дисциплину use strict; use warnings;, а затем разобрали базовые типы данных: скаляры, строки, массивы и хэши.

    Теперь мы соберём из этих “кирпичиков” управляемые сценарии: ветвления, циклы и повторно используемые подпрограммы. Это фундамент для DevOps-скриптов: обработка списков хостов, фильтрация логов, контроль статусов, ретраи, предсказуемые ошибки.

    Ключевые страницы документации, которые стоит держать рядом:

  • perlsyn
  • perlsub
  • perlfunc
  • perlop
  • Ветвление: if/elsif/else, unless, тернарный оператор

    Базовый if/elsif/else

    perl my @ports = (22, 80, 443);

    for (my i < @ports; i port=i]\n"; } perl #!/usr/bin/env perl use strict; use warnings;

    while (my line;

    next if line =~ /^\s*#/;

    print "line=line = <STDIN>) естественным образом заканчивает цикл.

    until

    until — это “while наоборот”: крутится, пока условие ложно.

    В эксплуатации чаще используют while, а until оставляют для действительно читаемых случаев.

    Управление циклом: next/last/redo

  • next — перейти к следующей итерации
  • last — выйти из цикла
  • redo — повторить текущую итерацию без проверки условия
  • Пример: пропуск мусора, ограничение по числу обработанных строк, и повторная попытка при “пустой” строке.

    Возврат значения: return и “последнее выражение”

    return завершает функцию явно.

    Если вы не уверены, нужен ли local, почти наверняка вам достаточно my.

    !как временная подмена специальной переменной внутри функции и всех вызванных ею функций. Использовать простые цвета, стрелки видимости, подписи “lexical”, “package”, “dynamic”. | Схема, которая визуально различает my/our/local и их области видимости

    Сквозной пример: мини-утилита фильтрации и агрегации событий из stdin

    Ниже — цельный пример, который одновременно использует ветвления, циклы, подпрограммы и my-scope. Он читает строки, классифицирует их по уровню и печатает сводку.

    Формат входа простой: строки вида LEVEL message..., где LEVEL это INFO, WARN или ERROR.

    Пример запуска:

    !Flowchart, который закрепляет, как if/next/while/sub работают вместе

    Типичные ошибки и как их избегать

  • Путать = и == в условиях
  • Путать строковые и числовые сравнения
  • Забывать my и случайно использовать переменную “из воздуха” (под strict это обычно ловится)
  • Сложные условия в одну строку (лучше разнести на блоки и дать переменным имена)
  • Не сортировать ключи при выводе хэша, если вывод пойдёт в CI/diff
  • Видео-скрипт для урока

  • Кадр: быстрый повтор сигилов x “пропадает” за пределами блока, пояснить our и когда он встречается.
  • Финал: собрать мини-утилиту подсчёта уровней и показать стабильный вывод (сортировка ключей).
  • Прогресс-трекер и геймификация

    Трекер

    | Активность | Статус | |---|---| | Понимаю if/elsif/else и использую строковые сравнения eq/ne | ☐ | | Использую постфиксные if/unless для guard-checks (next if ...) | ☐ | | Умею писать for/foreach по массиву и while для чтения stdin | ☐ | | Понимаю next и last, могу применить метки для вложенных циклов | ☐ | | Пишу sub, принимаю параметры через @_, возвращаю значение через return | ☐ | | Понимаю scope: когда нужен my, и что такое our и local | ☐ |

    Бейджи

  • Badge: Flow Controller — уверенно применяешь if/else, циклы, next/last.
  • Badge: Script Architect — выделяешь логику в sub и держишь переменные в правильном scope.
  • Лидерборд

    Очки начисляются за домашний проект: чистота кода под strict/warnings, читаемость условий, отсутствие “магических” глобальных переменных, стабильный вывод.

    Чаты по темам

  • #control-flow — условия, циклы, next/last, метки
  • #perl-subroutinessub, параметры @_, return, паттерны разбиения логики
  • #scope-and-varsmy/our/local, видимость переменных, спецпеременные
  • Домашний проект

    Проект: CLI-фильтр для логов с правилами и сводкой

    Напишите скрипт log_triage.pl, который читает строки из STDIN и выводит:

  • нормализованные строки (опционально, если установлен DEBUG=1 в окружении)
  • итоговую сводку счётчиков в конце
  • Требования:

  • в начале use strict; use warnings;
  • вход: строки вида LEVEL message..., игнорировать пустые строки и комментарии # ...
  • поддержать уровни: INFO, WARN, ERROR плюс алиасы ERR -> ERROR, WARNING -> WARN
  • реализация должна использовать как минимум две подпрограммы: parse_ и normalize_
  • использовать next для пропуска строк и exists для проверки известных уровней
  • в конце печатать сводку в стабильном порядке (сортировка ключей)
  • Формат сдачи:

  • файл log_triage.pl
  • пример команды запуска (пайп через printf или cat)
  • пример вывода
  • Подсказка по DevOps-стилю: делайте вывод стабильным и “машиночитаемым” (например KEY=value`), чтобы это легко подключалось в CI.

    4. Текст и данные: регулярные выражения, grep/map, парсинг логов

    Текст и данные: регулярные выражения, grep/map, парсинг логов

    Как этот урок связан с предыдущими

    Ранее вы освоили базовые типы данных (скаляры, массивы, хэши), научились писать предсказуемый код под use strict; use warnings;, а также строить сценарии через if/else, циклы и sub.

    Теперь мы берём главное практическое оружие Perl для DevOps: регулярные выражения (regex) и связку поток строк → фильтрация → преобразование → агрегация. Это напрямую ложится на задачи эксплуатации:

  • парсинг логов (Nginx, systemd, Jenkins/GitLab runner)
  • вычленение метрик (HTTP-коды, latency, size)
  • нормализация сообщений (маскирование токенов)
  • быстрые фильтры в пайплайнах
  • Справочники, которые стоит держать рядом:

  • perlre
  • perlreref
  • perlfunc
  • Регулярные выражения в Perl: минимальная модель

    Регулярное выражение в Perl чаще всего встречается в трёх операциях:

  • m// или просто //поиск совпадения
  • s///замена
  • split /.../разбиение
  • Важно: regex почти всегда применяется к строке через оператор связывания =~.

    Если написать !~, это означает “не совпало”.

    perl my line =~ /ERROR/i; perl my line =~ /^ERROR/; print "ends with digits\n" if /; perl my s =~ /\b\d{3}\b/; perl if (1, & — вся совпавшая подстрока

    > Практика эксплуатации: старайтесь не строить архитектуру на 1, line = "HTTP 503 from upstream";

    if (code = code\n"; } perl my line =~ /req_id=(?<reqid>\w+)\s+status=(?<status>\d{3})/) { print "reqid=+{status}\n"; }

    Глобальная замена с g

    perl my s =~ /\[(.*)\]/) { print "captured=s =~ /\[(.*?)\]/) { print "captured=re_http = qr/\b(?<status>\d{3})\b/;

    while (my line =~ +{status}\n"; } } perl my @lines = ( "INFO started", "ERROR failed", "WARN disk", );

    my @bad = grep { /^(?:ERROR|WARN)\b/ } @lines; print join("\n", @bad) . "\n";

    Типичный паттерн: grep + map

    Например, взять только строки с HTTP-кодами 5xx и вытащить код.

    > Практика эксплуатации: для потоковой обработки больших логов чаще используйте while (<STDIN>), а grep/map оставляйте для сравнительно небольших списков, чтобы не держать всё в памяти.

    Парсинг логов: практический мини-парсер Nginx access log

    Упрощённый формат

    Часто встречается формат вроде:

  • ip - - [time] "METHOD path HTTP/1.1" status bytes "referer" "ua"
  • Мы не будем строить “идеальный” парсер на все случаи, а сделаем надёжный для типового продакшена, с проверками и понятным фолбеком.

    Скрипт: извлекаем ip, method, path, status, считаем статистику

    Создайте nginx_triage.pl:

    > Для сложной логики лучше переходить от one-liner к скрипту: появятся strict/warnings, функции, тестируемость и меньше риск “сломать прод”.

    Типичные ошибки в regex для DevOps и как их избегать

  • Слишком общий .* без якорей
  • - лучше фиксировать контекст: ^... или конкретные разделители
  • Забыть про минимальный режим *?, когда в строке несколько похожих фрагментов
  • Парсить “всё одним огромным regex”
  • - чаще надёжнее: вытащить ключевые поля и валидировать их отдельно
  • Не обрабатывать “не распарсилось”
  • - в утилитах для эксплуатации “молчаливое” принятие мусора приводит к неверным метрикам

    Видео-скрипт для урока

  • Кадр: напоминание о стиле скрипта (use strict; use warnings;) и о паттерне while (<STDIN>) { ... }.
  • Показ =~ и !~ на простом поиске ERROR.
  • Разбор флагов i и g на примере нормализации пробелов и регистронезависимого поиска.
  • Захват групп: сначала +{name}.
  • Демонстрация “жадности”: \[(.)\] vs \[(.?)\].
  • Переход к grep и map: фильтруем строки с 5xx, затем вытаскиваем коды.
  • Сборка nginx_triage.pl: пишем parse_nginx_access, добавляем счётчики, показываем DEBUG=1.
  • Финал: one-liner примеры и правило “если усложняется — превращай в нормальный скрипт”.
  • Прогресс-трекер и геймификация

    Трекер

    | Активность | Статус | |---|---| | Понимаю =~ и !~, умею искать совпадение через // | ☐ | | Использую группы (...) и понимаю $1, а также именованные группы (?<x>...) | ☐ | | Умею делать замены через s/// и глобально через g | ☐ | | Понимаю “жадность” и умею применять *? | ☐ | | Умею использовать grep для фильтрации и map для преобразования | ☐ | | Написал потоковый парсер логов через while (<STDIN>) и стабильную сводку | ☐ |

    Бейджи

  • Badge: Regex Operator — уверенно применяешь m// и s///, группы и флаги.
  • Badge: Log Wrangler — написал парсер логов со сводкой и обработкой ошибок парсинга.
  • Лидерборд

    Очки начисляются за домашний проект: качество regex (точность, читаемость), обработка “не распарсилось”, стабильность вывода и аккуратная структура через sub.

    Чаты по темам

  • #regex-basics — флаги, группы, якоря, жадность
  • #grep-map — обработка списков, idioms, читаемость
  • #log-parsing — разбор реальных логов (Nginx, systemd, Jenkins)
  • #oneliners — безопасные one-liners и превращение их в скрипты
  • Домашний проект

    Проект: triage-утилита для логов с маскированием секретов и отчётом

    Напишите скрипт log_inspector.pl, который читает строки из STDIN и печатает сводку.

    Требования:

  • в начале: use strict; use warnings;
  • вход: произвольные строки логов
  • функциональность:
  • - маскировать секреты в строках перед выводом (минимум token=... и password=... через s///) - извлекать уровень события, если строка начинается с INFO, WARN, WARNING, ERROR, ERR (уровни нормализовать) - извлекать HTTP-статус, если встречается отдельное число из трёх цифр, и считать распределение - считать топ-3 “причины”, если строка содержит шаблон reason=... (значение до пробела)
  • структура:
  • - минимум 3 подпрограммы: mask_secrets, normalize_level, extract_fields - для уровней и статусов использовать хэши-счётчики
  • вывод:
  • - стабильный, машиночитаемый (key=value), ключи сортировать - при DEBUG=1 печатать нормализованные строки (уже замаскированные)

    Формат сдачи:

  • файл log_inspector.pl
  • команда запуска с примером входа через printf или cat
  • пример вывода
  • Подсказка: начните с маленького набора строк (5–10), отладьте regex и только потом запускайте на больших логах.

    5. IO и надежность: файлы/директории, flock, исключения, отладка

    IO и надежность: файлы/директории, flock, исключения, отладка

    Как этот урок связан с предыдущими

    Ранее вы научились обрабатывать поток строк (stdin), писать предсказуемые скрипты с use strict; use warnings;, использовать regex для парсинга логов и агрегировать данные в хэши.

    Следующий практический шаг для DevOps-скриптинга на Perl: научиться надёжно работать с файлами и директориями, не ломать данные при параллельных запусках, и уметь быстро находить причину сбоя.

    В этом уроке мы разберём:

  • IO-основы: корректный open, режимы чтения/записи, обработка ошибок.
  • Директории: opendir/readdir, безопасные пути.
  • Блокировки: flock для защиты от гонок и параллельных запусков.
  • Исключения: die/warn, eval, fh, '<', path) failed: fh создаёт лексический filehandle, он безопаснее и проще для поддержки.
  • '<', ! содержит текст системной ошибки (например, Permission denied).
  • Режимы открытия, которые нужны чаще всего

    | Режим | Смысл | Когда использовать | |---|---|---| | < | чтение | чтение логов, конфигов | | > | перезапись | генерация отчёта заново | | >> | дозапись | писать в общий лог | | +< | чтение/запись | редко, осторожно |

    Мини-шаблон чтения файла построчно

    Практический смысл close(... ) or die ...: ошибки записи иногда проявляются только при закрытии (например, переполнен диск или оборвалась сеть при записи на сетевой FS).

    Кодировки и binmode

    В DevOps часто встречаются бинарные данные (gzip, tar, protobuf) и текст с разными кодировками.

  • Для текста на UTF-8 можно явно указать слой:
  • Если вы не уверены, что данные текстовые, лучше начинать с :raw, иначе вы можете получить неочевидные проблемы при чтении.

    Проверки файлов и директорий

    Perl имеет встроенные file test operators. Они часто делают код короче и яснее.

  • -e path это файл
  • -d path размер файла (в байтах), либо false если пустой
  • -r path доступен на запись
  • Пример в стиле эксплуатации:

    mkdir и права

    Запуск:

    Прогресс-трекер и геймификация

    Трекер

    | Активность | Статус | |---|---| | Использую трёхаргументный open и проверяю ошибки через line = <@ | ☐ | | Использую perl -d и Data::Dumper для отладки | ☐ |

    Бейджи

  • Badge: IO Reliable — используешь open/close с проверками и атомарную запись.
  • Badge: Concurrency Safe — защищаешь скрипты от параллельных запусков через flock.
  • Badge: Debug Ready — умеешь быстро найти проблему через debugger и Dumper.
  • Чаты по темам

  • #io-filesopen/close, режимы, кодировки, binmode, атомарные записи
  • #locks-flockflock, lockfiles, cron, гонки и параллелизм
  • #exceptionsdie/warn, eval, !
  • потоковая обработка
  • атомарная запись результатов
  • блокировки через flock
  • перехват ошибок через eval и диагностика через debugger
  • 6. Экосистема: модули CPAN (cpanm), JSON/LWP/DBI, OOP (bless/Moose)

    Экосистема: модули CPAN (cpanm), JSON/LWP/DBI, OOP (bless/Moose)

    Как этот урок связан с предыдущими

    Раньше вы писали потоковые утилиты, парсили текст и логи, а также делали надёжный IO: корректный open, атомарная запись, flock, обработка ошибок через die/warn/eval и отладка.

    Теперь вы переходите от одного файла-скрипта к настоящей экосистеме Perl: готовые библиотеки, управление зависимостями, HTTP-клиенты, JSON, работа с базами данных и объектный код. Это критично для DevOps-задач, где нужно:

  • быстро интегрироваться с API (GitLab/Jenkins/Nexus/Prometheus)
  • читать и писать JSON-конфиги/ответы
  • надёжно работать с БД (инвентаризация, CMDB, аудит)
  • поддерживать большой код (структура, тестируемость, расширяемость)
  • Полезные источники:

  • MetaCPAN (поиск модулей и документации)
  • CPAN (экосистема Perl)
  • App::cpanminus (cpanm)
  • local::lib
  • !Схема жизненного цикла зависимости: от поиска до запуска в CI

    Что такое CPAN и почему DevOps-инженеру это важно

    CPAN (Comprehensive Perl Archive Network) это огромный каталог модулей Perl.

    Практический DevOps-смысл:

  • вы почти никогда не пишете “вручную” HTTP, JSON, DB, CLI-парсинг, логирование
  • вы можете быстро собирать production-ready утилиты, используя проверенные модули
  • вы можете фиксировать версии зависимостей и повторяемо разворачивать окружение (важно для CI/CD)
  • use и где Perl ищет модули: @INC, PERL5LIB

    Когда вы пишете:

    Perl ищет JSON.pm в путях массива @INC.

    Быстро посмотреть @INC:

    Временное добавление пути при запуске:

    Через переменную окружения:

    DevOps-правило: лучше явно управлять тем, откуда берутся модули (особенно в CI), чем надеяться на “что-то уже установлено на сервере”.

    Установка модулей: cpanm и безопасный workflow

    Почему чаще выбирают cpanm

    cpanm (cpanminus) это практичный установщик CPAN-модулей: меньше интерактива, удобнее для автоматизации.

    Документация: App::cpanminus (cpanm)

    Установка cpanm на Ubuntu

    Вариант через apt (часто достаточно):

    Проверка:

    Не ломаем системный Perl: local::lib

    Системный Perl на Ubuntu часто используется пакетами ОС. Для своих скриптов и зависимостей используйте установку в домашний каталог.

    Документация: local::lib

    Быстрый старт:

    После настройки local::lib модули будут ставиться в пользовательский каталог, а PERL5LIB и PATH будут настроены.

    Установка модуля в локальный каталог одной командой

    Если вы хотите явно указать каталог (полезно для CI job):

    Запуск с таким окружением обычно делается так:

    Использование (скрипт timer_demo.pl):

    DevOps-заметка: FindBin и lib позволяют хранить собственные модули в ./lib рядом со скриптом.

    Документация:

  • FindBin
  • lib (pragma)
  • Наследование на минималках: @ISA

    Использование:

    ``perl #!/usr/bin/env perl use strict; use warnings;

    use FindBin; use lib "c = DevOps::HTTPClient->new(base_url => 'https://example.com'); my c->get_path('/health');

    print "status=" . {url}${path} - выставить таймаут - если ответ не 2xx завершаться через die с понятным сообщением

  • JSON:
  • - попытаться распарсить тело как JSON - если JSON не парсится, завершаться через die
  • вывод:
  • - печатать стабильный машиночитаемый результат, например: - http_status=200 - json_type=HASH|ARRAY - json_keys=a,b,c (если это HASH)
  • БД (опционально):
  • - таблица (пример): api_checks(ts bigint, url text, path text, http_status int, json_type text) - вставка только через placeholders
  • код:
  • - минимум один класс на Moose или на bless (на ваш выбор), но структура должна быть модульной (логика не вся в одном файле)

    Критерии приёмки:

  • зависимости поднимаются повторяемо (carton install на чистой машине)
  • HTTP и JSON ошибки не игнорируются
  • если включена БД, нет склейки SQL строкой, только placeholders
  • скрипт работает предсказуемо под use strict; use warnings;
  • 7. Экспертный DevOps: performance, threading, cron, security, портфолио-проекты

    Экспертный DevOps: performance, threading, cron, security, портфолио-проекты

    Как этот урок связан с предыдущими

    Ранее вы научились писать предсказуемые Perl-скрипты под use strict; use warnings;, обрабатывать потоки данных и логи через regex, делать надёжный IO (включая атомарную запись и flock), а также подключать зависимости через CPAN (cpanm, local::lib, Carton), работать с HTTP/JSON/DBI и строить модульный код, включая OOP.

    Этот урок переводит вас в режим экспертного DevOps: вы будете думать не только про то, чтобы скрипт работал, но и про то, чтобы он был:

  • быстрым и предсказуемым по ресурсам
  • безопасным по входным данным и окружению
  • корректным при параллельных запусках
  • удобным для запуска по расписанию (cron/systemd timers)
  • оформленным как портфолио-проект с качеством, близким к production
  • Ключевые справочники:

  • Benchmark
  • Time::HiRes
  • threads
  • Thread::Queue
  • perlsec
  • perlipc
  • File::Temp
  • autodie
  • Performance: измеряем, потом оптимизируем

    В DevOps-скриптинге перформанс важен в двух местах:

  • потоковая обработка больших логов (гигабайты текста)
  • массовые операции (тысячи хостов, тысячи HTTP-запросов, большие JSON)
  • Главное правило: сначала измеряем, потом меняем код. Иначе легко «оптимизировать» не то место.

    !Процесс: от измерения до повторной проверки после оптимизации

    Быстрое измерение времени: Time::HiRes

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

    Практический смысл для DevOps: вы можете сравнивать разные варианты парсинга, IO или нормализации и не спорить «на глаз».

    Микробенчмарк: Benchmark

    Benchmark помогает сравнивать два подхода на одинаковой нагрузке.

    perl #!/usr/bin/env perl use strict; use warnings;

    use threads; use Thread::Queue;

    my ENV{WORKERS} // 4;

    my out_q = Thread::Queue->new();

    sub worker { while (defined(my in_q->dequeue())) { # пример "работы": считаем 5xx my job =~ /\b5\d{2}\b/) ? 1 : 0; is_5xx); } return; }

    my @ts; for (1..line = <STDIN>) { chomp line eq ''; line); }

    sentinels: по одному на воркер

    workers);

    collector

    my bad = 0;

    ждём завершения воркеров

    x = total++; x; }

    print "total_jobs=bad\n"; perl #!/usr/bin/env perl use strict; use warnings;

    use Fcntl qw(:flock); use File::Temp qw(tempfile);

    my 0 <input> <output>\n"; my 0 <input> <output>\n";

    open(my out_path.lock") or die "open lock failed: lock_fh, LOCK_EX | LOCK_NB) or die "another instance is running\n";

    open(my in_path) or die "open(!";

    my %count; my re = qr/\b(?<st>\d{3})\b/;

    while (my in>) { line =~ count{ENV{DEBUG}; } }

    close(in_path) failed: tmp_fh, tmp_fh "total_lines=!"; for my tmp_fh "status_count{!"; }

    close(!"; rename(out_path) or die "rename failed: out_path\n"; exit 0;

    Почему это безопаснее:

  • аргументы не интерпретируются shell-ом
  • снижается риск инъекции через пробелы, ;, | и подстановки
  • Если вам нужно читать stdout/stderr команды, смотрите IPC-подсистему:

  • perlipc
  • Taint mode: -T как режим повышенной строгости

    Taint mode помечает данные из внешних источников (ARGV/ENV/STDIN) как «грязные» и запрещает использовать их в опасных операциях, пока вы явно не «очистите» значения.

    Запуск:

    Taint mode особенно полезен для скриптов, которые:

  • запускаются с повышенными правами
  • принимают внешние параметры
  • строят пути и команды
  • Валидация ввода через allowlist

    Практика DevOps: не пытайтесь «запретить плохое», лучше «разрешить хорошее».

    Пример: разрешим имя окружения только из букв, цифр, _ и -.

    Здесь \A и \z это жёсткие якоря начала и конца строки.

    Секреты: маскирование и минимизация вывода

  • Никогда не печатайте токены и пароли целиком.
  • Никогда не кладите секреты в исключения (die) без маскирования.
  • Логи должны быть полезными, но не токсичными.
  • Мини-шаблон маскирования:

    Права и принцип наименьших привилегий

  • запускать скрипт от пользователя с минимальными правами
  • задавать разумные права при mkdir и записи файлов
  • не писать секреты в world-readable каталоги
  • Наблюдаемость: логи, метрики, exit codes

    Даже лучший скрипт бесполезен, если он «молча» ломается.

    Минимальные практики:

  • stdout для «нормального результата» (если это CLI)
  • stderr для проблем и диагностики
  • стабильные коды выхода: 0 успех, != 0 ошибка
  • машиночитаемый вывод (key=value) для интеграции с CI и мониторингом
  • Если вы хотите syslog:

  • Sys::Syslog
  • Портфолио-проекты: что делать, чтобы вас считали Perl-экспертом в DevOps

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

    Требование к каждому портфолио-проекту

  • структура bin/, lib/, cpanfile, запуск через carton exec
  • надёжность IO: open с проверками, атомарная запись, flock
  • безопасность: list form system, маскирование секретов, allowlist валидации
  • тесты на ключевую логику
  • Для тестов используйте core-модуль:

  • Test::More
  • Рекомендуемая структура:

    Проект: парсер логов Jenkins или GitLab Runner

    Идея: потоково читать лог, извлекать job-id, стадии, длительности, статусы, строить отчёт.

    Что демонстрирует:

  • regex и устойчивый парсинг
  • performance (потоково, без лишних аллокаций)
  • атомарную запись отчёта
  • опциональный режим DEBUG=1
  • Проект: мониторинг SLA по HTTP и запись в БД

    Идея: периодически дергать endpoint, измерять latency, писать в PostgreSQL через DBI.

    Что демонстрирует:

  • LWP::UserAgent с timeouts
  • Time::HiRes для latency
  • DBI placeholders и обработку ошибок
  • cron-safe запуск с lockfile
  • Проект: автоматизатор бэкапов 1C или любой enterprise-системы

    Идея: запуск команд бэкапа, сбор stdout/stderr, ротация файлов, отчёт.

    Что демонстрирует:

  • безопасность системных вызовов
  • корректная работа с файлами и правами
  • надёжный результат под параллельными запусками
  • Проект: security-sanitizer для логов

    Идея: утилита, которая принимает поток логов, маскирует секреты, нормализует поля, генерирует безопасный вывод.

    Что демонстрирует:

  • безопасную работу с чувствительными данными
  • аккуратные regex
  • производительность на больших потоках
  • Видео-скрипт для урока

  • Кадр: проблема эксплуатации: «скрипт работает, но медленно и иногда ломает файлы при cron».
  • Performance: показать Time::HiRes и сравнить два подхода на одном вводе.
  • Benchmark: запустить cmpthese, объяснить что сравниваем и почему.
  • Threading: объяснить, что Perl threads не бесплатны, затем показать Thread::Queue producer-consumer.
  • Cron-safe: собрать шаблон flock + File::Temp + rename, объяснить почему так надёжнее.
  • Security: показать разницу system("...") и system('cmd', @args), объяснить shell injection.
  • Портфолио: показать структуру репозитория bin/lib/t/cpanfile, коротко объяснить, что проверяет работодатель.
  • Прогресс-трекер и геймификация

    Трекер

    | Активность | Статус | |---|---| | Измеряю время через Time::HiRes и сравниваю подходы через Benchmark | ☐ | | Знаю типовые hotspots: IO, regex, лишние аллокации, системные вызовы | ☐ | | Понимаю модель threads и могу собрать worker-pool через Thread::Queue | ☐ | | Делаю cron-safe job: flock + атомарная запись + стабильный вывод | ☐ | | Применяю security-минимум: list form system, allowlist валидации, маскирование секретов | ☐ | | Оформляю проект как production: cpanfile, carton exec, bin/lib/t | ☐ |

    Бейджи

  • Badge: Performance Engineer — измеряешь, находишь hotspot, оптимизируешь без потери корректности.
  • Badge: Cron-Safe Operator — задания не ломают файлы и не запускаются параллельно.
  • Badge: Secure Scripter — нет shell injection, есть валидация ввода и маскирование секретов.
  • Badge: Portfolio Ready — проект выглядит как production-утилита с тестами и зависимостями.
  • Чаты по темам

  • #perf-benchmarkingBenchmark, профилирование, regex и IO performance
  • #threads-and-concurrency — воркеры, очереди, корректное завершение, ограничения
  • #cron-and-scheduling — cron/systemd timers, lockfiles, отчёты, ротация
  • #perl-securityperlsec, taint mode, валидация, работа с секретами
  • #portfolio-review — ревью проектов, структура, тесты, best practices
  • Домашний проект

    Проект: production-ready cron-safe triage с параллельной обработкой и безопасностью

    Сделайте утилиту-проект, которая обрабатывает большой лог и генерирует отчёт.

    Требования:

  • Репозиторий с bin/, lib/, t/, cpanfile и запуском через carton exec.
  • Скрипт bin/triage_job.pl принимает:
  • --input путь к логу
  • --output путь к отчёту
  • --workers число воркеров (по умолчанию 4)
  • Надёжность:
  • lockfile через flock рядом с output
  • запись отчёта через File::Temp + rename
  • машиночитаемый вывод отчёта (key=value)
  • Параллелизм:
  • использовать threads + Thread::Queue
  • каждый воркер считает локальные счётчики и возвращает результаты в collector
  • Security:
  • маскирование секретов в диагностике (если печатаете строки)
  • запретить опасные пути: allowlist на basename отчёта или проверка, что output лежит в разрешённой директории
  • Тесты:
  • минимум 3 теста на функции парсинга и маскирования
  • Критерии приёмки:

  • при параллельном запуске второй процесс завершается с понятной ошибкой
  • отчёт никогда не бывает частично записан
  • на тестовом логе из 100000 строк выполнение не деградирует из-за лишней памяти
  • в выводе и ошибках нет утечек секретов