{
  "categories": [
    {
      "id": "linux",
      "name": "Linux",
      "description": "Команды, система и повседневная работа в терминале.",
      "icon": "terminal"
    },
    {
      "id": "windows",
      "name": "Windows",
      "description": "Практичные инструкции для знакомой системы.",
      "icon": "window"
    },
    {
      "id": "wordpress",
      "name": "WordPress",
      "description": "Структура сайта, контент и маленькие улучшения.",
      "icon": "layers"
    },
    {
      "id": "networks",
      "name": "Сети",
      "description": "DNS, HTTP и понятная диагностика соединений.",
      "icon": "network"
    },
    {
      "id": "tools",
      "name": "Инструменты",
      "description": "Утилиты и приёмы, которые экономят несколько минут.",
      "icon": "wrench"
    },
    {
      "id": "notes",
      "name": "Личные заметки",
      "description": "Наблюдения, рабочие привычки и порядок в знаниях.",
      "icon": "bookmark"
    }
  ],
  "notes": [
    {
      "slug": "linux-disk-space",
      "title": "Куда уходит место на диске в Linux",
      "excerpt": "От общего объёма файловой системы до тяжёлых каталогов — спокойная диагностика в несколько шагов.",
      "category": "linux",
      "tags": [
        "Диск",
        "Терминал",
        "Диагностика"
      ],
      "date": "2026-10-28",
      "minutes": 9,
      "featured": true,
      "kind": "Инструкция",
      "blocks": [
        {
          "type": "paragraph",
          "text": "Если свободное место внезапно заканчивается, сначала полезно понять масштаб, а уже затем искать конкретные файлы. Здесь собран маршрут из небольших проверок: каждая отвечает на один вопрос и помогает выбрать следующий шаг. Все приведённые команды читают информацию и ничего не удаляют. Примеры рассчитаны на обычную Linux-систему с GNU coreutils."
        },
        {
          "type": "callout",
          "title": "Сначала измеряем",
          "text": "Не начинайте с удаления журналов, кешей и незнакомых каталогов. Даже временный на вид файл может быть нужен работающей программе. Сначала определите файловую систему, владельца данных и причину роста."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "filesystem",
          "text": "1. Смотрим на файловые системы"
        },
        {
          "type": "paragraph",
          "text": "Одна система может использовать несколько разделов: для корня, домашнего каталога или подключённого диска. Свободное место на одном разделе не помогает другому автоматически. Начните с общей таблицы и найдите строку, относящуюся к каталогу, с которым возникла проблема. Размеры с суффиксами K, M и G проще читать, чем длинные числа байтов."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Общий объём и свободное место",
          "text": "df -h"
        },
        {
          "type": "paragraph",
          "text": "Если интересует только домашний каталог, передайте его путь. Так вы получите сведения о файловой системе, на которой он действительно находится, а не обо всех подключённых носителях сразу. Обращайте внимание не только на процент заполнения, но и на оставшийся абсолютный объём: одинаковые 90 процентов означают совершенно разный запас на маленьком и большом диске."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Файловая система домашнего каталога",
          "text": "df -h -- \"$HOME\""
        },
        {
          "type": "heading",
          "level": 2,
          "id": "directories",
          "text": "2. Ищем самые крупные каталоги"
        },
        {
          "type": "paragraph",
          "text": "Теперь можно перейти от раздела к данным. Команда du обходит каталог и суммирует занятые блоки. На первом проходе достаточно одного уровня глубины: длинный список отдельных файлов обычно мешает увидеть главное. Ключ -x ограничивает обход одной файловой системой, чтобы случайно не посчитать подключённые внутри неё диски и сетевые ресурсы."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Размер каталогов первого уровня",
          "text": "du -xh --max-depth=1 -- \"$HOME\" 2>/dev/null | sort -h"
        },
        {
          "type": "paragraph",
          "text": "Последние строки отсортированного списка покажут самых заметных кандидатов. После этого повторите измерение внутри одного выбранного каталога. Такой спуск по дереву обычно быстрее, чем поиск по всему диску. При первом знакомстве с системой полезно записать несколько итоговых размеров: сравнение через неделю даст больше контекста, чем единственное измерение прямо сейчас."
        },
        {
          "type": "details",
          "summary": "Почему здесь скрыты сообщения об ошибках?",
          "text": "Перенаправление 2>/dev/null убирает сообщения о каталогах, к которым нет доступа. Оно делает пример короче, но не расширяет права пользователя. Если итоговые числа выглядят неполными, повторите команду без этого перенаправления и прочитайте сообщения. Не добавляйте sudo автоматически."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "large-files",
          "text": "3. Находим отдельные большие файлы"
        },
        {
          "type": "paragraph",
          "text": "Иногда место занимает один образ диска, видеофайл или забытая выгрузка. Когда крупный каталог уже найден, имеет смысл поискать внутри него файлы больше заданного порога. В примере порог равен 100 МиБ. Список ограничен домашним каталогом и одной файловой системой; это разумная отправная точка для собственного рабочего компьютера."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Файлы крупнее 100 МиБ",
          "text": "find \"$HOME\" -xdev -type f -size +100M -printf '%s\\t%p\\n' 2>/dev/null | sort -nr | head -n 20"
        },
        {
          "type": "paragraph",
          "text": "Первое число в каждой строке — логический размер файла в байтах. Оно может отличаться от фактически занятого места, например у разреженных файлов. Прежде чем перемещать найденное, выясните, какой программе принадлежит файл и можно ли закрыть её штатно. Если путь содержит пробелы, при последующих ручных командах заключайте его в кавычки."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "journal",
          "text": "4. Проверяем системный журнал"
        },
        {
          "type": "paragraph",
          "text": "На системах с systemd отдельный источник роста — журнал событий. Для первого знакомства достаточно узнать его суммарный размер. Это не повод сразу чистить журнал: сохранённые сообщения могут объяснить саму причину заполнения диска, например повторяющуюся ошибку службы. Важнее заметить необычный рост и затем посмотреть, какая служба создаёт много записей."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Размер журнала systemd",
          "text": "journalctl --disk-usage"
        },
        {
          "type": "paragraph",
          "text": "Доступная часть журнала зависит от прав пользователя и настроек системы. Если команда показывает ограниченный набор записей, учитывайте это при сравнении с общей занятостью раздела. Настройку хранения и удаление старых записей лучше вынести в отдельную задачу: сначала убедитесь, что нужная история сохранена и что повторяющаяся ошибка действительно устранена."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "inodes",
          "text": "5. Не забываем про количество файлов"
        },
        {
          "type": "paragraph",
          "text": "Бывает, что байты ещё есть, а новый файл создать уже нельзя. В файловых системах с ограниченным числом inode причиной может стать огромное количество маленьких файлов. Inode хранит служебную информацию об объекте; его наличие нужно независимо от того, занимает файл несколько байтов или несколько гигабайт. Поэтому полезна отдельная проверка заполнения этой таблицы."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Использование inode",
          "text": "df -i -- \"$HOME\""
        },
        {
          "type": "paragraph",
          "text": "Если число доступных inode близко к нулю, ищите каталоги с множеством небольших объектов: кеш миниатюр, результаты автоматических задач или временные файлы приложения. Обычная сортировка по объёму в такой ситуации может не выделить виновника. Начинайте с области, в которой недавно изменилось поведение программы, и проверяйте гипотезу небольшими шагами."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "compare",
          "text": "6. Различаем показания df и du"
        },
        {
          "type": "paragraph",
          "text": "Эти инструменты отвечают на разные вопросы. df смотрит на состояние файловой системы, а du считает доступные ему объекты в дереве каталогов. Результаты не обязаны полностью совпадать. Разницу могут объяснять права доступа, точки монтирования, резерв файловой системы и удалённые файлы, которые процесс всё ещё держит открытыми."
        },
        {
          "type": "table",
          "headers": [
            "Проверка",
            "Что показывает",
            "Когда полезна"
          ],
          "rows": [
            [
              "df -h",
              "Общий объём и свободное место",
              "Понять, какой раздел заполнен"
            ],
            [
              "du -xh --max-depth=1",
              "Занятое место в каталогах",
              "Найти область с крупными данными"
            ],
            [
              "df -i",
              "Использование inode",
              "Разобраться с множеством мелких файлов"
            ],
            [
              "journalctl --disk-usage",
              "Размер доступных журналов",
              "Оценить вклад системных событий"
            ]
          ]
        },
        {
          "type": "details",
          "summary": "Почему удалённый файл может продолжать занимать место?",
          "text": "Если процесс держит файл открытым, удаление имени не всегда освобождает занятые блоки немедленно. Они освобождаются после закрытия последнего открытого дескриптора. Это повод выяснить, какой процесс работает с файлом, а не перезагружать весь компьютер без понимания причины."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "next-steps",
          "text": "7. Решаем, что делать дальше"
        },
        {
          "type": "paragraph",
          "text": "После измерений у вас должна появиться конкретная гипотеза, например: домашний каталог вырос из-за нескольких учебных образов или журнал заполняется повторяющимися сообщениями. Запишите текущие размеры и время проверки. Затем выберите одно действие, которое можно объяснить и при необходимости отменить. Измерьте результат теми же командами, чтобы сравнение было честным."
        },
        {
          "type": "list",
          "ordered": true,
          "items": [
            "Определить файловую систему и проверить запас места.",
            "Найти крупный каталог или источник большого числа файлов.",
            "Понять назначение данных и проверить, не используются ли они сейчас.",
            "Перед удалением важных файлов сохранить нужную копию на другом носителе.",
            "После осознанного изменения повторить измерения и записать результат."
          ]
        },
        {
          "type": "paragraph",
          "text": "Смысл этого маршрута — не освободить максимум места одной командой, а получить понятную картину. В следующий раз начать будет проще: у вас останутся исходные цифры, список обычных крупных каталогов и заметка о том, какая причина оказалась реальной. Для регулярной проверки достаточно нескольких таких ориентиров, без сложной системы наблюдения."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "references",
          "text": "8. Документация под рукой"
        },
        {
          "type": "paragraph",
          "text": "Справка установленной команды точнее описывает доступные именно в вашей системе ключи. Начать можно с man df, man du и man find, а для короткого напоминания использовать --help. Онлайн-документация ниже пригодится, когда хочется разобраться в различии между логическим размером файла и выделенными ему блоками."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "GNU Coreutils: df",
              "url": "https://www.gnu.org/software/coreutils/manual/html_node/df-invocation.html"
            },
            {
              "label": "GNU Coreutils: du",
              "url": "https://www.gnu.org/software/coreutils/manual/html_node/du-invocation.html"
            },
            {
              "label": "systemd: journalctl",
              "url": "https://www.freedesktop.org/software/systemd/man/latest/journalctl.html"
            }
          ]
        }
      ]
    },
    {
      "slug": "linux-journalctl",
      "title": "journalctl: посмотреть события без лишнего шума",
      "excerpt": "Три фильтра для системного журнала: текущая загрузка, период времени и конкретная служба.",
      "category": "linux",
      "tags": [
        "systemd",
        "Журнал"
      ],
      "date": "2026-10-25",
      "minutes": 4,
      "featured": false,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "В журнале системы много полезного, но читать его целиком неудобно. Начните с небольшого интервала и постепенно уточняйте запрос. Все примеры только показывают события и не меняют настройки хранения."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "current-boot",
          "text": "Только текущая загрузка"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "События после последнего запуска",
          "text": "journalctl -b --no-pager -n 40"
        },
        {
          "type": "paragraph",
          "text": "Параметр -b выбирает текущую загрузку, -n ограничивает количество последних записей, а --no-pager выводит результат прямо в терминал."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "time-range",
          "text": "Небольшой промежуток времени"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Последние полчаса",
          "text": "journalctl --since \"30 minutes ago\" --no-pager"
        },
        {
          "type": "heading",
          "level": 2,
          "id": "unit",
          "text": "Одна служба"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Журнал службы времени",
          "text": "journalctl -u systemd-timesyncd --since today --no-pager"
        },
        {
          "type": "details",
          "summary": "Почему часть записей недоступна?",
          "text": "Набор видимых событий зависит от прав пользователя и политики системы. Сообщение об ограниченном доступе — полезный контекст. Сначала уточните, какие журналы нужны для задачи, и только затем решайте вопрос доступа."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "Документация journalctl",
              "url": "https://www.freedesktop.org/software/systemd/man/latest/journalctl.html"
            }
          ]
        }
      ]
    },
    {
      "slug": "linux-file-permissions",
      "title": "Права файлов: как читать rwx и числа 644",
      "excerpt": "Короткое напоминание о правах владельца, группы и остальных пользователей.",
      "category": "linux",
      "tags": [
        "Файлы",
        "Права"
      ],
      "date": "2026-10-16",
      "minutes": 3,
      "featured": false,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "В строке ls -l права разбиты на три группы: владелец, группа и остальные. Для обычного файла r означает чтение, w — изменение, x — запуск. Для каталога x отвечает за проход к объектам внутри него."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Посмотреть права каталога",
          "text": "ls -ld -- \"$HOME\""
        },
        {
          "type": "table",
          "headers": [
            "Символ",
            "Число",
            "Значение для файла"
          ],
          "rows": [
            [
              "r",
              "4",
              "Чтение"
            ],
            [
              "w",
              "2",
              "Изменение"
            ],
            [
              "x",
              "1",
              "Выполнение"
            ],
            [
              "-",
              "0",
              "Право отсутствует"
            ]
          ]
        },
        {
          "type": "paragraph",
          "text": "Число 644 читается как 6 = 4 + 2 для владельца, 4 для группы и 4 для остальных. Это распространённый пример для обычного файла, который должен читаться другими пользователями. Он не подходит автоматически для любого документа."
        },
        {
          "type": "callout",
          "title": "Проверяем контекст",
          "text": "Права 777 редко помогают понять настоящую проблему. У файла и родительских каталогов могут быть разные ограничения, а дополнительные ACL могут менять итоговый доступ."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "GNU Coreutils: права доступа",
              "url": "https://www.gnu.org/software/coreutils/manual/html_node/File-permissions.html"
            }
          ]
        }
      ]
    },
    {
      "slug": "windows-network-check",
      "title": "Проверить сеть в Windows за пять минут",
      "excerpt": "Адрес, DNS и доступность HTTPS — последовательная проверка в PowerShell.",
      "category": "windows",
      "tags": [
        "PowerShell",
        "Сеть",
        "Диагностика"
      ],
      "date": "2026-10-27",
      "minutes": 5,
      "featured": true,
      "kind": "Инструкция",
      "blocks": [
        {
          "type": "paragraph",
          "text": "Если страница не открывается, полезно разделить проблему на несколько уровней. Сначала проверяем локальную конфигурацию, затем разрешение имени и только после этого соединение с нужным портом. Примеры используют общедоступный демонстрационный домен example.org."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "configuration",
          "text": "1. Посмотреть конфигурацию"
        },
        {
          "type": "code",
          "language": "powershell",
          "label": "Адреса и основной шлюз",
          "text": "Get-NetIPConfiguration"
        },
        {
          "type": "paragraph",
          "text": "Найдите активный сетевой адаптер. Если подключений несколько, учитывайте, какое из них используется сейчас: Wi-Fi, кабель или виртуальный интерфейс могут показывать разные параметры."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "dns",
          "text": "2. Проверить DNS"
        },
        {
          "type": "code",
          "language": "powershell",
          "label": "Получить IPv4-адрес домена",
          "text": "Resolve-DnsName example.org -Type A"
        },
        {
          "type": "paragraph",
          "text": "Наличие ответа означает, что имя удалось разрешить через текущий DNS-механизм. Оно ещё не доказывает доступность сайта: это отдельный этап проверки."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "https",
          "text": "3. Проверить порт HTTPS"
        },
        {
          "type": "code",
          "language": "powershell",
          "label": "TCP-соединение с портом 443",
          "text": "Test-NetConnection example.org -Port 443"
        },
        {
          "type": "paragraph",
          "text": "Значение TcpTestSucceeded показывает результат TCP-проверки. Успех не заменяет проверку сертификата и содержимого страницы в браузере, но помогает сузить область поиска."
        },
        {
          "type": "details",
          "summary": "Почему ping может не отвечать, а сайт открывается?",
          "text": "ICMP и HTTPS — разные виды трафика. Узел или промежуточное оборудование могут не отвечать на ping, продолжая принимать соединения на порт 443. Для проверки веб-сайта полезнее тест нужного TCP-порта."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "Microsoft Learn: Test-NetConnection",
              "url": "https://learn.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection"
            }
          ]
        }
      ]
    },
    {
      "slug": "wordpress-content-map",
      "title": "Рубрики и метки WordPress: разложить заметки по местам",
      "excerpt": "Простая схема для справочника: рубрика задаёт тему, а метки помогают связать детали.",
      "category": "wordpress",
      "tags": [
        "Контент",
        "Навигация"
      ],
      "date": "2026-10-21",
      "minutes": 4,
      "featured": false,
      "kind": "Заметка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "Справочник удобен, когда новая заметка получает понятное место, а старая находится несколькими путями. Рубрики и метки решают похожие, но разные задачи: первые задают основные разделы, вторые связывают конкретные инструменты и сценарии."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "categories",
          "text": "Небольшое число рубрик"
        },
        {
          "type": "paragraph",
          "text": "Для начала достаточно нескольких устойчивых тем. Читатель должен предсказать содержание раздела по его названию. Если две рубрики постоянно конкурируют за одну и ту же запись, полезно уточнить их границы или объединить."
        },
        {
          "type": "list",
          "ordered": false,
          "items": [
            "Linux — система и терминал.",
            "Сети — протоколы и диагностика соединений.",
            "Инструменты — утилиты и рабочие приёмы."
          ]
        },
        {
          "type": "heading",
          "level": 2,
          "id": "tags",
          "text": "Метки описывают детали"
        },
        {
          "type": "paragraph",
          "text": "В заметке про curl рубрикой могут быть «Инструменты», а метками — HTTP, терминал и диагностика. Не стоит создавать новый вариант написания одной метки для каждой записи: единообразные названия делают связанные материалы заметнее."
        },
        {
          "type": "table",
          "headers": [
            "Элемент",
            "На какой вопрос отвечает",
            "Пример"
          ],
          "rows": [
            [
              "Рубрика",
              "В каком разделе искать?",
              "Сети"
            ],
            [
              "Метка",
              "Какая тема встречается ещё?",
              "DNS"
            ],
            [
              "Заголовок",
              "Какую задачу решает запись?",
              "Проверить DNS-ответ домена"
            ]
          ]
        },
        {
          "type": "details",
          "summary": "Нужна ли отдельная рубрика для каждой программы?",
          "text": "Она полезна, когда материалов достаточно и читателю действительно нужен самостоятельный раздел. Для нескольких заметок часто хватает общей рубрики и метки с названием программы."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "WordPress: рубрики и метки",
              "url": "https://wordpress.org/documentation/article/posts-categories-screen/"
            }
          ]
        }
      ]
    },
    {
      "slug": "dns-basics",
      "title": "DNS без путаницы: A, AAAA и CNAME",
      "excerpt": "Что означают основные записи домена и как посмотреть ответ DNS из терминала.",
      "category": "networks",
      "tags": [
        "DNS",
        "Домены",
        "Терминал"
      ],
      "date": "2026-10-26",
      "minutes": 5,
      "featured": true,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "DNS помогает превратить знакомое доменное имя в данные, с которыми умеет работать сеть. Для обычного сайта чаще всего встречаются записи A, AAAA и CNAME. Ниже — небольшой словарь и команды чтения записей; они не меняют настройки домена."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "record-types",
          "text": "Три вида записей"
        },
        {
          "type": "table",
          "headers": [
            "Тип",
            "Что хранит",
            "Пример назначения"
          ],
          "rows": [
            [
              "A",
              "IPv4-адрес",
              "Указать адрес веб-сервера"
            ],
            [
              "AAAA",
              "IPv6-адрес",
              "Открывать сайт через IPv6"
            ],
            [
              "CNAME",
              "Другое доменное имя",
              "Создать псевдоним для поддомена"
            ]
          ]
        },
        {
          "type": "paragraph",
          "text": "CNAME указывает на имя, а не на URL: без https:// и без пути страницы. Наличие A не требует обязательной AAAA. Публиковать адрес IPv6 имеет смысл, когда сервер и весь путь до него действительно поддерживают такое соединение."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "query",
          "text": "Посмотреть ответ"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "IPv4-записи демонстрационного домена",
          "text": "dig example.org A +noall +answer"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "IPv6-записи",
          "text": "dig example.org AAAA +noall +answer"
        },
        {
          "type": "paragraph",
          "text": "Формат +noall +answer убирает большую часть служебного вывода. Если требуется понять причину отсутствия ответа, повторите запрос без этих параметров и посмотрите статус ответа и дополнительные секции."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "ttl",
          "text": "Зачем нужен TTL"
        },
        {
          "type": "paragraph",
          "text": "TTL задаёт время хранения ответа в кеше. После изменения записи разные пользователи некоторое время могут видеть разные данные: их резолверы получили прежний ответ в разное время. Уменьшение TTL после изменения не отменяет уже сохранённые ответы."
        },
        {
          "type": "details",
          "summary": "DNS отвечает правильно, но сайт не открывается. Почему?",
          "text": "Разрешение имени — только один этап. Затем нужны сетевое соединение, работающий веб-сервер, подходящая конфигурация домена и корректный сертификат для HTTPS. Проверяйте эти уровни по отдельности."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "IANA: типы DNS-записей",
              "url": "https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml"
            }
          ]
        }
      ]
    },
    {
      "slug": "http-status-codes",
      "title": "Пять HTTP-статусов, которые полезно узнавать с первого взгляда",
      "excerpt": "200, 301, 404, 403 и 500 — маленькая памятка для чтения ответа сервера.",
      "category": "networks",
      "tags": [
        "HTTP",
        "Веб"
      ],
      "date": "2026-10-18",
      "minutes": 3,
      "featured": false,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "HTTP-статус — короткий сигнал о результате запроса. Он помогает выбрать направление проверки, но сам по себе не объясняет всю причину. Для диагностики полезно посмотреть и заголовки ответа, и содержимое страницы."
        },
        {
          "type": "table",
          "headers": [
            "Статус",
            "Обычный смысл",
            "Что проверить"
          ],
          "rows": [
            [
              "200 OK",
              "Запрос выполнен",
              "Соответствует ли содержимое ожиданиям"
            ],
            [
              "301 Moved Permanently",
              "Постоянный новый адрес",
              "Заголовок Location и целевой URL"
            ],
            [
              "403 Forbidden",
              "Доступ запрещён",
              "Правила доступа и права"
            ],
            [
              "404 Not Found",
              "Ресурс не найден",
              "Путь, регистр и адрес ссылки"
            ],
            [
              "500 Internal Server Error",
              "Сбой обработки на сервере",
              "Журналы приложения и сервера"
            ]
          ]
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Посмотреть заголовки ответа",
          "text": "curl --head --max-time 15 https://example.org/"
        },
        {
          "type": "details",
          "summary": "Всегда ли 200 означает, что всё хорошо?",
          "text": "Страница может вернуть статус 200 и при этом содержать сообщение приложения об ошибке или неверный документ. Поэтому код статуса нужно сопоставлять с ожидаемым содержимым."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "IANA: реестр HTTP-статусов",
              "url": "https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml"
            }
          ]
        }
      ]
    },
    {
      "slug": "useful-curl",
      "title": "curl: проверить страницу и время ответа",
      "excerpt": "Полезные флаги для заголовков, перенаправлений и небольшого отчёта о запросе.",
      "category": "tools",
      "tags": [
        "curl",
        "HTTP",
        "Терминал"
      ],
      "date": "2026-10-24",
      "minutes": 5,
      "featured": true,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "curl удобен, когда нужно получить воспроизводимый ответ без браузера. Начните с понятной команды, ограничьте время ожидания и добавляйте параметры по мере необходимости. Все примеры обращаются к публичному демонстрационному домену."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "headers",
          "text": "Посмотреть заголовки"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Запрос HEAD",
          "text": "curl --head --max-time 15 https://example.org/"
        },
        {
          "type": "paragraph",
          "text": "Параметр --head выполняет запрос HEAD: сервер возвращает заголовки без тела страницы. Некоторые приложения обрабатывают HEAD иначе, чем GET, поэтому при странном результате полезно проверить обычный запрос."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "redirects",
          "text": "Проверить перенаправления"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Перейти по цепочке редиректов",
          "text": "curl --location --max-redirs 5 --head --max-time 15 https://example.org/"
        },
        {
          "type": "heading",
          "level": 2,
          "id": "timing",
          "text": "Измерить время запроса"
        },
        {
          "type": "paragraph",
          "text": "Следующая команда выполняет GET, не сохраняет страницу и печатает компактную сводку. Это намеренно длинный пример: его можно прокрутить внутри блока или скопировать целиком. Время включает конкретные условия одного запроса и не заменяет серию измерений."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Код ответа, адрес и длительность",
          "text": "curl --location --max-redirs 5 --connect-timeout 5 --max-time 20 --silent --show-error --output /dev/null --write-out 'HTTP: %{http_code} | IP: %{remote_ip} | DNS: %{time_namelookup}s | Соединение: %{time_connect}s | Первый байт: %{time_starttransfer}s | Всего: %{time_total}s\\n' https://example.org/"
        },
        {
          "type": "callout",
          "title": "Проверку сертификата оставляем включённой",
          "text": "В этих примерах нет --insecure. Ошибка доверия сертификату — часть результата проверки, которую полезно понять, а не скрыть."
        },
        {
          "type": "details",
          "summary": "Что означают --silent и --show-error вместе?",
          "text": "Первая опция скрывает индикатор прогресса, вторая возвращает сообщения об ошибках. Так обычный вывод остаётся коротким, а сетевой сбой всё ещё виден."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "curl: справочник параметров",
              "url": "https://curl.se/docs/manpage.html"
            }
          ]
        }
      ]
    },
    {
      "slug": "find-in-text",
      "title": "Найти строку в файлах с помощью grep",
      "excerpt": "Точный текст, номера строк и поиск без учёта регистра в нескольких понятных примерах.",
      "category": "tools",
      "tags": [
        "Текст",
        "Поиск",
        "Терминал"
      ],
      "date": "2026-10-13",
      "minutes": 3,
      "featured": false,
      "kind": "Шпаргалка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "Когда нужно найти буквальную строку, полезно сразу сказать об этом grep. Ключ -F отключает интерпретацию шаблона как регулярного выражения. Ниже используются вымышленные имена файлов: перед запуском подставьте путь к своему обычному текстовому документу."
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Точная строка и номера строк",
          "text": "grep -nF -- \"example.org\" notes.txt"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Без учёта регистра",
          "text": "grep -niF -- \"todo\" notes.txt"
        },
        {
          "type": "code",
          "language": "bash",
          "label": "Поиск в каталоге с заметками",
          "text": "grep -rnF --include=\"*.txt\" -- \"example.org\" ./notes"
        },
        {
          "type": "paragraph",
          "text": "Двойной дефис отделяет параметры от искомого текста. Это полезная привычка, когда строка может начинаться с дефиса. Для небольшой разовой проверки не требуется настраивать отдельную систему индексирования."
        },
        {
          "type": "links",
          "items": [
            {
              "label": "GNU grep: руководство",
              "url": "https://www.gnu.org/software/grep/manual/grep.html"
            }
          ]
        }
      ]
    },
    {
      "slug": "one-note-one-task",
      "title": "Одна заметка — одна решённая задача",
      "excerpt": "Маленький шаблон, который помогает превратить найденную команду в полезную шпаргалку.",
      "category": "notes",
      "tags": [
        "Заметки",
        "Порядок"
      ],
      "date": "2026-10-11",
      "minutes": 2,
      "featured": false,
      "kind": "Заметка",
      "blocks": [
        {
          "type": "paragraph",
          "text": "Хорошая заметка узнаётся по первому абзацу: понятно, для чего она нужна и когда её открыть. Не обязательно записывать всё, что встретилось во время работы. Иногда достаточно одного проверенного приёма и короткого объяснения условий."
        },
        {
          "type": "heading",
          "level": 2,
          "id": "template",
          "text": "Шаблон на четыре строки"
        },
        {
          "type": "list",
          "ordered": true,
          "items": [
            "Задача: что хотелось получить.",
            "Решение: команда или последовательность действий.",
            "Контекст: система, ограничения и важные условия.",
            "Проверка: по какому признаку понятно, что результат получен."
          ]
        },
        {
          "type": "details",
          "summary": "Что делать с устаревшей заметкой?",
          "text": "Добавить дату проверки и коротко описать, что изменилось. Если решение больше не работает, лучше отметить это прямо, чем оставлять уверенный заголовок без пояснения."
        },
        {
          "type": "paragraph",
          "text": "Начать можно с одной записи. Через некоторое время станет видно, какие рубрики и метки действительно помогают вам возвращаться к знаниям."
        }
      ]
    }
  ]
}
