ServerAdmin.ru
26.6K subscribers
197 photos
24 videos
8 files
2.47K links
Авторская информация о системном администрировании.

Информация о рекламе: @srv_admin_reklama_bot
Автор: @zeroxzed

Второй канал: @srv_admin_live
Сайт: serveradmin.ru
Download Telegram
​​Решил проверить, на какой минимальной VPS можно поднять Linux с рабочим столом и браузером, чтобы можно было подключаться к нему и работать удалённо. Это актуально для тех, у кого есть потребность в рабочем месте, где гарантированно будет нигде не засвеченный ранее твой IP адрес. Если использовать VPN или прокси на основной машине, рано или поздно всё равно спалишь свой IP из-за каких-нибудь ошибок. И получишь блок акка.

Взял VPS 1CPU, 1Gb RAM, 10Gb SSD и у меня всё получилось. Использовал:

Debian 12 minimal в качестве системы
Lxde-core в качестве графического окружения
X2Go в качестве удалённого доступа к системе

Настройка максимально простая, осилит каждый. Устанавливаем lxde-core и x2go:

# apt install x2goserver x2goserver-xsession lxde-core

Уже можно подключаться, скачав клиент x2go под свою систему. В качестве аутентификации используется локальная учётка пользователя, не root, с правами подключения по ssh.

Далее можно установить любой браузер. Я вычитал, что Falkon наименее прожорливый и поставил его:

# apt install falkon

Понятное дело, что с такими ресурсами всё это работает не очень быстро, но пользоваться можно. Если пользоваться предполагается активно, то надо добавить ещё ядро CPU и еще гиг памяти. Тогда вообще нормально будет.

Я так понимаю, подобную связку lxde-core и falkon можно использовать на старом железе. Можно наверное ещё всё это как-то ужать, используя более специализированные системы и софт, но мне хотелось использовать именно базу, чтобы без заморочек взять и развернуть на стандартном ПО.

#linux
​​В ОС на базе ядра Linux реализован механизм изоляции системных вызовов под названием namespace. С его помощью каждое приложение может быть изолировано от других средствами самого ядра, без сторонних инструментов. Попробую простыми словами рассказать, что это такое.

Покажу сразу на простом примере. Запустим оболочку bash с отдельными namespace PID и mount. То есть мы получим изолированную среду на уровне процессов и точек монтирования. Новый процесс bash в этом namespace получит id 1.

# unshare --pid --fork --mount-proc --mount /bin/bash
# ps ax
  PID TTY   STAT  TIME COMMAND
   1 pts/0  S   0:00 /bin/bash
   45 pts/0  R+   0:00 ps ax

Теперь на условном примере покажу изоляцию mount. Здесь же в изолированных namespaces добавляем монтирование:

# mkdir /tmp/dir1 /mnt/dir1
# mount --bind /tmp/dir1 /mnt/dir1
# mount | grep dir1
/dev/sda2 on /mnt/dir1 type ext4 (rw,relatime,errors=remount-ro)

При этом на самом хосте вы этого mount не увидите. Если в изолированном namespace создать что-то в /tmp/dir1, оно появится в /mnt/dir1, а если на хосте зайти в /mnt/dir1 там будет пусто, потому что для хоста этого монтирования не существует.

Посмотреть существующие namespaces можно командой lsns:

# lsns

................................................
4026532129 mnt     2  853 root       unshare --pid --fork --mount-proc --mount /bin/bash
4026532130 pid     1  854 root       └─/bin/bash
.................................................

Там будет видно в том числе созданные нами namespaces для форка bash. Это будут mnt и pid. Если у вас на хосте запущены контейнеры, то здесь же их и увидите. Работа контейнеров основана на этом механизме ядра.

Из показанного примера видно, что использовать изоляцию можно и без контейнеров. Можно создавать юниты systemd с использованием namespaces. Базово в системе уже есть некоторые юниты, работающие в своём пространстве. Их видно по lsns.

С помощью утилиты nsenter можно запускать процессы в произвольных namespaces. Откроем отдельную консоль и запустим процесс в созданном ранее namespace с bash. Для этого с помощью lsns узнаём pid процесса в ns pid и подцепляем к нему, к примеру, команду sleep.

# lsns | grep /bin/bash
4026532129 mnt     2  853 root       unshare --pid --fork --mount-proc --mount /bin/bash
4026532130 pid     1  854 root       └─/bin/bash

# nsenter -t 854 -m -p sleep 60

Возвращаемся в консоль с unshare и смотрим список процессов:

# ps ax
  PID TTY   STAT  TIME COMMAND
   1 pts/0  S   0:00 /bin/bash
   50 pts/2  S+   0:00 sleep 60
   51 pts/0  R+   0:00 ps ax

Видим процесс со sleep. Базово всё это попробовать довольно просто, но на самом деле там очень много нюансов. Поэтому все и пользуются готовыми решениями на базе этой технологии, типа Docker.

Всего существует следующий набор namespaces:

- mount - изоляция на уровне монтирования файловых систем;
- UTS - изоляция hostname и domainname, т.е. в каждом ns может быть своё имя хоста;
- IPC - изоляция межпроцессорного взаимодействия (Inter-process communication);
- network - свои сетевые настройки для разных ns, включая ip адреса, маршруты, правила файрволов;
- PID - изоляция процессов;
- user - изоляция пользовательских UIDs и GIDs;
- cgroup - ограничивает потребляемый объём аппаратных ресурсов, cpu, ram, io и т.д.;
- time - изоляция некоторых параметров времени, а конкретно только MONOTONIC и BOOTTIME, установить разное текущее время в разных ns нельзя.

Все эти ns можно использовать с помощью утилит unshare и nsenter. Также существует отдельный продукт systemd-nspawn, один из компонентов systemd, который реализует возможности для создания легковесных контейнеров. Он как-то не особо распространён, не знаю почему. По идее, благодаря тесной интеграции с systemd это должно быть удобно, так как systemd сейчас везде.

#linux
▶️ Очередная подборка авторских IT роликов, которые я лично посмотрел и посчитал интересными/полезными. Как раз к выходным.

Прохождение #Linux-машины DRIVE.HTB, сложного уровня | #HackTheBox
Новое прохождение задания на Hackthebox по взлому операционной системы. Не буду подробно описывать видео. Оно по структуре и тематике такое же как прошлое, где я подробно разобрал, о чём там речь. Только тут задача посложнее и подольше. Смотреть интересно, но только если понимаешь, что там происходит. В целом, контент очень качественный, рекомендую.

Как в Synology просто и быстро развернуть несколько сайтов в пару кликов
Автор рассказывает, как в Synology настроить веб сервер и захостить там сайты. Когда-то давным-давно мой сайт некоторое время жил у меня в квартире на Synology. В целом, работал нормально, но мне быстро надоел постоянно работающий сервер. Убрал сайт на хостинг, а NAS стал периодически выключать.

Организация компьютерных сетей 
Терминология сетей
Андрей Созыкин начал работу над новой актуальной версией курса по компьютерным сетям. Первые уроки уже смонтированы, можно посмотреть.

Proxmox Установка и обзор функций WebUI
Простая установка и разбор возможностей веб интерфейса Proxmox. Конкретно в этом видео ничего особо нового и интересного нет. Автор обещает дальше настройку кластера, настройку бэкапов в PBS. Так что имеет смысл подписаться и следить, если интересна эта тема.

Monitor Storage S.M.A.R.T With ZABBIX - Tutorial
Инструкция от Dmitry Lambert о том, как мониторить показатели SMART с помощью Zabbix agent 2. В инструкции он показывает на примере системы Windows. То есть это решение в основном для мониторинга за рабочими станциями.

🔥Running Windows in a Docker Container!
История о том, как на Linux запустить любую версию Windows с помощью Docker контейнера и зайти в неё через браузер. Сначала подумал, что за магия? На самом деле никакой магии. Контейнер поднимает KVM, создаёт виртуалку и запускает. Весь процесс автоматизирован. По этой теме имеет смысл сделать отдельную публикацию с описанием. Очень интересное решение получилось. Я пока только посмотрел, сам не пробовал запускать.

Если посмотрите видео, то не забудьте зайти в комментарии и поблагодарить авторов. Вам это ничего не стоит, а им приятно.

#видео
​​В Linux относительно просто назначить выполнение того или иного процесса на заданном количестве ядер процессора. Для этого используется утилита taskset. Она может "сажать" на указанные ядра как запущенный процесс, так и запустить новый с заданными параметрами.

1️⃣ Покажу сразу на примерах. Допустим, у вас есть какой-то процесс, который по умолчанию может занимать ресурсы всех ядер процессора. Допустим, вы хотите разрешить ему работать только на первых двух. Для того, чтобы это сделать, нам необходимо узнать pid процесса:

# ps ax | grep mc
# ps -T -C mc | awk '{print $2}' | grep -E '[0-9]'
# pidof mc

Выбирайте любой способ, какой больше нравится. Смотрим, какие у нас процессоры и ядра в системе:

# lscpu | grep -i CPU\(s\)
# lscpu | grep -i numa
NUMA node(s):            1
NUMA node0 CPU(s):         0-3

Видим четыре CPU с 0 по 3. Посадим наш процесс на первые два ядра:

# taskset -pc 0-1 927
pid 927's current affinity list: 0-3
pid 927's new affinity list: 0,1

Где 927 - это pid процесса. Видим, что привязка изменилась с 0-3 на 0,1.

2️⃣ Менять привязку уже запущенных процессов мне кажется не таким полезным, как иметь возможность запустить процесс с заданными параметрами. Это более практичная возможность, для которой нетрудно придумать реальный пример.

Я активно использую архиватор pigz, который умеет жать всеми доступными ядрами. Ему можно задать ограничение на использование ядер, но он будет случайным образом занимать ядра и почти всегда нулевое будет занято. А его желательно оставить свободным для остальных задач. Особенно если вы снимаете дампы СУБД и сразу жмёте в каком-то нагруженном сервере. В таком случае можно явно во время запуска указать pigz, какие ядра использовать.

Для этого нужно запустить программу через taskset, указав ядра, на которых она будет работать. К сожалению, для этого не получится использовать простой список ядер, типа 1,2,3. Нужно использовать bitmask в полном или сокращённом виде. Например, использование только 0-го ядра будет выглядеть вот так:

# taskset 0x00000001 pigz testfile
или просто
# taskset 1 pigz testfile

Pigz будет жать только одним, нулевым ядром. Я до конца не разобрался, как быстро понять, какая маска тебе нужна. Самый простой способ это узнать, проверить на каком-то работающем процессе. Ему можно задать список ядер не маской, а явно. Допустим, нам нужна запустить архиватор только на 2 и 3 ядре. Для этого назначим, к примеру, эти ядра для htop и посмотрим нужную маску:

# taskset -pc 2-3 `pidof htop`
pid 984's current affinity list: 0-3
pid 984's new affinity list: 2,3
Смотрим маску:
# taskset -p `pidof htop`
pid 984's current affinity mask: c

Маска c. Запускаем pigz с этой маской, чтобы он жал только на 2 и 3 ядрах, оставив первые два свободными:

# taskset c pigz testfile

Я взял для примера именно pigz, потому что на нём наглядно видны все настройки. Какие ядра задал, такие он и использует. Для этого достаточно создать небольшой тестовый файл и понаблюдать через htop его поведение:

# dd if=/dev/zero of=/tmp/testfile bs=1024 count=2000000
# taskset 6 pigz testfile

Список масок, которые имеют отношение к первым 4-м ядрам:

1 - ядро 0
2 - ядро 1
3 - ядра 0,1
4 - ядро 2
5 - ядра 0,2
6 - ядра 1,2
7 - ядра 1,2,3
8 - ядро 3
9 - ядра 0,3
a - ядра 1,3
b - ядра 0,1,3
с - ядра 2,3
d - ядра 0,2,3

#linux #system
​​В ОС на базе Linux есть разные способы измерить время выполнения той или иной команды. Самый простой с помощью утилиты time:

# time curl http://127.0.0.1/server-status
Active connections: 1 
server accepts handled requests
 6726 6726 4110 
Reading: 0 Writing: 1 Waiting: 0 

real 0m0.015s
user 0m0.006s
sys 0m0.009s

Сразу показал на конкретном примере, как я это использовал в мониторинге. Через curl обращаюсь на страницу со статистикой веб сервера Nginx. Дальше распарсиваю вывод и забираю в том числе метрику real, которая показывает реальное выполнение запроса. Сама по себе в абсолютном значении эта метрика не важна, но важна динамика. Когда сервер работает штатно, то эта метрика плюс-минус одна и та же. И если начинаются проблемы, то отклик запроса страницы растёт. А это уже реальный сигнал, что с сервером какие-то проблемы.

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

# apt install hyperfine

С его помощью можно не только измерять время выполнения разовой задачи, но и прогонять множественные тесты, сравнивать выполнение разных команд, выгружать результаты в различные форматы, в том числе json. В репозитории много примеров. Hyperfine заточен в основном на оптимизацию консольных команд, сравнение и выявление узких мест. Лично мне он больше интересен как инструмент мониторинга.

Например, в hyperfine можно обернуть какую-то команду и получить информацию по её выполнению. Покажу на примере создания дампа mysql базы:

# hyperfine --runs 1 --export-json mysqldump.json 'mysqldump --opt -v --no-create-db db01 -u'user01' -p'pass01' > ~/db01.sql'

На выходе получаем файл mysqldump.json с информацией:

{
 "results": [
  {
   "command": "mysqldump --opt -v --no-create-db db01 -u'user01' -p'pass01' > ~/db01.sql",
   "mean": 2.7331184105,
   "stddev": null,
   "median": 2.7331184105,
   "user": 2.1372425799999997,
   "system": 0.35953332,
   "min": 2.7331184105,
   "max": 2.7331184105,
   "times": [
    2.7331184105
   ],
   "exit_codes": [
    0
   ]
  }
 ]
}

Получаем команду, время выполнения и код выхода. Эти данные можно забирать в систему мониторинга или сбора логов. Удобно настроить мониторинг на среднее время выполнения команды или на код выхода. Если не нулевой, то срабатывает триггер.

Точно так же можно собирать информацию о реальном отклике сайта:

# hyperfine --runs 3 'curl -s https://github.com/'

Можно раз в минуту прогонять по 3 теста с нужной вам локации, записывать результат и сравнивать со средним или с заданным пределом.

Я привел примеры только для мониторинга. Так то hyperfine многофункционален. Так что берите на вооружение.

#linux #мониторинг #perfomance
​​Нравятся тенденции последних лет по принятию разных полезных современных утилит в базовые репозитории популярных дистрибутивов. Недавно рассказывал про hyperfine и bat. К ним можно теперь добавить утилиту duf, как замену df. Она теперь тоже переехала в базовый репозиторий:

# apt install duf

Когда первый раз про неё писал, её там не было. Качал бинарник вручную. Рассказывать про неё особо нечего. Так же, как и df, duf показывает использование диска разных устройств и точек монтирования. Вывод более наглядный, чем в df. Плюс, есть несколько дополнительных возможностей, которые могут быть полезны:

▪️ Умеет делать вывод в формате json:
# duf -json

▪️ Умеет сразу сортировать по разным признакам:
# duf -sort size
# duf -sort used
# duf -sort avail

▪️ Умеет группировать и сортировать устройства:
# duf --only local
# duf --only network
# duf --hide local
# duf --only-mp /,/mnt/backup
и т.д.

То есть эта штука удобна не только для визуального просмотра через консоль, но и для использования в различных костылях, велосипедах и мониторингах. Не нужно парсить регулярками вывод df, а можно отфильтровать, выгрузить в json и обработать jq. Написана duf на GO, работает шустро. Хороший софт, можно брать на вооружение.

#linux #terminal
Начиная с пятницы, в сети наперебой постили новости с шокирующей уязвимостью в OpenSSH сервере CVE-2024-3094, которая позволяет получить доступ к SSH-серверу без аутентификации (на самом деле это не так). Якобы ей подвержены почти все современные системы. Я всю пятницу и субботу в сборах и дороге был, так что только вчера смог спокойно сесть и разобраться, что там случилось.

Сразу скажу, что если у вас Debian 11 или 12 можно вообще не переживать и не торопиться обновляться. Никаких проблем с найденной уязвимостью в этих системах нет. Заражённый пакет успел приехать только в тестовый репозиторий sid.

Расскажу своими словами, в чём там дело. OpenSSH сервер использует библиотеку liblzma. Насколько я понял, не все сервера её используют, но большая часть. Проверить можно так:

# ldd "$(command -v sshd)" | grep liblzma
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f4f01c9d000)

Уязвимой является версия библиотеки 5.6.0 и 5.6.1. Проверяем установленную у себя версию через пакетный менеджер. Для deb вот так:

# dpkg -l | grep liblzma
ii liblzma5:amd64         5.4.1-0.2           amd64    XZ-format compression library

Или напрямую через просмотр версии xz:

# xz --version
xz (XZ Utils) 5.4.1
liblzma 5.4.1

В Debian 12 указанной уязвимости нет, можно не переживать. В security-tracker есть отдельная страница по этой уязвимости. Там видно, что версия 5.6.1 была только в sid.

В rpm дистрибутивах нужно проверять версию пакета xz-libs:

# rpm -qa | grep xz-libs
xz-libs-5.2.4-4.el8_6.x86_64

Для 8-й ветки форков RHEL проблема тоже неактуальна. 9-й у меня нигде нет, там не проверял.

Вообще, история с этой уязвимостью очень любопытная. На самом деле она позвоялет выполнить произвольный код в системе, не оставляя следов в логах sshd. Подробный разбор работы есть на opennet. Сделано всё очень мудрёно и запутанно не без использования bash портянки, которая выглядит как обфускация. А обнаружили уязвимость случайно, потому что sshd стал чуток медленнее работать, чем раньше. А сколько таких уязвимостей есть в системах, которые ещё никто случайно не заметил?

#linux #security
​​В популярных файловых системах на Linux есть одна полезная особенность. Любой файл или каталог можно сделать неизменяемым с помощью атрибута immutable. Его ещё называют immutable bit. Его может установить только root. Он же его может и убрать.

Сразу покажу на примере, где это может быть актуально. Я уже как-то делал ранее заметки на тему заполнения локальной файловой системы, когда вы копируете что-то в точку монтирования, например, /mnt/backup, которая подключает сетевой диск. В случае, если диск по какой-то причине не подключился, а вы в точку монтирования /mnt/backup залили кучу файлов, они всё лягут локально в корень и заполнят его.

Бороться с этим можно разными способами. Например, проверять перед копированием монтирование с помощью findmnt. А можно просто с помощью флага immutable запретить запись в директорию:

# chattr +i /mnt/backup

Так как это признак файловой системы, то когда сетевой диск будет смонтирован поверх, писать в директорию можно будет. А если диск не примонтирован, то в локальную директорию записать не получится:

# > /mnt/backup/file.txt
bash: /mnt/backup/file.txt: Operation not permitted

Убираем бит и пробуем ещё раз:

# chattr -i /mnt/backup
# > /mnt/backup/file.txt
# ls /mnt/backup/file.txt
/mnt/backup/file.txt

Посмотреть наличие этого бита можно командой lsattr. Для директории необходимо добавлять ключ -a, для отдельных файлов он не нужен.

# lsattr -a /mnt/backup
--------------e------- /mnt/backup/..
----i---------e------- /mnt/backup/.

Буква i указывает, что immutable bit установлен. Про псевдопапки точка и две точки читайте отдельную заметку.

Можно придумать разное применение этого бита. В основном это будут какие-то костыли, которыми не стоит сильно увлекаться. Например, можно очень просто запретить изменение паролей пользователям. Достаточно установить immutable bit на файл /etc/shadow:

# chattr +i /etc/shadow

Теперь если пользователь попытается поменять пароль, то у него ничего не выйдет. Даже у root:

# passwd root
passwd: Authentication token manipulation error
passwd: password unchanged

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

Также читал, что некоторые трояны и прочие зловреды защищают себя от удаления или изменения с помощью immutable bit. Так что если расследуете взлом, имеет смысл рекурсивно пройтись по всем системным бинарям и проверить у них этот бит. Отсюда следует параноидальный способ защиты от вирусов - использование этого бита на всех важных системных файлах. Нужно только понимать, что для обновления системы, этот бит нужно будет снимать и потом ставить заново.

Если знаете ещё какое-то полезное применение immutable, поделитесь в комментах. Я видел, что некоторые /etc/hosts или /etc/resolve.conf им защищают от изменений.

Вообще, это неплохой вопрос для собеседований или шуток над каким-то незнающим человеком. Обычно в Unix root может удалить всё, что угодно, даже работающую систему. А тут он вдруг по какой-то причине не может удалить или изменить файл, записать в директорию.

#linux
​​Для управления Linux сервером через браузер существуют два наиболее популярных решения:

▪️ webmin
▪️ cockpit

Webmin очень старый продукт, написанный на Perl. Он же наиболее функциональный. Развивается до сих пор. Удивительный долгожитель. Сколько работаю с Linux, столько его знаю. Под него существует большое количество плагинов. Вся базовая функциональность сервера им покрывается: файрвол, samba, postfix и dovecot, dns и dhcp, логи, обновления и т.д. Я знал админов, которые успешно управлялись с сервером только через вебмин, не умея и не работая в консоли вообще. Удивился, когда не нашёл на своём канале отдельной заметки про эту панель. Неплохо её знаю, доводилось работать, хотя на свои сервера не устанавливал.

Cockpit более молодой проект, который принадлежит Red Hat. Ими же и развивается. Он более компактный и целостный, возможностей поменьше, чем у Webmin, но лично я бы для базовых задач отдал ему предпочтение. Но только если вам хватает его возможностей. В cockpit удобный просмотр логов, установка обновлений, выполнение базовых настроек системы — переименовать, настроить сеть, посмотреть автозагрузку, остановить или запустить какую-то службу, посмотреть таймеры systemd, отредактировать пользователя и т.д. Можно поставить и отдать сервер в управление кому-то далёкому от консоли человеку. Он сможет решать какие-то простые задачи, типа установки обновлений и настройки пользователей.

Сегодня хочу немного расширить эту тему и познакомить вас с ещё одной панелью управления сервером - Ajenti. Сразу скажу, что это проект намного меньше и проще описанных выше, но у него есть некоторые свои полезные особенности. Базовые возможности там примерно такие же, как у Cockpit без модулей. Функциональность расширяется плагинами, которые устанавливаются через веб интерфейс.

Я развернул на тестовом сервере Ajenti и внимательно посмотрел на неё. Отметил следующие полезные возможности:

двухфакторная аутентификация через TOTP;
аутентификация по сертификатам;
🔥настраиваемые дашборды с табами и виджетами, куда можно добавить запуск служб или выполнение каких-то скриптов;
удобный файловый менеджер;
есть русский язык;
адаптивный интерфейс, работает и на смартфонах.

Устанавливается панель просто. Есть инструкция, где описан автоматический и ручной способ установки. Панель написана на Python, так что установка через pip. Есть простой скрипт, который автоматизирует её в зависимости от используемого дистрибутива:

# curl https://raw.githubusercontent.com/ajenti/ajenti/master/scripts/install-venv.sh | bash -s -

Скрипт определяет дистрибутив, устанавливает необходимые пакеты и панель через pip, создаёт systemd службу.

Далее можно идти по IP адресу сервера на порт 8000 и логиниться под root в панель. Сразу имеет смысл сгенерировать самоподписанный TLS сертификат, включить принудительную работу по HTTPS. Всё это в админке делается.

#linux
Ранее я делал шпаргалку по mtime, ctime, atime и crtime. Кто иногда путается в этих характеристиках, как я, рекомендую почитать и сохранить. Я там постарался кратко рассказать о них, чтобы не ошибаться на практике. Хотя путаться всё равно не перестал. Расскажу недавнюю историю.

Надо было периодически чистить корзину от Samba. Сама шара регулярно бэкапится, так что большого смысла в корзине нет. Сделал её больше для себя, чтобы если что, можно было быстро локально восстановить случайно удалённые файлы, а не тянуть с бэкапа. Засунул в крон простую команду по очистке:

/usr/bin/find /mnt/shara/.trash/ -type d -mtime +7 -exec rm -rf {} \;

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

В какой-то момент был удалён сам каталог .trash/. Я, не вникая в суть проблемы, на автомате решил, что достаточно в корне этого каталога раз в сутки обновлять какой-нибудь файл, чтобы mtime каталога обновлялся, и скрипт его не удалял. Добавил перед удалением обновление одного и того же файла через touch:

/usr/bin/touch /mnt/shara/.trash/timestamp

Через некоторое время каталог .trash/ опять был удалён. Тут уже решил разобраться. Оказалось, обновление mtime файла внутри каталога недостаточно, чтобы обновился mtime самого каталога. Нужно, чтобы был удалён или добавлен какой-то файл. То есть надо файл timestamp удалить и добавить снова. Тогда mtime каталога обновится. В итоге сделал так:

/usr/bin/rm /mnt/shara/.trash/timestamp
/usr/bin/touch /mnt/shara/.trash/timestamp
/usr/bin/find /mnt/shara/.trash/ -type d -mtime +7 -exec rm -rf {} \;

Надеюсь теперь всё будет работать так, как задумано.

Такой вот небольшой нюанс, о котором я ранее не знал. Изменения mtime файла внутри каталога недостаточно для изменения mtime каталога, в котором находится этот файл. Необходимо добавить, удалить или переименовать файл или каталог внутри родительского каталога.

Если я правильно понимаю, то так происходит, потому что каталог это по сути набор информации о всех директориях и файлах внутри. Информация эта состоит из имени и номера inode. Когда я через touch дёргаю файл, его номер inode не меняется. Поэтому и родительский каталог остаётся неизменным. А если файл удалить и создать снова, даже точно такой же, то его номер inode поменяется, поэтому и mtime каталога изменяется.

Век живи - век учись. С такими вещами пока не столкнёшься, не познакомишься. Просто так со всем этим разбираться вряд ли захочется. Я вроде всю теорию по файлам, директориям и айнодам когда-то изучал, но уже всё забыл. Теория без практики мертва.

#linux
Максимально простой и быстрый способ перенести без остановки ОС Linux на другое железо или виртуальную машину. Не понадобится ничего, кроме встроенных средств. Проверял лично и не раз. Перед написанием этой заметки тоже проверил.

Допустим, у вас система виртуальной машины установлена на /dev/sda. Там, соответственно, будет три раздела: boot, корень и swap. Нам надо эту систему перенести куда-то в другое место. Желательно на однотипное железо, чтобы не возникло проблем. Если железо будет другое, то тоже реально, но нужно будет немного заморочиться и выполнить дополнительные действия. Заранее их все не опишешь, так как это сильно зависит от конкретной ситуации. Скорее всего придётся внутри системы что-то править (сеть, точки монтирования) и пересобрать initrd.

Создаём где-то новую виртуальную машину с таким же диском. Загружаемся с любого загрузочного диска. Например, с SystemRescue. Настраиваем в этой системе сеть, чтобы виртуальная машина, которую переносим, могла сюда подключиться. Запускаем сервер SSH. Не забываем открыть порты в файрволе. В SystemRescue он по умолчанию включен и всё закрыто на вход.

Идём на виртуалку, которую будем переносить. И делаем там простой трюк:

# dd if=/dev/sda | ssh root@10.20.1.28 "dd of=/dev/sda"

Мы с помощью dd читаем устройство /dev/sda и передаём его содержимое по ssh на другую машину такой же утилите dd, которая пишет информацию в устройство /dev/sda уже на другой машине. Удобство такого переноса в том, что не нужен промежуточный носитель для хранения образа. Всё передаётся налету.

Процесс будет длительный, так как передача получается посекторная. Нужно понимать, что если машина большая и нагруженная, то в момент передачи целостность данных нарушается. Какую-нибудь СУБД так не перенести. Я лично не пробовал, но подозреваю, что с большой долей вероятности база будет битая. А вот обычный не сильно нагруженный сервер вполне.

После переноса он скорее всего ругнётся на ошибки файловой системы при загрузке, но сам себя починит с очень большой долей вероятности. Я как-то раз пытался так перенести виртуалку на несколько сотен гигабайт. Вот это не получилось. Содержимое судя по всему сильно билось по дороге, так как виртуалка не останавливалась. Не удалось её запустить. А что-то небольшое на 20-30 Гб вполне нормально переносится. Можно так виртуалку от какого-то хостера себе локально перенести. Главное сетевую связность между ними организовать.

Если по сети нет возможности передать образ, то можно сохранить его в файл, если есть доступный носитель:

# dd if=/dev/sda of=/mnt/backup/sda.img

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

# dd if=/mnt/backup/sda.img of=/dev/sda

Делаем всё это с какого-то загрузочного диска.

Напомню, что перенос системы можно выполнить и с помощью специально предназначенного для этого софта:

▪️ ReaR
▪️ Veeam Agent for Linux FREE
▪️ Clonezilla

#linux #backup
​​Для тех, кто не любит читать многостраничные man, существует его упрощённая версия, поддерживаемая сообществом — tldr. Аббревиатура как бы говорит сама за себя — Too long; didn't read. Это урезанный вариант man, где кратко представлены примеры использования консольных программ в Linux с минимальным описанием.

Для просмотра информации из tldr можно использовать консольный клиент, либо просто пользоваться веб версией. Описание каждой программы умещается в одну страницу. Авторы, судя по всему, последователи чеховского принципа: "Краткость сестра таланта".

Вот пример выдачи для lsof:

lsof — Lists open files and the corresponding processes. Note: Root privileges (or sudo) is required to list files opened by others. More information: https://manned.org/lsof.

● Find the processes that have a given file open:
lsof path/to/file
● Find the process that opened a local internet port:
lsof -i :port
● Only output the process ID (PID):
lsof -t path/to/file
● List files opened by the given user:
lsof -u username
● List files opened by the given command or process:
lsof -c process_or_command_name
● List files opened by a specific process, given its PID:
lsof -p PID
● List open files in a directory:
lsof +D path/to/directory
● Find the process that is listening on a local IPv6 TCP port and don't convert network or port numbers:
lsof -i6TCP:port -sTCP:LISTEN -n -P

В принципе, всё основное охватили. Кому интересно, может посмотреть мою подборку с примерами использования lsof. Я тоже люблю такие краткие выжимки с примерами. Надо будет собрать их все в одну публикацию. На канале уже много набралось по многим популярным утилитам.

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

▪️ cheat.sh — он удобнее организован, можно информацию получать через curl сразу в консоль, без установки клиента
▪️ explainshell.com — тут немного другой принцип, на основе man выдаёт описание длинных команд с разными ключами

Отдельно упомяну сервис, который немного про другое, но тоже очень полезный. Регулярно им пользуюсь:

🔥 shellcheck.net — проверка синтаксиса shell скриптов

#linux #terminal
​​После установки обновлений иногда необходимо выполнить перезагрузку системы. Точно надо это сделать, если обновилось ядро. Необходимо загрузиться с новым ядром. В коммерческих системах Linux от разных разработчиков есть механизмы обновления ядра без перезагрузки. В бесплатных системах такого не видел.

Для того, чтобы отслеживать этот момент, можно воспользоваться программой needrestart. Она есть в базовых репах:

# apt install needrestart

В rpm дистрибутивах название будет needs-restarting. Если просто запустить программу, то она в интерактивном режиме покажет, какие службы необходимо перезапустить, чтобы подгрузить обновлённые библиотеки, либо скажет, что надо перезапустить систему, чтобы применить обновление ядра.

Для того, чтобы использовать её в автоматизации, есть ключ -b, batch mode:

# needrestart -b
NEEDRESTART-VER: 3.5
NEEDRESTART-KCUR: 5.10.0-25-amd64
NEEDRESTART-KEXP: 5.10.0-29-amd64
NEEDRESTART-KSTA: 3
NEEDRESTART-SVC: cron.service
NEEDRESTART-SVC: dbus.service
NEEDRESTART-SVC: getty@tty1.service
NEEDRESTART-SVC: ifup@ens18.service
NEEDRESTART-SVC: qemu-guest-agent.service
NEEDRESTART-SVC: rsyslog.service
NEEDRESTART-SVC: systemd-journald.service
NEEDRESTART-SVC: systemd-logind.service
NEEDRESTART-SVC: systemd-timesyncd.service
NEEDRESTART-SVC: systemd-udevd.service

Здесь перечислены службы, которые нужно перезапустить после обновления системы. И показана информация об ядре. Значение NEEDRESTART-KSTA может принимать следующие состояния необходимости обновления ядра:

0: неизвестно, либо не удалось определить
1: нет необходимости в обновлении
2: ожидается какое-то ABI совместимое обновление (не понял, что это такое)
3: ожидается обновление версии

Если у вас значение 3, как у меня в примере, значит систему нужно перезагрузить, чтобы обновлённое ядро 5.10.0-29-amd64 заменило текущее загруженное 5.10.0-25-amd64.

Значение NEEDRESTART-KSTA можно передать в мониторинг и отслеживать необходимость перезагрузки. Например, В Zabbix можно передать вывод следующей команды:

# needrestart -b | grep 'NEEDRESTART-KSTA' | awk '{print $2}'

Если на выходе будет 3, активируем триггер. Передать значение можно любым доступным способом, которому вы отдаёте предпочтение в своей инфраструктуре:

с помощью локального скрипта и параметра UserParameter в агенте
с помощью EnableRemoteCommands в агенте и ключа system.run на сервере
с помощью zabbix_sender
с помощью скрипта и передачи значения ключа напрямую в сервер через его API

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

После перезагрузки значение NEEDRESTART-KSTA станет равно единице:

# needrestart -b
NEEDRESTART-VER: 3.5
NEEDRESTART-KCUR: 5.10.0-29-amd64
NEEDRESTART-KEXP: 5.10.0-29-amd64
NEEDRESTART-KSTA: 1

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

Покажу, как строку сразу преобразовать в нормальный json, чтобы потом можно было легко анализировать:

# needrestart -b | tr ':' '=' | tr -d ' ' | jo -p
{
  "NEEDRESTART-VER": 3.5,
  "NEEDRESTART-KCUR": "5.10.0-29-amd64",
  "NEEDRESTART-KEXP": "5.10.0-29-amd64",
  "NEEDRESTART-KSTA": 1
}

Обработал в лоб. Взял утилиту jo, заменил : на = c помощью tr, потому что jo понимает только =, потом убрал лишние пробелы опять же с помощью tr. Получили чистый json, из которого с помощью jsonpath можно забрать необходимое для анализа значение.

# needrestart -b | tr ':' '=' | tr -d ' ' | jo -p | jq .'"NEEDRESTART-KSTA"'
1

Придумал это без помощи ChatGPT. Даже не знаю уже, хорошо это или плохо. По привычке трачу время и пишу такие штуки сам.

#linux #мониторинг
​​Есть популярный вопрос для собеседования администраторов Linux:

Расскажите, как происходит загрузка операционной системы на базе Linux.

Тема, на самом деле полезная, в отличие от некоторых других, имеет прикладное значение, особенно если приходится переносить системы, либо сталкиваться с тем, что тот или иной сервер по какой-то причине не загружается. А причин может быть много. Не понимая процесс загрузки, решить их затруднительно. Расскажу эту тему своими словами с примерами из своей практики.

1️⃣ После запуска сервера или виртуалки, первым делом загружается bios или uefi. Bios ищет загрузчик на локальном или сетевом носителе и запускает его. Uefi может в себе содержать загрузчик. А может и нет. Если вы переносите виртуалку с одного гипервизора на другой, то обязательно учитывайте этот момент, используется bios или uefi. Если второе, то на другом гипервизоре нужно будет воспроизвести настройки uefi, чтобы виртуалка заработала. Если честно, я не совсем понимаю, зачем может быть нужен uefi для виртуальных машин, если не используется secure boot. Проще использовать обычный bios. Пример, как может на практике выглядеть перенос VM с uefi с HyperV на Proxmox.

2️⃣ Дальше загружается загрузчик с диска (не обязательно локального, может и сетевого). Для Linux обычно это GRUB. Я ничего другого не встречал, хотя есть и другие. У загрузчика есть небольшое меню и набор опций, которые иногда пригождаются. Например, если загрузчик по какой-то причине не смог загрузиться с диска или раздела, который у него указан загрузочным. Можно это сделать вручную через grub rescue. Пример, когда я так поступал, чтобы починить загрузку системы.

❗️Важно не забывать про загрузчик, когда вы используете в качестве загрузочного диска mdadm раздел софтового рейда. Загрузчик GRUB должен быть на всех дисках, входящих в рейд массив, чтобы в случае выхода из строя одного диска, вы могли загрузиться с любого другого. Он не реплицируется автоматически, так как mdadm работает на уровне разделов диска, а загрузчик располагается вне разделов.

3️⃣ В зависимости от настроек GRUB, загружается ядро Linux. Оно монтирует специально подготовленный образ файловой системы initramfs, загружаемый в оперативную память. Этот образ содержит все необходимые настройки и драйвера, чтобы загрузиться с нестандартный файловых систем, с LVM, с RAID, по сети и т.д. Там могут быть любые настройки. Можно выводить какую-то заставку, проверять диски и многое другое. Также с него запускается первый процесс init.

Процесс пересборки initramfs вы можете наблюдать при обновлениях ядра в системе. В конце обычно пакетный менеджер подвисает на несколько секунд как раз на пересборке initramfs. Если ему помешать в этот момент, то потом можете не загрузиться с новым ядром, для которого не собрался initramfs. Я с таким сталкивался. А вот пример, когда с этим же столкнулся человек на своём ноуте. Мой совет с пересборкой initramfs ему помог.

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

4️⃣ После запуска Init начинает загружаться система инициализации и управления службами. Сейчас это почти везде SystemD. Здесь я особо не знаю, что рассказать. С какими-то проблемами если и сталкивался, то это уже отдельные моменты в работающей системе, которые относительно легко исправить, так как чаще всего к системе уже есть удалённый доступ.

Написал всё так, как я это знаю и понимаю. Возможно в чём-то ошибаюсь, потому что в каждом из этих разделов есть много нюансов. Один только uefi чего стоит. Я как мог ужал материал, чтобы уместить в формат заметки и дать максимум информации, которая пригодится в реальной работе.

#linux #grub
​​В ОС на базе Linux есть очень простой в настройке инструмент по ограничению сетевого доступа к сервисам. Он сейчас почти не применяется, так как не такой гибкий, как файрволы, но тем не менее работает до сих пор. Речь пойдёт про TCP Wrappers, которые используют библиотеку libwrap для ограничения доступа. По своей сути это файрвол уровня приложений, которые его поддерживают. Расскажу, как это работает.

В большинстве Linux дистрибутивов есть файлы /etc/hosts.allow и /etc/hosts.deny. Сразу покажу пример, как всем ограничить доступ к SSH и разрешить только с указанных локальных подсетей. Добавляем в /etc/hosts.allow:

sshd : 10.20.1.0/24
sshd : 192.168.13.0/24

И одновременно в /etc/hosts.deny:

sshd : ALL

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

# journalctl -u ssh -n 10
sshd[738]: refused connect from 10.8.2.2 (10.8.2.2)

Не нужна ни перезагрузка, ни запуск каких-либо программ. Просто добавляете записи в указанные файлы и они сразу же применяются. Можно логировать заблокированные попытки:

sshd : ALL \ : spawn /usr/bin/echo "$(/bin/date +"%%d-%%m-%%y %%T") SSH access blocked from %h" >> /var/log/libwrap

В файле /var/log/libwrap будет аккуратная запись:

03-06-24 12:29:31 SSH access blocked from 10.8.2.2

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

# ldd /usr/sbin/sshd | grep libwrap
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007f55228a2000)

В Debian 12 sshd поддерживает, но так не во всех дистрибутивах. Надо проверять. Из более-менее популярного софта libwrap поддерживается в vsftpd, nfs-server, apcupsd, syslog-ng, nut, dovecot, stunnel, nagios, Nutanix Controller VM.

Очевидно, что тот же iptables или nftables более функциональный инструмент и полагаться лучше на него. Но в каких-то простых случаях, особенно, если нужно ограничить только ssh, можно использовать и libwrap. Также можно продублировать в нём правила, чтобы в случае ошибки в файрволе, доступ к некоторым сервисам точно не был открыт. Ну и просто полезно знать, что есть такой инструмент. Мало ли, придётся столкнуться.

#linux #security
​​Раньше были разные варианты перезагрузки системы Linux. Как минимум shutdown -r и reboot. Сейчас всё это не имеет значения, так как реально всем управляет systemd. А если посмотреть на shutdown и reboot, то окажется, что это символьные ссылки на systemctl.

# whereis reboot
reboot: /usr/sbin/reboot

# ls -la /usr/sbin/reboot
/usr/sbin/reboot -> /bin/systemctl

# whereis shutdown
shutdown: /usr/sbin/shutdown

# ls -la /usr/sbin/shutdown
/usr/sbin/shutdown -> /bin/systemctl

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

# systemctl reboot

Набирать systemctl не обязательно. Обычный reboot выполнит ту же самую команду.

Возникает вопрос, а как systemctl понимает, какую команду надо выполнить? Символьные ссылки одинаковы в обоих случаях и ведут просто в /bin/systemctl. С помощью механизма запуска программ execve можно узнать имя исполняемой команды. Примерно так:

$ bash -c 'echo $0'
bash

$0 покажет имя запущенной команды. В systemctl стоит проверка вызванной команды, поэтому она определяет, что реально вы запустили - reboot или shutdown. Вообще, в systemctl столько всего наворочено. Перезагрузить компьютер так же можно следующими командами:

# systemctl start reboot.target
# systemctl start ctrl-alt-del.target

Эти команды делают то же самое, что и reboot. По крайней мере на первый взгляд. Остаётся только гадать, зачем там всё это. Ну либо где-то в манах или исходниках читать.

Дам ещё небольшую подсказку в рамках этой темы. И shutdown, и reboot, и systemctl в итоге обращаются к бинарнику на диске. Если у вас какие-то проблемы с диском и не удаётся прочитать этот бинарник, то перезагрузка не состоится. Всё будет продолжать висеть. Если запущена консоль, то можно через неё сразу передать команду на перезагрузку напрямую ядру

# echo b > /proc/sysrq-trigger

Сервер тут же перезагрузится, как будто у него физически нажали reset.

#linux
Файловая система ext4 при создании резервирует 5% всего объёма создаваемого раздела. Иногда это очень сильно выручает, когда система встаёт колом и нет возможности освободить место. А без этого она не может нормально работать (привет zfs и lvm-thin). Тогда можно выполнить простую операцию:

# tune2fs -m 3 /dev/mapper/root
или
# tune2fs -m 3 /dev/sda3

Вместо 5% в резерв оставляем 3%, а высвободившееся место остаётся доступным для использования. На больших разделах 5% может быть существенным объёмом. Очень хочется этот резерв сразу поставить в 0 и использовать весь доступный объём. Сделать это можно так:

# tune2fs -m 0 /dev/sda3

Сам так не делаю никогда и вам не рекомендую. Хотя бы 1% я всегда оставляю. Но чаще всего именно 3%, если уж совсем место поджимает. Меня не раз и не два выручал этот резерв.

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

Создаём swap размером в гигабайт и подключаем:

# dd if=/dev/zero of=/swap bs=1024 count=1000000
# mkswap /swap
# chmod 0600 /swap
# swapon /swap

Если вдруг решите, что своп вам больше не нужен, отключить его так же просто, как и подключить:

# swapoff -a
# rm /swap

Третьим вариантом страховки в случае отсутствия свободного места на разделе является заранее создание пустого файла большого объёма.

# fallocate -l 10G /big_file

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

Может показаться, что это какие-то умозрительные примеры. Но на деле я много раз сталкивался с тем, что кончается место на сервере по той или иной причине, и службы на нём встают. А надо, чтобы работали. Пока разберёшься, что там случилось, уходит время. Я сначала добавляю свободное место из имеющихся возможностей (swap или резерв ext4), а потом начинаю разбираться. Это даёт возможность сразу вернуть работоспособность упавшим службам, а тебе несколько минут, чтобы разобраться, в чём тут проблема. Обычно это стремительно растущие логи каких-то служб.

#linux
Медленно, но верно, я перестаю использовать netstat и привыкаю к ss. У неё хоть и не такой удобный для восприятия вывод, но цепляться за netstat уже не имеет смысла. Она давно устарела и не рекомендуется к использованию. Плюс, её нет в стандартных минимальных поставках дистрибутивов. Надо ставить отдельно. Это как с ifconfig. Поначалу упирался, но уже много лет использую только ip. Ifconfig вообще не запускаю. Даже ключи все забыл.

Самые популярные ключи к ss это tulnp:

# ss -tulnp

Список открытых tcp и udp портов. Может показаться смешным и нелепым, но чтобы запомнить эту комбинацию и не лазить в шпаргалки, я представил её написание как тулуп (tulnp). Он хоть и не совсем тулуп, но это помогло мне запомнить эти ключи и активно использовать. Такие ассоциативные якоря помогают запоминать многие вещи. Я постоянно их использую в жизни.

Из того, что ещё часто используется - просмотр открытых сокетов. Актуально, чтобы быстро глянуть, поднялся ли сокет php-fpm или mariadb:

# ss -l | grep .sock

Вывести только сокеты можно и другой командой:

# ss -ax

Но там будет много лишнего. Трудно для восприятия. Поэтому грепнуть общий список мне проще, лучше запоминается и короче вывод.

У ss есть одна неприятная особенность, из-за которой она не кажется такой удобной, как netstat. Возможно, это только для меня актуально. Если терминал не очень широкий, то вывод расползается и труден для визуального восприятия. Я не люблю широкие окна для ssh подключений, обычно это небольшое окон посередине экрана, перед глазами. В таком окне вывод netstat выглядит аккуратнее, чем ss. Чтобы посмотреть ss, приходится разворачивать терминал на весь экран.

По памяти я больше ничего из ss не помню. Ещё несколько команд сохранены в заметках, остальные вообще не использую.

Просмотр активных сетевых соединений:

# ss -ntu

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

# ss -ntuH | awk '{print $6}' | grep -vE 127.0.0.1 | cut -d: -f1 | sort | uniq -c | sort -n| sed 's/^[ \t]*//'

То же самое, только выводим тех, у кого более 30 соединений с нами:

# ss -ntuH | awk '{print $6}' | grep -vE 127.0.0.1 | cut -d: -f1 | sort | uniq -c | sort -n| sed 's/^[ \t]*//' | awk '{if ($1 > 30) print$2}'

Получаем чистый список IP адресов, который можно куда-то направить. Например, в fail2ban, ipset или nftables. Если вас донимают простым досом какие-то мамкины хакеры, можете таким простым способом от них избавиться. Все эти примеры заработают только на ipv4. Для ipv6 нужно будет изменения вносить. Я пока отключаю везде ipv6, не использую.

Количество активных сетевых соединений с сервером:

# ss -ntuH | awk '{print $6}' | grep -vE 127.0.0.1 | wc -l

Всё то же самое, что делали выше, можно сделать не только для активных соединений, но и всех остальных, добавив ключ a:

# ss -ntua

Больше лично я ss ни для чего не использую. Если смотрите ещё что-то полезное с помощью этой утилиты, поделитесь в комментариях.

#linux #terminal
Стал регулярно сталкиваться с одной проблемой. Есть сервер с бюджетными SSD дисками. Они для многих задач вполне подходят, несмотря на низкую стоимость и скорость записи. Последнее как раз их узкое место. Но если у вас в основном с дисков чтение, то можно существенно экономить, используя десктопные диски.

У меня как раз такой случай. Несколько виртуалок под веб сервера, где в основном чтение из кэшей на дисках. По производительности никаких нареканий, кроме одного момента. Когда дампишь для бэкапов базы данных, весь гипервизор начинает прилично тормозить, а в мониторинг сыпятся уведомления о медленном ответе веб сервера и увеличении отклика дисков. Обычно это происходит ночью и особых проблем не доставляет. Но тем не менее, решил это исправить.

Самый простой способ в лоб - ограничить скорость пайпа, через который данные с mysqldump записываются в файл. По умолчанию всё читается и пишется параллельными потоками с одних и тех же SSD. Десктопные диски такой режим очень не любят и заметно тормозят при выполнении.

Я использовал утилиту pv:

# apt install pv
# mysqldump --opt -v --single-transaction --databases db01 | pv -L 20m > /mnt/backup/db01.sql

Ограничил скорость записи в 20 MiB/s через ключ -L. Для того, чтобы посмотреть текущую скорость записи, используйте pv без ограничения:

# mysqldump --opt -v --single-transaction --databases db01 | pv > /mnt/backup/db01.sql
............................
 1319MiB 0:00:06 [ 205MiB/s]

Вообще pv интересная утилита. Стоит написать о ней отдельно. Если знаете ещё какие-то способы решения этой задачи, поделитесь в комментариях. Если дампишь сразу по сети, то можно скорость сетевой передачи ограничивать. А вот так, чтобы локально, больше ничего в голову не приходит. Разве что жать сразу на лету с сильной компрессией, чтобы медленно было. Но это как-то муторно подбирать подходящую скорость.

#linux #terminal
Вчера вскользь упомянул утилиту pv, хотя она вполне заслуживает отдельного рассказа. Знаю её очень давно, но использую не часто. Конкретно в задаче по ограничению скорости записи дампа на диск она очень выручила. Других простых способов я не нашёл, да и никто не предложил ничего лучше.

PV это аббревиатура от pipeviewer. То есть это инструмент для работы с пайпами. Обычно есть в репозиториях всех популярных дистрибутивов:

# apt install pv
# dnf install pv

Чаще всего pv упоминают в контексте прогресс бара при работе с файлами и каталогами. Например, при копировании, перемещении, сжатии. Так как размер файлов заранее известен, а так же видна скорость обработки файлов, pv может предсказать, сколько процесс продлится и когда закончится. Примерно так:

# pv testfile > copy/testfile_copy
 976MiB 0:00:02 [ 344MiB/s] [=======================>] 100

Размер файла, который копировали, известен, скорость тоже, так что прогресс бар нормально отработал.

То же самое для сжатия:

# pv testfile | gzip > testfile.gz
 976MiB 0:00:05 [ 183MiB/s] [=======================>] 100

При этом pv может притормозить этот процесс, если у вас есть в этом потребность. Это очень полезная и практически уникальная возможность. Копируем файл с заданной скоростью:

# pv -L 50m testfile > copy/testfile_copy
 976MiB 0:00:19 [49.9MiB/s] [=======================>] 100

Ограничили скорость записи в 50 Мб в секунду (на самом деле мебибайт, но не суть важно, и зачем только придумали эту путаницу). Подобным образом можно ограничивать скорость любого пайпа.

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

# tar -czf - usr | pv -s $(du -sb /usr | grep -o '[0-9]*') > /tmp/usr.tgz
 126MiB 0:00:16 [9.46MiB/s] [==>                  ] 5% ETA 0:04:18

Наглядно виден процесс сжатия, сколько времени осталось. Мы по сути просто определили размер каталога usr через du и передали этот размер в pv через ключ -s. Можно и напрямую передать туда размер, если он известен. На самом деле со сжатием этот пример практически бесполезен, так как скорость сжатия всегда разная, в зависимости от того, какие файлы сжимаются.

Область применения pv обширная. Её можно воткнуть куда угодно, где используется пайп, как минимум, чтобы посмотреть скорость прохождения данных там, где это не видно. Например, можно проследить за снятием образа диска:

# pv -EE /dev/sda > disk-image.img

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

# pv -L 50m -EE /dev/sda > disk-image.img

Можно измерить скорость выполнения дампа СУБД:

# mysqldump --opt -v --databases db01 | pv > db01.sql

🔥 С помощью pv можно посмотреть за работой всех файловых дескрипторов, открытых процессов. Причём не просто список увидеть, но и скорость обработки данных в них:

# pv -d 1404
  3:/prometheus/queries.active: 0.00 B 0:01:40 [0.00 B/s]
  8:/prometheus/lock: 0.00 B 0:01:40 [0.00 B/s]
  9:/prometheus/wal/00000000: 10.9MiB 0:01:40 [4.28KiB/s]
 14:/prometheus/chunks_head/000001: 8.00 B 0:01:40 [0.00 B/s]
 16:/prometheus/chunks_head/000001: 0.00 B 0:01:40 [0.00 B/s]

С помощью pv легко ограничивать скорость передачи данных по сети, если направить их через pipe:

# pv -L 10m /tmp/testfile | ssh user@server02 'cat > /tmp/testfile'

Пример синтетический, так как копировать удобнее через rsync, так как там можно штатно указать ограничение на использование канала. Другое дело, что лично я эти ключи rsync наизусть не помню, надо смотреть. А ключ -L (limit) для pv помню.

Можно и просто скорость по ssh между двух серверов проверить:

# pv /dev/zero | ssh user@server02 'cat > /dev/null'

В общем, применять pv можно везде, где используются пайпы в Unix. Очень удобная штука.

#linux #terminal