{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "M9K blog: заметки с тегом linux",
    "_rss_description": "Заметки обо всём: devops, lifestyle, культура.",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/blog.m9k.space\/tags\/linux\/",
    "feed_url": "https:\/\/blog.m9k.space\/tags\/linux\/json\/",
    "icon": "https:\/\/blog.m9k.space\/pictures\/userpic\/userpic@2x.jpg?1769095194",
    "authors": [
        {
            "name": "M",
            "url": "https:\/\/blog.m9k.space\/",
            "avatar": "https:\/\/blog.m9k.space\/pictures\/userpic\/userpic@2x.jpg?1769095194"
        }
    ],
    "items": [
        {
            "id": "251",
            "url": "https:\/\/blog.m9k.space\/all\/monitoring-relizov-github\/",
            "title": "Мониторинг релизов GitHub",
            "content_html": "<p>Очередной небольшой эксперимент с вайбкодингом — Bash-скрипт для отслеживания новых релизов в GitHub-репозиториях.<\/p>\n<p>Раз в сутки проверяет заданный список проектов через GitHub API и отправляет уведомления в Telegram: версия, ссылка и краткий список изменений.<\/p>\n<p>Поддерживает SOCKS5-прокси, хранит историю обработанных релизов, умеет работать в режиме dry-run. Конфигурация — JSON и .env. Зависимости — Bash, curl и jq.<\/p>\n<p>Сейчас используется для мониторинга Lychee, Firefly III и Memos.<\/p>\n<p>Никаких постоянно работающих сервисов: обычный скрипт, запускаемый через cron.<\/p>\n<p><a href=\"https:\/\/egit.m9k.space\/m9k\/github-release-monitor\">Репа<\/a><\/p>\n",
            "summary": "Очередной небольшой эксперимент с вайбкодингом — Bash-скрипт для отслеживания новых релизов в GitHub-репозиториях...",
            "date_published": "2026-10-11T21:58:38+07:00",
            "date_modified": "2026-10-11T21:58:35+07:00",
            "tags": [
                "github",
                "linux",
                "opensource",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Sun, 11 Oct 2026 21:58:38 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "251",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "250",
            "url": "https:\/\/blog.m9k.space\/all\/migraciya-lychee-6-7-v-docker-lxc\/",
            "title": "Миграция Lychee 6 -> 7 в Docker (LXC)",
            "content_html": "<p>Развлекался намедни обновлением Lychee с миграцией с базового LXC-контейнера Debian 12 -> Debian 13<br \/>\nИсходно: <b>Lychee 6.10.3<\/b> в Debian 12 LXC. База — MariaDB 10.<br \/>\nДанные приложения находились в:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/lychee\/conf\n\/lychee\/uploads\n\/lychee\/sym\n\/lychee\/pictures\n\/lychee\/db<\/code><\/pre><p>Цель: обновить приложение и MariaDB  10->11<br \/>\nВ Lychee 7 изменилась структура каталогов внутри контейнера (см. <a href=\"https:\/\/lycheeorg.dev\/docs\/administration\/upgrade\/\">Update Guide<\/a>))<\/p>\n<p>Новая схема:<\/p>\n<pre class=\"e2-text-code\"><code class=\"yaml\">volumes:\n  - .\/lychee\/uploads:\/app\/public\/uploads\n  - .\/lychee\/logs:\/app\/storage\/logs\n  - .\/lychee\/tmp:\/app\/storage\/tmp\n  - .\/lychee\/storage\/app:\/app\/storage\/app<\/code><\/pre><p>База смонтирована в локальную директорию, но т. к. хочу поднять версию базы, делаем миграцию через дамп.<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">docker exec lychee_db \\\n  mysqldump \\\n  -u root \\\n  -p&#039;PASSWORD&#039; \\\n  --single-transaction \\\n  lychee &gt; \/lychee\/lychee.sql<\/code><\/pre><p>Переносим всё другой сервер, восстанавливаем.<\/p>\n<h2>APP_KEY<\/h2>\n<p>В Lychee 7 обязателен `APP_KEY`. Без него контейнер завершается с ошибкой:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ERROR: APP_KEY is not set<\/code><\/pre><p>Ключ можно сгенерировать:<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">echo &quot;base64:$(openssl rand -base64 32)&quot;<\/code><\/pre><p>и передать контейнеру:<\/p>\n<pre class=\"e2-text-code\"><code class=\"yaml\">environment:\n  APP_KEY: &quot;base64:...&quot;<\/code><\/pre><h2>Восстановление базы<\/h2>\n<pre class=\"e2-text-code\"><code class=\"bash\">docker compose up -d lychee_db<\/code><\/pre><p>Восстанавливаем дамм.<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">docker exec -i lychee_db \\\n  mariadb \\\n  -u root \\\n  -p&#039;PASSWORD&#039; \\\n  lychee &lt;lychee.sql<\/code><\/pre><p>В MariaDB 11 используется клиент `mariadb`, а не старое имя `mysql`.<\/p>\n<h2>Пересчёт статистики<\/h2>\n<p>После успешного запуска Lychee 7 стоит пересчитать размеры альбомов и thumbnails<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">docker exec -it lychee php artisan lychee:recompute-album-sizes<\/code><\/pre><p>и статистику альбомов:<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">docker exec -it lychee php artisan lychee:recompute-album-stats<\/code><\/pre><h2>Reverse proxy<\/h2>\n<p>После миграции при работе через Nginx возникала плавающая 502, причём выглядела она интересно — на одном и том же ПК веб-морда могла открывать в одном браузере, и не открывать в другом. В логах:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">upstream sent too big header while reading response header from upstream<\/code><\/pre><p>Проблема решилась увеличением proxy buffers:<\/p>\n<!-- Lychee Photo Album Embed v1.0.0 --><link rel=\"stylesheet\" href=\"https:\/\/lychee.m9k.space\/embed\/lychee-embed.css?v=1.0.0\">\n<script src=\"https:\/\/lychee.m9k.space\/embed\/lychee-embed.js?v=1.0.0\"><\/script>\n\n<div\n    data-lychee-embed\n    data-api-url=\"https:\/\/lychee.m9k.space\"\n    data-mode=\"album\"\n    data-album-id=\"Nym-osIiRs6lKn48wlXW9-zt\"\n    data-layout=\"square\"\n    data-spacing=\"8\"\n    data-target-row-height=\"200\"\n    data-target-column-width=\"200\"\n    data-max-photos=\"12\"\n    data-sort-order=\"asc\"\n    data-header-placement=\"none\"\n><\/div>",
            "summary": "Развлекался намедни обновлением Lychee с миграцией с базового LXC-контейнера Debian 12 -> Debian 13",
            "date_published": "2026-10-04T11:49:58+07:00",
            "date_modified": "2026-10-04T11:53:24+07:00",
            "tags": [
                "linux",
                "Lychee",
                "системное администрирование",
                "фотография"
            ],
            "_date_published_rfc2822": "Sun, 04 Oct 2026 11:49:58 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "250",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "244",
            "url": "https:\/\/blog.m9k.space\/all\/sozdanie-polzovateley-v-debian-i-astra-linux\/",
            "title": "Создание пользователей в Debian и Astra Linux",
            "content_html": "<p>Cкрипт для создания локальных пользователей с настройкой passwordless sudo.<br \/>\nОпределяет дистрибутив через \/etc\/os-release. Для Astra Linux дополнительно выполняет pdpl-user -l 0:63 -i 63.<br \/>\nПроверяет наличие утилит, не пересоздаёт существующих пользователей и не изменяет их пароли. Конфигурация sudo проверяется через visudo. Поддерживает повторный запуск.<br \/>\nЗапуск:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">.\/create-users.sh user1 user2 user3<\/code><\/pre><p><a href=\"https:\/\/egit.m9k.space\/m9k\/blog_data\/src\/branch\/main\/scripts\/Base\/debian-astra-create-passwordless-user.sh\">скрипт<\/a><\/p>\n",
            "summary": "Cкрипт для создания локальных пользователей с настройкой passwordless sudo",
            "date_published": "2026-09-23T09:51:16+07:00",
            "date_modified": "2026-09-27T21:33:31+07:00",
            "tags": [
                "Astra",
                "debian",
                "linux",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Wed, 23 Sep 2026 09:51:16 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "244",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "239",
            "url": "https:\/\/blog.m9k.space\/all\/proxmox-7-vklyuchenie-docker-i-podman-v-lxc\/",
            "title": "Proxmox 7: включение Docker и Podman в LXC",
            "content_html": "<p>Для запуска Docker или Podman внутри LXC-контейнера необходимо активировать дополнительные возможности: nesting, keyctl и fuse.<\/p>\n<p>Скрипт запрашивает ID контейнера, проверяет наличие конфигурации, создаёт резервную копию с меткой времени и включает необходимые параметры. Остальные настройки features сохраняются.<\/p>\n<p>Запускать от root на хосте Proxmox.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">#!\/bin\/bash\n\nread -rp &quot;Введите ID контейнера (CTID): &quot; CTID\n\nif [[ ! &quot;$CTID&quot; =~ ^[0-9]+$ || ! -f &quot;\/etc\/pve\/lxc\/${CTID}.conf&quot; ]]; then\n    echo &quot;Ошибка: некорректный CTID или конфигурация не найдена&quot;\n    exit 1\nfi\n\nCONF=&quot;\/etc\/pve\/lxc\/${CTID}.conf&quot;\nBACKUP_DIR=&quot;\/root\/lxc-config-backups&quot;\n\nmkdir -p &quot;$BACKUP_DIR&quot; &amp;&amp;\ncp &quot;$CONF&quot; &quot;$BACKUP_DIR\/${CTID}.conf.$(date +%Y%m%d_%H%M%S).bak&quot; &amp;&amp;\npct set &quot;$CTID&quot; --features &quot;$(awk -F, &#039;\/^features:\/{sub(\/^features:[[:space:]]*\/, &quot;&quot;); for(i=1;i&lt;=NF;i++) if($i !~ \/^(nesting|keyctl|fuse)=\/) printf &quot;%s,&quot;, $i} END{print &quot;nesting=1,keyctl=1,fuse=1&quot;}&#039; &quot;$CONF&quot;)&quot; &amp;&amp;\npct config &quot;$CTID&quot; | grep &#039;^features:&#039;<\/code><\/pre><p>Пример выполнения:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Введите ID контейнера (CTID): 177\nfeatures: fuse=1,keyctl=1,nesting=1<\/code><\/pre><p>Резервная копия конфигурации сохраняется в \/root\/lxc-config-backups\/.<\/p>\n<p>После изменения параметров необходимо полностью остановить и запустить контейнер:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">pct stop 177 &amp;&amp; pct start 177<\/code><\/pre><p>Update:<br \/>\nЕщё одна ошибка:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Failed to open() \/dev\/net\/tun: No such file or directory\nFailed to set up tap device in namespace<\/code><\/pre><p>Чиним:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">#!\/bin\/bash\nset -euo pipefail\n\nCTID=178\nCONF=&quot;\/etc\/pve\/lxc\/${CTID}.conf&quot;\nBACKUP=&quot;${CONF}.$(date +%Y%m%d%H%M%S).bkp&quot;\n\nmodprobe tun\ntest -c \/dev\/net\/tun\n\ncp -a &quot;$CONF&quot; &quot;$BACKUP&quot;\n\nRULES=(\n    &quot;lxc.cgroup2.devices.allow: c 10:200 rwm&quot;\n    &quot;lxc.mount.entry: \/dev\/net\/tun dev\/net\/tun none bind,create=file&quot;\n)\n\nfor rule in &quot;${RULES[@]}&quot;; do\n    grep -Fqx -- &quot;$rule&quot; &quot;$CONF&quot; || printf &#039;%s\\n&#039; &quot;$rule&quot; &gt;&gt; &quot;$CONF&quot;\ndone\n\necho &quot;Backup: $BACKUP&quot;\necho &quot;Configuration:&quot;\ngrep -E &#039;^lxc\\.(cgroup2\\.devices\\.allow|mount\\.entry):&#039; &quot;$CONF&quot;<\/code><\/pre>",
            "summary": "Для запуска Docker или Podman внутри LXC-контейнера необходимо активировать дополнительные возможности",
            "date_published": "2026-09-19T10:20:57+07:00",
            "date_modified": "2026-09-19T21:20:16+07:00",
            "tags": [
                "docker",
                "linux",
                "lxc",
                "podman",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Sat, 19 Sep 2026 10:20:57 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "239",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "236",
            "url": "https:\/\/blog.m9k.space\/all\/prinuditelny-full-gc-java-processov-po-cron\/",
            "title": "Принудительный Full GC Java-процессов по cron",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">0 3 * * * for pid in $(pgrep -u spring -x java); do java_bin=$(readlink -f &quot;\/proc\/$pid\/exe&quot;) &amp;&amp; jcmd=&quot;$(dirname &quot;$java_bin&quot;)\/jcmd&quot; &amp;&amp; [ -x &quot;$jcmd&quot; ] &amp;&amp; &quot;$jcmd&quot; &quot;$pid&quot; GC.run; done &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre><p>Суть:<\/p>\n<p>pgrep -u spring -x java находит все процессы с именем java, принадлежащие пользователю spring.<\/p>\n<p>Для каждого PID через \/proc\/$pid\/exe определяется реальный исполняемый файл Java.<\/p>\n<p>Рядом с найденным java ищется соответствующий jcmd:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">jcmd=&quot;$(dirname &quot;$java_bin&quot;)\/jcmd&quot;<\/code><\/pre><p>Если jcmd существует и исполняемый, выполняется:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">jcmd PID GC.run<\/code><\/pre><p>Команда инициирует Full GC внутри соответствующей JVM.<\/p>\n<p>jcmd должен иметь возможность подключиться к JVM. Сron следует запускать от пользователя spring или от root. Если jcmd отсутствует рядом с используемым java, эта JVM будет молча пропущена.<\/p>\n",
            "summary": "Суть",
            "date_published": "2026-09-17T16:57:50+07:00",
            "date_modified": "2026-09-17T16:57:47+07:00",
            "tags": [
                "Java",
                "jcmd",
                "linux",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 17 Sep 2026 16:57:50 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "236",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "235",
            "url": "https:\/\/blog.m9k.space\/all\/default-nano-as-crontab-editor\/",
            "title": "Default Nano as crontab editor",
            "content_html": "<p>Чтобы `crontab -e` открывался в `nano`, добавить в профиль пользователя:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">printf &#039;\\nexport EDITOR=nano\\nexport VISUAL=nano\\n&#039; &gt;&gt; ~\/.profile &amp;&amp; . ~\/.profile<\/code><\/pre>",
            "summary": "Чтобы `crontab -e` открывался в `nano`, добавить в профиль пользователя",
            "date_published": "2026-09-17T12:13:26+07:00",
            "date_modified": "2026-09-17T12:13:37+07:00",
            "tags": [
                "crontab",
                "linux",
                "nano"
            ],
            "_date_published_rfc2822": "Thu, 17 Sep 2026 12:13:26 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "235",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "228",
            "url": "https:\/\/blog.m9k.space\/all\/kak-vremenno-rasshirit-zfs-pul-s-pomoschyu-zvol-iz-drugogo-pula\/",
            "title": "Как временно расширить ZFS-пул с помощью zvol из другого пула",
            "content_html": "<p>Иногда ZFS-пул оказывается заполнен почти полностью, но переносить данные на другой файловый раздел неудобно или слишком долго.<\/p>\n<p>Было два независимых пула:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool list\n\nNAME    SIZE  ALLOC   FREE  FRAG  CAP  HEALTH\ndb     11.7T  8.99T  2.71T   18%  76%  ONLINE\nlimon  79.5G  77.0G  2.46G   90%  96%  ONLINE<\/code><\/pre><p>Пул limon закончился, а в пуле db оставалось несколько терабайт свободного пространства.<\/p>\n<p>Требовалось временно дать пулу limon около 10 ГБ, очистить логи и затем вернуть конфигурацию в исходное состояние.<\/p>\n<h3>Почему нельзя просто передать свободное место?<\/h3>\n<p>Свободное пространство принадлежит конкретному ZFS-пулу. Датасет одного пула не может непосредственно использовать место из другого пула.<\/p>\n<h3>Топология исходного пула<\/h3>\n<p>Пул limon состоял из одного раздела:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool status limon\n\npool: limon\nstate: ONLINE\nconfig:\n\n    NAME        STATE     READ WRITE CKSUM\n    limon       ONLINE       0     0     0\n      sdd1      ONLINE       0     0     0<\/code><\/pre><p>Для последующего удаления временного vdev необходимо проверить поддержку функции device_removal:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool get feature@device_removal limon<\/code><\/pre><p>В моём случае функция была включена:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">NAME   PROPERTY                VALUE    SOURCE\nlimon  feature@device_removal  enabled  local<\/code><\/pre><p>Также необходимо определить фактическое значение ashift существующего vdev.<\/p>\n<p>Команда:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool get ashift limon<\/code><\/pre><p>может показать:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">limon  ashift  0  default<\/code><\/pre><p>Значение 0 означает автоматический выбор для новых устройств и не показывает фактический ashift уже существующего vdev.<\/p>\n<p>Реальное значение можно получить через zdb:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zdb -C limon | grep -E &#039;path|ashift&#039;<\/code><\/pre><p>Результат:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">path: &#039;\/dev\/sdd1&#039;\nphys_path: &#039;acpi-VMBUS:01-vmbus-3d4511ba2bac43a19298b9d3bddf7b27-lun-2&#039;\nashift: 12<\/code><\/pre><p>Таким образом, временный vdev тоже нужно добавлять с ashift=12.<\/p>\n<h3>Важное предупреждение<\/h3>\n<p>Описанный способ создаёт зависимость одного ZFS-пула от другого.<\/p>\n<p>Пока временный zvol входит в пул limon:<\/p>\n<ul>\n<li>пул db нельзя экспортировать;<\/li>\n<li>zvol нельзя удалить;<\/li>\n<li>сервер нельзя загружать без доступного пула db;<\/li>\n<li>потеря пула db может привести к потере всего пула limon<br \/>\nЭто аварийная временная мера, а не постоянная архитектура хранения.<\/li>\n<\/ul>\n<h3>Создание временного zvol<\/h3>\n<p>Чтобы не повторять изменяемые значения в командах, зададим переменные:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">POOL_SOURCE=&quot;db&quot;\nPOOL_TARGET=&quot;limon&quot;\nZVOL_NAME=&quot;limon-temp-vdev&quot;\nZVOL_SIZE=&quot;10G&quot;\nZVOL_DATASET=&quot;${POOL_SOURCE}\/${ZVOL_NAME}&quot;\nZVOL_DEVICE=&quot;\/dev\/zvol\/${ZVOL_DATASET}&quot;\nASHIFT=&quot;12&quot;\nVOLBLOCKSIZE=&quot;16K&quot;<\/code><\/pre><p>Создаём обычный, неразреженный zvol:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zfs create -V &quot;${ZVOL_SIZE}&quot; -b &quot;${VOLBLOCKSIZE}&quot; -o compression=off &quot;${ZVOL_DATASET}&quot;<\/code><\/pre><p>Проверяем созданный zvol:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zfs get volsize,volblocksize,refreservation,compression &quot;${ZVOL_DATASET}&quot;<\/code><\/pre><p>Проверяем наличие блочного устройства:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">udevadm settle\nls -l &quot;${ZVOL_DEVICE}&quot;\nblockdev --getsize64 &quot;${ZVOL_DEVICE}&quot;<\/code><\/pre><p>У обычного zvol параметр refreservation должен быть примерно равен его размеру. Это гарантирует, что необходимые 10 ГБ действительно зарезервированы в пуле db.<\/p>\n<h3>Проверка добавления без изменения пула<\/h3>\n<p>Сначала выполняем пробный запуск:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool add -n -o ashift=&quot;${ASHIFT}&quot; &quot;${POOL_TARGET}&quot; &quot;${ZVOL_DEVICE}&quot;<\/code><\/pre><p>В предполагаемой конфигурации исходный диск и временный zvol должны находиться на одном уровне:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">limon\nsdd1\n\/dev\/zvol\/db\/limon-temp-vdev<\/code><\/pre><h3>Добавление временного пространства<\/h3>\n<p>Если пробная проверка не показывает ошибок, добавляем zvol:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool add -o ashift=&quot;${ASHIFT}&quot; &quot;${POOL_TARGET}&quot; &quot;${ZVOL_DEVICE}&quot;<\/code><\/pre><p>После этого проверяем состояние:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool status -P &quot;${POOL_TARGET}&quot;\nzpool list &quot;${POOL_TARGET}&quot;\nzfs list &quot;${POOL_TARGET}&quot;<\/code><\/pre><p>Дополнительно проверяем ashift обоих vdev:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zdb -C &quot;${POOL_TARGET}&quot; | grep -E &#039;path|ashift&#039;<\/code><\/pre><p>Оба top-level vdev должны иметь ashift=12. Разный ashift может помешать последующему удалению временного устройства.<\/p>\n<p>После добавления zvol пул limon получит немного меньше 10 ГБ полезного пространства из-за внутренних накладных расходов ZFS.<\/p>\n<h3>Удаление временного vdev<\/h3>\n<p>Сначала проверяем возможность удаления:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool remove -n &quot;${POOL_TARGET}&quot; &quot;${ZVOL_DEVICE}&quot;<\/code><\/pre><p>Параметр -n не выполняет полноценную симуляцию переноса данных. Он используется для оценки параметров операции, включая необходимый объём памяти для таблиц перенаправления.<\/p>\n<p>Если ошибок нет, запускаем удаление с ожиданием завершения:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool remove -w &quot;${POOL_TARGET}&quot; &quot;${ZVOL_DEVICE}&quot;<\/code><\/pre><p>Во время удаления ZFS переносит блоки с временного zvol обратно на исходный диск sdd1.<\/p>\n<p>За процессом можно наблюдать в другом терминале:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">watch -n 5 &quot;zpool status ${POOL_TARGET}; zpool list ${POOL_TARGET}&quot;<\/code><\/pre><p>До полного завершения операции нельзя:<\/p>\n<ul>\n<li>уничтожать zvol;<\/li>\n<li>экспортировать пул db;<\/li>\n<li>отключать устройство;<\/li>\n<li>перезагружать систему без необходимости.<\/li>\n<\/ul>\n<p>После успешного удаления проверяем, что в пуле остался только исходный vdev:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool status -P &quot;${POOL_TARGET}&quot;<\/code><\/pre><p>В конфигурации должен снова отображаться только sdd1.<\/p>\n<h3>Удаление временного zvol<\/h3>\n<p>Только после успешного завершения zpool remove можно уничтожить zvol:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zfs destroy &quot;${ZVOL_DATASET}&quot;<\/code><\/pre><p>Финальная проверка:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">zpool status &quot;${POOL_TARGET}&quot;\nzpool list &quot;${POOL_TARGET}&quot;\nzfs list &quot;${POOL_SOURCE}&quot; &quot;${POOL_TARGET}&quot;<\/code><\/pre>",
            "summary": "Иногда ZFS-пул оказывается заполнен почти полностью, но переносить данные на другой файловый раздел неудобно или слишком долго",
            "date_published": "2026-07-21T16:36:32+07:00",
            "date_modified": "2026-09-18T23:28:31+07:00",
            "tags": [
                "linux",
                "ZFS",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Tue, 21 Jul 2026 16:36:32 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "228",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "227",
            "url": "https:\/\/blog.m9k.space\/all\/v-terminale-linux-propal-tekst-vernite-echo\/",
            "title": "Проблемы с отображение текста в консоли",
            "content_html": "<p>Если терминал выполняет команды, но не отображает вводимый текст, восстановите отображение:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">stty echo<\/code><\/pre><p>Причина — отключённый режим echo, например после некорректного завершения программы, скрывавшей ввод пароля.<\/p>\n<p>Если проблема сохраняется, сбросьте настройки терминала:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">stty sane<\/code><\/pre>",
            "summary": "Если терминал выполняет команды, но не отображает вводимый текст, восстановите отображение",
            "date_published": "2026-07-21T15:40:59+07:00",
            "date_modified": "2026-09-19T10:03:48+07:00",
            "tags": [
                "linux",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Tue, 21 Jul 2026 15:40:59 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "227",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "220",
            "url": "https:\/\/blog.m9k.space\/all\/id-docker-konteynerov-maksimalnyh-potrebiteley-swap-v-linux\/",
            "title": "ID Docker контейнеров — максимальных потребителей SWAP в Linux",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">for pid in $(ls \/proc | grep -E &#039;^[0-9]+$&#039;); do     swap=$(grep VmSwap \/proc\/$pid\/status 2&gt;\/dev\/null | awk &#039;{print $2}&#039;);          if [[ -n &quot;$swap&quot; &amp;&amp; &quot;$swap&quot; -gt 0 ]]; then         cmd=$(tr &#039;\\0&#039; &#039; &#039; &lt; \/proc\/$pid\/cmdline);          cgroup=$(cat \/proc\/$pid\/cgroup 2&gt;\/dev\/null);\n        container_id=$(echo &quot;$cgroup&quot; | grep -Eo &#039;[a-f0-9]{64}&#039; | head -n1);\n        if [[ -z &quot;$container_id&quot; ]]; then             container_id=$(echo &quot;$cgroup&quot; | grep -Eo &#039;docker-[a-f0-9]+&#039; | sed &#039;s\/docker-\/\/&#039; | head -n1);         fi;          echo -e &quot;$swap KB\\tPID: $pid\\tCID: ${container_id:-host}\\tCMD: $cmd&quot;;     fi; done | sort -nr | head<\/code><\/pre>",
            "summary": "",
            "date_published": "2026-04-27T09:48:52+07:00",
            "date_modified": "2026-04-27T09:48:51+07:00",
            "tags": [
                "docker",
                "linux",
                "swap",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Mon, 27 Apr 2026 09:48:52 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "220",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "202",
            "url": "https:\/\/blog.m9k.space\/all\/linux-passwordless-oneliner\/",
            "title": "Linux Passwordless oneliner",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">TARGET=user@host; PORT=22; [[ -r ~\/.ssh\/id_ed25519.pub ]] || ssh-keygen -t ed25519 -N &quot;&quot; -f ~\/.ssh\/id_ed25519; ssh -p &quot;$PORT&quot; &quot;$TARGET&quot; &#039;umask 077; mkdir -p ~\/.ssh &amp;&amp; cat &gt; ~\/.ssh\/authorized_keys&#039; &lt; ~\/.ssh\/id_ed25519.pub &amp;&amp; ssh -p &quot;$PORT&quot; &quot;$TARGET&quot; &#039;echo &quot;&gt;&gt;&gt; Root доступ подтверждён&quot;&#039;<\/code><\/pre>",
            "summary": "",
            "date_published": "2025-08-25T17:44:17+07:00",
            "date_modified": "2025-08-25T17:44:14+07:00",
            "tags": [
                "linux",
                "passwordless",
                "ssh",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Mon, 25 Aug 2025 17:44:17 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "202",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "201",
            "url": "https:\/\/blog.m9k.space\/all\/skreschivaem-uzha-i-ezha\/",
            "title": "CouchDB, Debian, AstraLinux, Docker и все-все-все",
            "content_html": "<p>Возникла необходимость запустить Couchdb в контейнере, где базовая ось (и базовые же пакеты) должны быть очень-очень свежими, в противной случай контейнер не проходит встроенную проверку на безопасность.<br \/>\nСтандартный официальный образ собран на базе Debian 12.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">FROM debian:bookworm-slim<\/code><\/pre><p>Простая замена базового образа на<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">FROM debian:trixie-slim<\/code><\/pre><p>приводит к тому, что контейнер не собирается по зависимостям.<br \/>\nСмотрим официальную репу в части зависимостей и видим прекрасное — libmozjs-78-0 (>= 78.15.0). Пробуем ставить свежую версию, которая есть в репах — не помогает, пакет couchdb принципиально требует libmozjs-78-0.<\/p>\n<p>Ок, скрещиваем ежа и ужа.<\/p>\n<p>У debian есть механизм apt-pinning. Это механизм, позволяющий задать приоритеты для версий пакетов из разных источников (репозиториев, release-веток, PPA), чтобы фиксировать версию, запрещать обновление или предпочитать конкретный источник.<\/p>\n<p>Коротко приоритеты делятся на:<\/p>\n<ul>\n<li>< 0 — никогда не устанавливать.<\/li>\n<li>1..99 — ставить только при явном указании версии.<\/li>\n<li>100 — приоритет уже установленной версии.<\/li>\n<li>500 — дефолт для неприоритетных источников.<\/li>\n<li>990 — приоритет для целевого релиза (-t), либо если явно указан release.<\/li>\n<li>>1000 — разрешает понижение версии (downgrade) к закреплённой.<\/li>\n<\/ul>\n<p>Добавляет в наш Dockerfile:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">RUN echo &quot;deb http:\/\/deb.debian.org\/debian bookworm main&quot; &gt; \/etc\/apt\/sources.list.d\/bookworm.list &amp;&amp; \\\n    echo &quot;Package: *\\nPin: release n=bookworm\\nPin-Priority: 500&quot; &gt; \/etc\/apt\/preferences.d\/bookworm &amp;&amp; \\\n    echo &quot;Package: *\\nPin: release n=trixie\\nPin-Priority: 600&quot; &gt; \/etc\/apt\/preferences.d\/trixie &amp;&amp; \\\n    echo &quot;deb [signed-by=\/usr\/share\/keyrings\/couchdb-archive-keyring.gpg] https:\/\/apache.jfrog.io\/artifactory\/couchdb-deb\/ bookworm main&quot; \\\n            &gt; \/etc\/apt\/sources.list.d\/couchdb.list &amp;&amp; \\\n    apt-get update<\/code><\/pre><p>Основная часть пакетов ставится из свежей репы, часть, которых в ней нет — из старых.<\/p>\n",
            "summary": "Возникла необходимость запустить Couchdb в контейнере, где базовая ось (и базовые же пакеты) должны быть очень-очень свежими, в противной случай контейнер не проходит встроенную проверку на безопасность",
            "date_published": "2025-08-14T17:40:09+07:00",
            "date_modified": "2025-08-14T17:40:08+07:00",
            "tags": [
                "apt-pinning",
                "astralinux",
                "couchdb",
                "debian",
                "docker",
                "linux",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 14 Aug 2025 17:40:09 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "201",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "200",
            "url": "https:\/\/blog.m9k.space\/all\/curl-over-ssh-tunnel\/",
            "title": "Curl over ssh-tls-tunnel",
            "content_html": "<p>Есть ресурс resource.name, на который нужно ходить curl-ом с засылкой данных через JSON. Специфика ресурса такова, что он принимает соединения через TLS 1.3.<br \/>\nЕсть сервер A server.name, на котором нет выхода на нужный ресурс, но есть Nginx, и есть ssh-доступ до сервера B<br \/>\nЕсть сервер B, на котором есть выход на нужный ресурс, но сам сервер очень старый, и TLS на нём не проходит по требования resource.name.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">printf &#039;&#039; | openssl s_client -connect 127.0.0.1:8443 -servername resource.name -tls1_3 -brief<\/code><\/pre><p>Костылим:<br \/>\nНа сервере A поднимаем туннель на внутренний порт:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ssh -fN -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -L 8443:resource.name:443 user@serverB<\/code><\/pre><p>На Nginx рисуем конфиг:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">server {\n        listen 9090;\n        server_name         server.name;\n\n        access_log  \/site\/logs\/nginx\/port_9090.log  main;\n        error_log   \/site\/logs\/nginx\/port_9090.error.log;\n\nlocation \/ {\n        proxy_pass https:\/\/127.0.0.1:8443;\n\n        proxy_set_header Host resource.name;\n        proxy_ssl_server_name on;\n        proxy_ssl_name resource.name;\n        proxy_ssl_protocols TLSv1.3;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto https;\n        proxy_connect_timeout 10s;\n        proxy_read_timeout 60s;\n        proxy_ssl_verify off;\n}\n}<\/code><\/pre><p>Кидаемся тестовым запросом:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">curl -v -X POST &#039;http:\/\/server.name:9090\/resource&#039; -H &#039;Content-Type: application\/json&#039; --data &#039;{&quot;login&quot;:&quot;$LOGIN&quot;,&quot;password&quot;:&quot;$PASSWORD&quot;}&#039;<\/code><\/pre>",
            "summary": "Есть ресурс resource.name, на который нужно ходить curl-ом с засылкой данных через JSON. Специфика ресурса такова, что он принимает соединения через TLS 1",
            "date_published": "2025-08-14T17:21:23+07:00",
            "date_modified": "2025-08-14T17:43:11+07:00",
            "tags": [
                "curl",
                "curl-over-ssh",
                "linux",
                "ssh",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 14 Aug 2025 17:21:23 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "200",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "199",
            "url": "https:\/\/blog.m9k.space\/all\/unzip-bez-unzip\/",
            "title": "Unzip без unzip",
            "content_html": "<p>Есть сервер без доступа в интернет, с древней ОС и мёртвыми репозиториями. Нужно распаковать ZIP-архив, но unzip отсутствует, а установить его неоткуда.<\/p>\n<p>Решаем вопрос штатным модулем Python zipfile, без дополнительных зависимостей.<\/p>\n<p>Python 2.7:<\/p>\n<pre class=\"e2-text-code\"><code class=\"python\">python - &lt;&lt;&#039;EOF&#039;\nimport zipfile\nimport os\n\narchive = &#039;archive.zip&#039;\ntarget_dir = &#039;archive&#039;\n\nif not os.path.exists(target_dir):\nos.makedirs(target_dir)\n\nwith zipfile.ZipFile(archive, &#039;r&#039;) as z:\nfor name in z.namelist():\nz.extract(name, target_dir)\nEOF<\/code><\/pre><p>Python 3:<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">python3 -m zipfile -e archive.zip archive<\/code><\/pre><p>Для Python 3 достаточно встроенного интерфейса командной строки модуля zipfile. Никаких дополнительных пакетов.<\/p>\n<p>В обоих случаях архив распаковывается в каталог archive. Для Python 3 каталог назначения должен существовать заранее, поэтому при необходимости сначала выполните mkdir -p archive.<\/p>\n",
            "summary": "Есть сервер без доступа в интернет, с древней ОС и мёртвыми репозиториями. Нужно распаковать ZIP-архив, но unzip отсутствует, а установить его неоткуда...",
            "date_published": "2025-08-14T17:07:44+07:00",
            "date_modified": "2026-10-11T23:56:46+07:00",
            "tags": [
                "linux",
                "python",
                "zip",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 14 Aug 2025 17:07:44 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "199",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "184",
            "url": "https:\/\/blog.m9k.space\/all\/perechityvanie-topologii-diska-v-vm-posle-rasshireniya-ego-v-gip\/",
            "title": "Перечитывание топологии диска в ВМ после расширения его в гипервизоре",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">echo 1 &gt; \/sys\/class\/scsi_device\/0:0:0:0\/device\/rescan<\/code><\/pre>",
            "summary": "",
            "date_published": "2025-04-08T15:04:53+07:00",
            "date_modified": "2025-04-08T15:04:49+07:00",
            "tags": [
                "linux",
                "диски",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Tue, 08 Apr 2025 15:04:53 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "184",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "181",
            "url": "https:\/\/blog.m9k.space\/all\/zfs-na-oracle-linux-8-10\/",
            "title": "ZFS на Oracle Linux 8.10",
            "content_html": "<p>При установке ZFS на Oracle Linux 8.10 по официальной <a href=\"https:\/\/openzfs.github.io\/openzfs-docs\/Getting%20Started\/RHEL-based%20distro\/index.html\">доке<\/a> столкнулся с неочевидной ошибкой:<\/p>\n<blockquote>\n<p>checking for kernel config option compatibility... done<br \/>\nchecking whether CONFIG_MODULES is defined... no<br \/>\nconfigure: error:<br \/>\n\t\t*** This kernel does not include the required loadable module<br \/>\n\t\t*** support!<br \/>\n\t\t***<br \/>\n\t\t*** To build OpenZFS as a loadable Linux kernel module<br \/>\n\t\t*** enable loadable module support by setting<br \/>\n\t\t*** `CONFIG_MODULES=y` in the kernel configuration and run<br \/>\n\t\t*** `make modules_prepare` in the Linux source tree.<br \/>\n\t\t***<br \/>\n\t\t*** If you don’t intend to enable loadable kernel module<br \/>\n\t\t*** support, please compile OpenZFS as a Linux kernel built-in.<br \/>\n\t\t***<br \/>\n\t\t*** Prepare the Linux source tree by running `make prepare`,<br \/>\n\t\t*** use the OpenZFS `—enable-linux-builtin` configure option,<br \/>\n\t\t*** copy the OpenZFS sources into the Linux source tree using<br \/>\n\t\t*** `.\/copy-builtin <linux source directory>`,<br \/>\n\t\t*** set `CONFIG_ZFS=y` in the kernel configuration and compile<br \/>\n\t\t*** kernel as usual.<\/p>\n<\/blockquote>\n<p>Объяснение и решение проблемы нашёл <a href=\"https:\/\/run.tournament.org.il\/build-zfs-on-oel-with-uek7\/\">тут<\/a><\/p>\n<blockquote>\n<p>The root of the problem is with the GCC toolset used to build UEK7 kernel, which is different from the one used to build Redhat compatible version. RH kernel is built (using the default) GCC.<\/p>\n<\/blockquote>\n<p>Решение:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">dnf install -y gcc-toolset-11-annobin-plugin-gcc\n. \/opt\/rh\/gcc-toolset-11\/enable\ndkms install zfs\/$VERSION<\/code><\/pre>",
            "summary": "При установке ZFS на Oracle Linux 8.10 по официальной доке столкнулся с неочевидной ошибкой",
            "date_published": "2025-03-06T17:29:29+07:00",
            "date_modified": "2025-03-06T17:29:48+07:00",
            "tags": [
                "GCC",
                "linux",
                "Oracle Linux 8.10",
                "UEK",
                "ZFS",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 06 Mar 2025 17:29:29 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "181",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "180",
            "url": "https:\/\/blog.m9k.space\/all\/python2-7-na-debian-12\/",
            "title": "Python 2.7 на Debian 12",
            "content_html": "<p>Потребовалось старым Ansible выполнить скрипты на свежайщем Debian 12. Столкнулся с тем, что в дистрибутиве окончательно выпилили поддержку Python 2.7. Пришлось сотворить Франкенштейна:<\/p>\n<ol start=\"1\">\n<li>Добавляем в \/etc\/apt\/sources.list:<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">deb http:\/\/archive.debian.org\/debian\/ stretch contrib main non-free<\/code><\/pre><ol start=\"2\">\n<li>Обновляемся<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">sudo apt-get update<\/code><\/pre><ol start=\"3\">\n<li>Делаем установку<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">sudo apt-get install python2.7<\/code><\/pre><ol start=\"4\">\n<li>Делаем симлинк на бинарь<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">cd \/usr\/bin &amp;&amp;  ln -s python2.7 python<\/code><\/pre><ol start=\"5\">\n<li>Удаляем добавленное в п.1 и повторно делаем пункт 2.<\/li>\n<\/ol>\n",
            "summary": "Потребовалось старым Ansible выполнить скрипты на свежайщем Debian 12. Столкнулся с тем, что в дистрибутиве окончательно выпилили поддержку Python 2",
            "date_published": "2025-03-06T17:22:59+07:00",
            "date_modified": "2025-03-06T17:22:58+07:00",
            "tags": [
                "Debian 12",
                "linux",
                "python 2.7",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Thu, 06 Mar 2025 17:22:59 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "180",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "179",
            "url": "https:\/\/blog.m9k.space\/all\/osnovnoy-potrebitel-swap-na-linux-serverah\/",
            "title": "Основной потребитель swap на Linux-серверах",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">for file in \/proc\/*\/status ; do awk &#039;\/VmSwap|Name\/{printf $2 &quot; &quot; $3}END{ print &quot;&quot;}&#039; $file; done | sort -k 2 -n -r | less<\/code><\/pre><p>Взято <a href=\"https:\/\/blog.programs74.ru\/linux-which-process-is-using-swap\/\">отсюда<\/a><\/p>\n",
            "summary": "Взято отсюда",
            "date_published": "2025-03-04T09:45:41+07:00",
            "date_modified": "2025-03-04T09:45:36+07:00",
            "tags": [
                "linux",
                "memory",
                "swap",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Tue, 04 Mar 2025 09:45:41 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "179",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "178",
            "url": "https:\/\/blog.m9k.space\/all\/sed-udalit-kommentarii-iz-xml\/",
            "title": "SED удалить комментарии из XML",
            "content_html": "<p>Возникла задача сравнить два XML-файла конфигурации Clickhouse для выяснения, что же в ней не так. Беда конфигурации в том, что она содержит прям какое-то совершенное безумное количество закомментированных параметров, и сравнение «в лоб» превращается в муку. Почистим файлы SED-ом:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">cat config.xml | sed &#039;\/&lt;!--.*--&gt;\/d&#039; | sed &#039;\/&lt;!--\/,\/--&gt;\/d&#039; | sed &#039;\/^[[:space:]]*$\/d&#039; &gt; config_without_comments.xml<\/code><\/pre>",
            "summary": "Возникла задача сравнить два XML-файла конфигурации Clickhouse для выяснения, что же в ней не так. Беда конфигурации в том, что она содержит прям какое-то совершенное безумное количество закомментированных...",
            "date_published": "2025-02-24T11:28:21+07:00",
            "date_modified": "2025-02-24T11:28:18+07:00",
            "tags": [
                "linux",
                "sed",
                "Unix",
                "xml",
                "системное администрирование"
            ],
            "_date_published_rfc2822": "Mon, 24 Feb 2025 11:28:21 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "178",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "174",
            "url": "https:\/\/blog.m9k.space\/all\/bombardier-2\/",
            "title": "Bombardier",
            "content_html": "<p>Максимальная простая и удобная тулза для тестирования нагрузки веб-приложений.<br \/>\n<a href=\"https:\/\/github.com\/codesenberg\/bombardier\">GitHub<\/a><br \/>\nПример:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">bombardier -c 125 -n 10000000 http:\/\/localhost:8080<\/code><\/pre>",
            "summary": "Максимальная простая и удобная тулза для тестирования нагрузки веб-приложений",
            "date_published": "2025-01-24T22:03:29+07:00",
            "date_modified": "2025-02-24T11:36:50+07:00",
            "tags": [
                "Bombardier",
                "linux",
                "tools",
                "администрирование",
                "системное администрирование",
                "утилиты"
            ],
            "_date_published_rfc2822": "Fri, 24 Jan 2025 22:03:29 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "174",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "163",
            "url": "https:\/\/blog.m9k.space\/all\/openssl-view-cert-info\/",
            "title": "OpenSSL view cert info",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">openssl x509 -noout -text -in &#039;cerfile.cer&#039;;<\/code><\/pre>",
            "summary": "",
            "date_published": "2024-07-15T10:31:18+07:00",
            "date_modified": "2024-07-15T10:31:15+07:00",
            "tags": [
                "linux",
                "openssl",
                "администрирование",
                "сертификаты"
            ],
            "_date_published_rfc2822": "Mon, 15 Jul 2024 10:31:18 +0700",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "163",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        }
    ],
    "_e2_version": 4199,
    "_e2_ua_string": "Aegea 11.5 (v4199)"
}