Please open Telegram to view this post
VIEW IN TELEGRAM
😁13
systemd.path: запуск действия при изменении файла
Многие задачи автоматизации до сих пор решают через бесконечные циклы:
▪️ Что есть лучше
В systemd существует специальный тип юнитов —
Он использует inotify и реагирует на реальные изменения файлов или директорий, а не занимается постоянным опросом.
Пример: нужно перезапускать сервис после изменения конфигурации.
Создаем path-юнит:
▪️ Что умеет отслеживать
Не только изменение файла:
▪️ Почему это удобно
Вместо собственных демонов, cron и циклов с
BashTex📱 #bash
Многие задачи автоматизации до сих пор решают через бесконечные циклы:
while true; do
if [ -f /tmp/reload ]; then
systemctl restart myapp
rm /tmp/reload
fi
sleep 5
done
Работает, но процесс постоянно висит в памяти и каждые несколько секунд проверяет состояние файловой системы.В systemd существует специальный тип юнитов —
.path.Он использует inotify и реагирует на реальные изменения файлов или директорий, а не занимается постоянным опросом.
Пример: нужно перезапускать сервис после изменения конфигурации.
Создаем path-юнит:
[Path]
PathModified=/etc/myapp/config.yml
[Install]
WantedBy=multi-user.target
И связанный сервис:
[Service]
Type=oneshot
ExecStart=/bin/systemctl restart myapp.service
Активируем:
systemctl daemon-reload
systemctl enable --now myapp.path
Теперь изменение файла автоматически вызовет запуск сервиса.Не только изменение файла:
PathExists=/tmp/file
PathChanged=/var/log/app.log
DirectoryNotEmpty=/var/spool/tasks
Например, можно запускать обработчик сразу после появления нового файла в директории или при заполнении очереди задач.Вместо собственных демонов, cron и циклов с
sleep получаем событийную модель: пока ничего не происходит - не расходуются ресурсы. Как только происходит нужное событие - systemd запускает действие.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
flock: защита от повторного запуска скрипта
Одна из самых неприятных проблем в автоматизации - случайный запуск нескольких копий одного скрипта.
Например, cron запускает задачу каждые 5 минут, но одна из прошлых итераций ещё не завершилась.
В результате появляются дублирующиеся процессы, конфликты при работе с файлами и непредсказуемые ошибки.
▪️ Типичная ошибка
Допустим, скрипт выполняется 10 минут, а cron запускает его каждые 5:
▪️ Решение через flock
Самый простой вариант - добавить блокировку:
Ключ
▪️ Использование внутри скрипта
Можно защитить сам скрипт независимо от способа запуска:
▪️ Чем лучше PID-файлов
Многие делают так:
▪️ Где особенно полезно
Бэкапы, синхронизация файлов, обработка очередей, обновление данных, cron-задачи и любые скрипты, которые нельзя запускать параллельно.
BashTex📱 #scripts #flock
Одна из самых неприятных проблем в автоматизации - случайный запуск нескольких копий одного скрипта.
Например, cron запускает задачу каждые 5 минут, но одна из прошлых итераций ещё не завершилась.
В результате появляются дублирующиеся процессы, конфликты при работе с файлами и непредсказуемые ошибки.
Допустим, скрипт выполняется 10 минут, а cron запускает его каждые 5:
*/5 * * * * /opt/backup.sh
Через некоторое время одновременно будут работать сразу несколько экземпляров.Самый простой вариант - добавить блокировку:
flock -n /tmp/backup.lock /opt/backup.sh
Если lock-файл уже занят другим процессом, новая копия просто не запустится.Ключ
-n означает “не ждать освобождения блокировки”.Можно защитить сам скрипт независимо от способа запуска:
exec 200>/var/run/myjob.lock
flock -n 200 || {
echo "Already running"
exit 1
}
Теперь второй экземпляр завершится сразу после старта.Многие делают так:
echo $$ > /tmp/script.pid
Но после аварийного завершения PID-файл может остаться, а PID уже будет принадлежать другому процессу.flock работает через файловые дескрипторы ядра и автоматически освобождает блокировку при завершении процесса.Бэкапы, синхронизация файлов, обработка очередей, обновление данных, cron-задачи и любые скрипты, которые нельзя запускать параллельно.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
PIPESTATUS: как узнать, где именно сломался пайп
Большинство администраторов знают про
Посмотрим на пример:
Если
▪️ Решение - PIPESTATUS
После выполнения пайпа Bash сохраняет коды возврата всех его команд в массиве
▪️ Проверка конкретного этапа
Можно обратиться к нужному элементу массива:
▪️ А что насчёт pipefail?
Многие включают:
Но
Для диагностики всё равно пригодится
▪️ Почему это важно
Если в скрипте есть длинные цепочки из
BashTex📱 #scripts #pipestatus
Большинство администраторов знают про
$?, но при работе с пайпами он может вводить в заблуждение.Посмотрим на пример:
grep ERROR app.log | sort | uniq
echo $?
Если пайп состоит из нескольких команд, $? покажет код возврата только последней из них.Если
grep завершился с ошибкой, а uniq отработал успешно, вы увидите:0
Хотя одна из команд фактически провалилась.После выполнения пайпа Bash сохраняет коды возврата всех его команд в массиве
PIPESTATUS:grep ERROR app.log | sort | uniq
echo "${PIPESTATUS[@]}"
Результат может выглядеть так:2 0 0
Здесь видно, что ошибка произошла именно в grep.Можно обратиться к нужному элементу массива:
grep ERROR app.log | sort | uniq
echo "${PIPESTATUS[0]}"
Проверяем первую команду в цепочке.echo "${PIPESTATUS[1]}"
Проверяем вторую.Многие включают:
set -o pipefail
Это полезно — теперь пайп вернёт ошибку, если упала любая команда внутри него.Но
pipefail не показывает, какой именно этап завершился неудачно.Для диагностики всё равно пригодится
PIPESTATUS.Если в скрипте есть длинные цепочки из
grep, awk, sed, jq, sort и других утилит, обычный $? может скрыть проблему. PIPESTATUS позволяет быстро понять, где именно произошёл сбой.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Почему журналы journald могут неожиданно заполнить диск
На сервере закончилось место, а в
Часто виновником оказывается journald.
▪️ Где хранятся логи
Проверить объём журналов можно одной командой:
▪️ Посмотреть самые “тяжёлые” журналы
Узнать, сколько данных записывается за последние сутки:
▪️ Как очистить старые журналы
Оставить только последние 500 МБ:
▪️ Ограничение роста журналов
Настройки находятся в:
▪️ Почему это важно
Когда приложение начинает писать ошибки в цикле, journald может вырасти до нескольких гигабайт за считанные часы. Если заранее не настроить лимиты, одна неудачная конфигурация способна оставить сервер без свободного места.
BashTex📱 #scripts #systemd
На сервере закончилось место, а в
/var/log ничего подозрительного нет?Часто виновником оказывается journald.
Проверить объём журналов можно одной командой:
journalctl --disk-usage
Например:Archived and active journals take up 2.8G on disk.
На серверах с большим количеством сервисов объём может расти довольно быстро.Узнать, сколько данных записывается за последние сутки:
journalctl --since yesterday | wc -l
А если какой-то сервис генерирует тысячи сообщений в минуту:journalctl -u myapp.service
Обычно проблема находится довольно быстро.Оставить только последние 500 МБ:
journalctl --vacuum-size=500M
Или удалить записи старше 14 дней:journalctl --vacuum-time=14d
Очистка происходит без остановки journald.Настройки находятся в:
/etc/systemd/journald.conf
Например:SystemMaxUse=1G
SystemKeepFree=2G
После изменения конфигурации:systemctl restart systemd-journald
Когда приложение начинает писать ошибки в цикле, journald может вырасти до нескольких гигабайт за считанные часы. Если заранее не настроить лимиты, одна неудачная конфигурация способна оставить сервер без свободного места.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
tmpfiles.d: автоматическое создание и очистка директорий без cron
На многих серверах можно встретить скрипты, которые создают нужные каталоги при загрузке системы или периодически чистят временные файлы через cron.
Хотя systemd умеет делать это самостоятельно.
▪️ Что такое tmpfiles.d
Механизм
Конфигурации обычно находятся здесь:
▪️ Создание каталога при старте
Допустим, приложению нужен каталог для кэша:
После применения:
▪️ Автоматическая очистка
Удалять файлы старше 7 дней:
Проверить правила можно так:
▪️ Где это полезно
Кэш приложений, временные выгрузки, очереди обработки файлов, каталоги с отчётами и любые данные, которые должны жить ограниченное время.
▪️ Почему это удобнее cron
Вместо отдельных скриптов и задач в планировщике вся логика хранения описывается одной строкой конфигурации. Создание, права доступа и очистка управляются стандартными средствами системы.
BashTex📱 #scripts #tmpfiles
На многих серверах можно встретить скрипты, которые создают нужные каталоги при загрузке системы или периодически чистят временные файлы через cron.
Хотя systemd умеет делать это самостоятельно.
Механизм
tmpfiles.d позволяет создавать каталоги, менять права доступа, владельцев и автоматически удалять старые файлы по заданным правилам.Конфигурации обычно находятся здесь:
/etc/tmpfiles.d/
/usr/lib/tmpfiles.d/
Допустим, приложению нужен каталог для кэша:
d /var/cache/myapp 0755 myapp myapp -
Где:d — создать директорию0755 — права доступаmyapp myapp — владелец и группаПосле применения:
systemd-tmpfiles --create
Каталог появится автоматически.Удалять файлы старше 7 дней:
D /var/tmp/myapp 0755 myapp myapp 7d
Теперь systemd будет очищать содержимое каталога согласно политике хранения.Проверить правила можно так:
systemd-tmpfiles --clean
Кэш приложений, временные выгрузки, очереди обработки файлов, каталоги с отчётами и любые данные, которые должны жить ограниченное время.
Вместо отдельных скриптов и задач в планировщике вся логика хранения описывается одной строкой конфигурации. Создание, права доступа и очистка управляются стандартными средствами системы.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Почему
Одна из классических загадок Linux:
Куда пропало место?
▪️ Что считают du и df
Из-за этого их значения могут различаться.
▪️ Самая частая причина
Удалённый файл всё ещё открыт процессом.
Например:
Но если процесс продолжает писать в него, место останется занятым.
Найти такие файлы можно так:
▪️ Другие причины
Зарезервированные блоки ext4:
▪️ Быстрая диагностика
Если диск внезапно заполнился:
▪️ Почему это важно
На продакшн-серверах часто удаляют огромный лог в надежде освободить место. Но если процесс продолжает держать файл открытым, свободное пространство не появится, а приложение может вскоре упасть из-за нехватки диска.
BashTex📱 #scripts #du
du и df показывают разный размерОдна из классических загадок Linux:
df -h
Показывает:/dev/sda1 100%
Но если проверить содержимое файловой системы:du -sh /var
du -sh /home
du -sh /opt
Суммарный объём получается заметно меньше.Куда пропало место?
du подсчитывает размер файлов, которые видны в файловой системе.df показывает занятые блоки на уровне самой файловой системы.Из-за этого их значения могут различаться.
Удалённый файл всё ещё открыт процессом.
Например:
rm app.log
Файл исчез из каталога, поэтому du его больше не видит.Но если процесс продолжает писать в него, место останется занятым.
Найти такие файлы можно так:
lsof +L1
Пример вывода:java 1234 user 5w REG ... app.log (deleted)
Пока процесс не завершится или не закроет дескриптор, место не освободится.Зарезервированные блоки ext4:
tune2fs -l /dev/sda1 | grep Reserved
Смонтированные файловые системы внутри каталогов:mount | column -t
Или bind-монтирования, из-за которых данные учитываются неожиданным образом.Если диск внезапно заполнился:
df -h
lsof +L1
Во многих случаях проблема обнаруживается уже на втором шаге.На продакшн-серверах часто удаляют огромный лог в надежде освободить место. Но если процесс продолжает держать файл открытым, свободное пространство не появится, а приложение может вскоре упасть из-за нехватки диска.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Почему
Многие администраторы при зависшем процессе сразу используют:
▪️ Что делает SIGKILL
Сигнал
Процесс не может его перехватить, обработать или проигнорировать.
Ядро просто убивает его.
▪️ Что при этом не происходит
Процесс не успевает:
сохранить данные
закрыть файлы
завершить активные операции
удалить временные файлы
выполнить обработчики завершения
Например, база данных может не успеть корректно завершить транзакции.
▪️ Что использовать сначала
Обычный сигнал завершения:
Процесс получает запрос на завершение и может корректно освободить ресурсы.
▪️ Посмотреть, реагирует ли процесс
Отправляем SIGTERM:
▪️ Полезный приём
Для сервисов под systemd лучше использовать:
Только если сервис не реагирует, будет применено принудительное завершение.
▪️ Почему это важно
BashTex📱 #scripts #kill9
kill -9 - не лучший способ остановить процессМногие администраторы при зависшем процессе сразу используют:
kill -9 <PID>
Обычно это работает. Но далеко не всегда это правильное решение.Сигнал
-9 (SIGKILL) принудительно завершает процесс на уровне ядра.Процесс не может его перехватить, обработать или проигнорировать.
Ядро просто убивает его.
Процесс не успевает:
сохранить данные
закрыть файлы
завершить активные операции
удалить временные файлы
выполнить обработчики завершения
Например, база данных может не успеть корректно завершить транзакции.
Обычный сигнал завершения:
kill <PID>
илиkill -15 <PID>
Это SIGTERM.Процесс получает запрос на завершение и может корректно освободить ресурсы.
Отправляем SIGTERM:
kill -15 1234
Проверяем:ps -p 1234
Если процесс всё ещё работает спустя разумное время, тогда можно переходить к более жёстким мерам.Для сервисов под systemd лучше использовать:
systemctl stop myapp
systemd сам отправит нужные сигналы в правильном порядке и подождёт завершения процесса.Только если сервис не реагирует, будет применено принудительное завершение.
kill -9 часто помогает быстро решить проблему, но одновременно может создавать новые. Поэтому его лучше рассматривать как последний инструмент, когда процесс уже не отвечает на обычное завершение.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Проверка недавно созданных пользователей: UID, shell и следы активности
На сервере часто важно быстро понять, появлялись ли новые пользователи и насколько они “нормальные”.
Один из базовых источников -
▪️ Поиск пользователей с обычным UID диапазоном
Системные - ниже.
Смотрим shell:
▪️ Быстрый срез через lastlog
▪️ Проверка событий создания пользователей
▪️ Косвенная проверка “новизны”
Можно оценить свежесть через системные изменения:
▪️ Дополнительная проверка активности
▪️ Почему это важно
Новые пользователи с UID 1000+, нестандартным shell или отсутствием логинов — один из первых сигналов, который стоит проверять при аудите сервера.
BashTex📱 #scripts #du
На сервере часто важно быстро понять, появлялись ли новые пользователи и насколько они “нормальные”.
Один из базовых источников -
/etc/passwd, но там нет явной даты создания. Поэтому анализ строится через косвенные признаки.getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $7}'
Обычно реальные пользователи находятся начиная с UID 1000. Системные - ниже.
Смотрим shell:
/bin/bash, /bin/zsh чаще у людей, /usr/sbin/nologin или /bin/false - сервисные аккаунты.lastlog -t 30
Показывает пользователей, которые логинились за последние 30 дней. Новые аккаунты без активности сразу заметны.journalctl _COMM=useradd --since "7 days ago"
или через auth лог:grep useradd /var/log/auth.log
Здесь видны факты создания аккаунтов и изменения групп.Можно оценить свежесть через системные изменения:
stat /etc/passwd
или изменения shadow:stat /etc/shadow
Если недавно был добавлен пользователь, эти файлы будут обновлены в тот же период.faillog -a
иlast
Позволяют понять, пытался ли пользователь входить в систему и с каких хостов.Новые пользователи с UID 1000+, нестандартным shell или отсутствием логинов — один из первых сигналов, который стоит проверять при аудите сервера.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Работа с дескрипторами файлов через
В Bash обычно работают только с stdin (0), stdout (1) и stderr (2). Но файловые дескрипторы на этом не заканчиваются - можно использовать FD 3, 4 и выше для более гибкого управления потоками.
▪️ Базовая идея
Каждый процесс имеет таблицу файловых дескрипторов:
▪️ Разделение логов
Классический приём - разделить обычный вывод и отладку:
stdout остаётся чистым
debug уходит в отдельный файл
▪️ Перенаправление команд через FD
Можно связать вывод команды с кастомным дескриптором:
Чтение:
▪️ Логирование через единый канал
Удобный паттерн - централизованный лог:
▪️ Почему это лучше обычного >> везде
единая точка управления логированием
проще отключать/перенаправлять вывод
можно динамически менять файл логов через
▪️ Закрытие дескрипторов
▪️ Где это реально используется
сложные Bash-скрипты с несколькими потоками данных
системы логирования без внешних библиотек
обработка нескольких входных источников одновременно
изоляция debug/production вывода
FD выше 2 - это недооценённый инструмент, который превращает Bash из набора команд в полноценную систему управления потоками.
BashTex📱 #scripts #linux
exec: FD 3, 4, логирование и контроль потоковВ Bash обычно работают только с stdin (0), stdout (1) и stderr (2). Но файловые дескрипторы на этом не заканчиваются - можно использовать FD 3, 4 и выше для более гибкого управления потоками.
Каждый процесс имеет таблицу файловых дескрипторов:
0 → stdin
1 → stdout
2 → stderr
Но можно открыть дополнительные:exec 3>debug.log
Теперь FD 3 пишет в файл debug.log.Классический приём - разделить обычный вывод и отладку:
echo "normal output"
echo "debug info" >&3
Результат:stdout остаётся чистым
debug уходит в отдельный файл
Можно связать вывод команды с кастомным дескриптором:
exec 4< input.txt
Теперь FD 4 читает файл как поток.Чтение:
read -u 4 line
echo "$line"
Удобный паттерн - централизованный лог:
exec 3>>/var/log/myapp.log
log() {
echo "$(date '+%F %T') $*" >&3
}
Теперь все логи идут через FD 3, без захламления stdout.единая точка управления логированием
проще отключать/перенаправлять вывод
можно динамически менять файл логов через
execexec 3>&-
FD освобождается, файл больше не удерживается процессом.сложные Bash-скрипты с несколькими потоками данных
системы логирования без внешних библиотек
обработка нескольких входных источников одновременно
изоляция debug/production вывода
FD выше 2 - это недооценённый инструмент, который превращает Bash из набора команд в полноценную систему управления потоками.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Bash strict mode: что реально даёт set -euo pipefail и где он ломает логику
В bash часто добавляют так называемый "strict mode":
▪️ Что означает каждая опция
▪️ Что это реально улучшает
Без strict mode многие ошибки проглатываются:
Или:
будет явная ошибка, а не пустая строка.
▪️ pipefail: скрытая проблема пайп
Без него:
Возвращает код последней команды, даже если grep упал.
▪️ Где начинается проблема. Strict mode ломает сценарии, где ошибка - это нормальное состояние.
Пример:
Если совпадений нет, grep возвращает 1 и скрипт завершается, хотя это не ошибка логики.
▪️ Типичный workaround
Или:
Но это уже
▪️ ещё один частый кейс - test / if
Здесь grep
▪️ Итоговый баланс
Strict mode хорошо работает в:
• CI/CD
• одноразовых скриптах
• автоматизации без ветвлений
Но начинает мешать в:
• парсинге данных
• поиске (grep как логика)
• скриптах с ожидаемыми "ошибками как состоянием"
Это не универсальная защита, а переключатель модели поведения Bash-скрипта: от гибкого к строго детерминированному.
BashTex📱 #scripts #linux
В bash часто добавляют так называемый "strict mode":
set -euo pipefail
Идея простая - сделать скрипты более предсказуемыми и ловить ошибки раньше.-e - остановить скрипт при любой ошибке команды-u - ошибка при использовании неинициализированной переменной-o pipefail - пайп считается упавшим, если упала любая команда в цепочке
Без strict mode многие ошибки проглатываются:
rm file_not_exist
echo "continue"
Или:
echo "$UNDEFINED_VAR"
будет явная ошибка, а не пустая строка.
Без него:
cat file | grep ERROR | sort
Возвращает код последней команды, даже если grep упал.
Пример:
grep pattern file.txt
echo "done"
Если совпадений нет, grep возвращает 1 и скрипт завершается, хотя это не ошибка логики.
grep pattern file.txt || true
Или:
set +e
grep pattern file.txt
set -e
Но это уже
ручное управление поведением.
set -e
if grep pattern file.txt; then
echo "found"
fi
Здесь grep
может упасть, но в контексте if это нормальный контроль потока - и это не считается фатальной ошибкой.Strict mode хорошо работает в:
• CI/CD
• одноразовых скриптах
• автоматизации без ветвлений
Но начинает мешать в:
• парсинге данных
• поиске (grep как логика)
• скриптах с ожидаемыми "ошибками как состоянием"
Это не универсальная защита, а переключатель модели поведения Bash-скрипта: от гибкого к строго детерминированному.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
coproc на практике: двусторонний обмен данными с процессом
В bash обычно все сводится к pipe: команда - команда. Но классический пайп односторонний. Если нужен диалог с процессом в обе стороны - используется coproc.
▪️ Что такое coproc. Он запускает процесс и даёт два канала:
stdin - в процесс
stdout - из процесса
И все это без временных файлов и костылей с FIFO.
▪️ Базовый пример
Теперь у нас есть процесс калькулятора, с которым можно общаться.
Отправляем данные:
▪️ Как это устроено. После запуска bash создает массив:
Можно читать и писать независимо.
▪️ Реальный кейс: фоновый parser
Отправляем поток данных:
▪️ Почему это лучше pipe Pipe работает так:
Но:
• нет обратного канала
• процесс заканчивается сразу
• нельзя поддерживать состояние
coproc позволяет держать живой процесс и общаться с ним как с сервисом.
▪️ Важный момент. Процесс внутри coproc не перезапускается автоматически. Если он завершился - каналы перестают работать, и это нужно проверять вручную.
▪️ Где это реально полезно
• интерактивные CLI-инструменты (bc, python, sqlite3)
• долгоживущие парсеры (jq, awk, кастомные демоны)
• проксирование данных между процессами
• построение "мини-сервисов" прямо в Bash
coproc превращает bash из набора команд в примитивную систему IPC, где процессы начинают вести диалог, а не просто передавать поток данных в одну сторону.
BashTex📱 #bash #scripts
В bash обычно все сводится к pipe: команда - команда. Но классический пайп односторонний. Если нужен диалог с процессом в обе стороны - используется coproc.
stdin - в процесс
stdout - из процесса
И все это без временных файлов и костылей с FIFO.
coproc BC { bc -l; }
Теперь у нас есть процесс калькулятора, с которым можно общаться.
Отправляем данные:
echo "2+2" >&"${BC[1]}"
read result <&"${BC[0]}"
echo "$result"
${COPROC[0]} # stdout процесса
${COPROC[1]} # stdin процесса
Можно читать и писать независимо.
coproc JSON { jq -c '.name'; }
Отправляем поток данных:
echo '{"name":"test"}' >&"${JSON[1]}"
read out <&"${JSON[0]}"
echo "$out"
cmd1 | cmd2
Но:
• нет обратного канала
• процесс заканчивается сразу
• нельзя поддерживать состояние
coproc позволяет держать живой процесс и общаться с ним как с сервисом.
• интерактивные CLI-инструменты (bc, python, sqlite3)
• долгоживущие парсеры (jq, awk, кастомные демоны)
• проксирование данных между процессами
• построение "мини-сервисов" прямо в Bash
coproc превращает bash из набора команд в примитивную систему IPC, где процессы начинают вести диалог, а не просто передавать поток данных в одну сторону.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
nameref (
В Bash функции по умолчанию работают с копиями значений или с глобальными переменными. Но есть механизм, который позволяет имитировать “ссылки” -
▪️ Что такое nameref
▪️ Передача массива в функцию без копирования
Классическая проблема:
С
▪️ Модификация массива внутри функции
▪️ Где это особенно полезно
функции обработки конфигураций
парсинг JSON → массивы ключей/значений
работа с таблицами данных
построение библиотек на Bash без глобальных переменных
▪️ Важный момент
• значения
• выражения
• результаты команд
Только имя переменной.
▪️ Ограничения
нельзя безопасно переиспользовать ссылку на разные переменные в одном scope без переопределения
сложнее отлаживать (меняется оригинальный объект)
требует Bash 4.3+
▪️ Почему это важно
Без
BashTex📱 #scripts #linux
declare -n): ссылки на переменные и передача массивов в функцииВ Bash функции по умолчанию работают с копиями значений или с глобальными переменными. Но есть механизм, который позволяет имитировать “ссылки” -
nameref.declare -n создаёт ссылку на другую переменную:arr=(1 2 3)
declare -n ref=arr
ref[0]=999
echo "${arr[0]}"
Результат:999
ref не хранит данные - он указывает на arr.Классическая проблема:
func() {
local arr=("$@")
}
Это создаёт копию массива.С
nameref:func() {
local -n arr=$1
echo "${arr[0]}"
}
Вызов:data=(10 20 30)
func data
Функция работает с оригинальным массивом.func() {
local -n arr=$1
arr[1]=999
}
data=(10 20 30)
func data
echo "${data[@]}"
Результат:
10 999 30
функции обработки конфигураций
парсинг JSON → массивы ключей/значений
работа с таблицами данных
построение библиотек на Bash без глобальных переменных
nameref работает только с именами переменных:local -n ref=$1
Нельзя передавать:• значения
• выражения
• результаты команд
Только имя переменной.
нельзя безопасно переиспользовать ссылку на разные переменные в одном scope без переопределения
сложнее отлаживать (меняется оригинальный объект)
требует Bash 4.3+
Без
nameref Bash-функции либо копируют данные, либо используют глобальное состояние. declare -n даёт третий вариант — передачу по ссылке, что делает сложные скрипты заметно чище и ближе к языкам общего назначения.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Автоматическая реакция на OOM через systemd и cgroups: перезапуск и контроль памяти
OOM (Out Of Memory) - это не просто “закончилась память”. В Linux это механизм, при котором ядро начинает принудительно завершать процессы, чтобы система не упала целиком.
Проблема в том, что без контроля первым под нож часто попадает не тот процесс, который должен.
▪️ Как systemd влияет на OOM
systemd работает поверх cgroups и может задавать приоритеты “жертвенности” процессов:
▪️ Влияние на OOM Killer
Можно управлять приоритетом уничтожения:
▪️ Автоматический перезапуск после OOM
systemd может перезапускать сервис даже после убийства ядром:
▪️ Практический сценарий
Типичная ситуация:
• сервис разогнал память
• ядро убивает его через OOM
• systemd фиксирует падение
• запускает новый экземпляр
• cgroups не дают повторно выйти за лимит
▪️ Где начинается реальный контроль
Ключевой момент - сочетание:
• MemoryMax (жёсткий лимит)
• MemoryHigh (раннее давление)
• OOMScoreAdjust (приоритет убийства)
• Restart=on-failure (самовосстановление)
▪️ Почему это важно
Без cgroups OOM - это хаос: ядро выбирает жертву само.
С systemd это превращается в управляемую систему: процесс либо не доходит до OOM, либо корректно переживает его через перезапуск и ограничение ресурсов.
BashTex📱 #scripts #linux
OOM (Out Of Memory) - это не просто “закончилась память”. В Linux это механизм, при котором ядро начинает принудительно завершать процессы, чтобы система не упала целиком.
Проблема в том, что без контроля первым под нож часто попадает не тот процесс, который должен.
systemd работает поверх cgroups и может задавать приоритеты “жертвенности” процессов:
systemd-cgtop
Показывает, какие группы потребляют память.
▪️Контроль памяти на уровне unit
Можно ограничить сервис:
[Service]
MemoryMax=500M
Теперь процесс физически не сможет превысить лимит.
Дополнительно:
MemoryHigh=400M
Это мягкий порог - systemd начинает давить на процесс раньше, чем наступит OOM.Можно управлять приоритетом уничтожения:
OOMScoreAdjust=-500
или наоборот:
OOMScoreAdjust=500
Чем выше значение - тем выше шанс, что процесс будет убит первым.systemd может перезапускать сервис даже после убийства ядром:
[Service]
Restart=on-failure
RestartSec=2
Это работает и для OOM-kill, потому что процесс считается завершённым с ошибкой.Типичная ситуация:
• сервис разогнал память
• ядро убивает его через OOM
• systemd фиксирует падение
• запускает новый экземпляр
• cgroups не дают повторно выйти за лимит
Ключевой момент - сочетание:
• MemoryMax (жёсткий лимит)
• MemoryHigh (раннее давление)
• OOMScoreAdjust (приоритет убийства)
• Restart=on-failure (самовосстановление)
Без cgroups OOM - это хаос: ядро выбирает жертву само.
С systemd это превращается в управляемую систему: процесс либо не доходит до OOM, либо корректно переживает его через перезапуск и ограничение ресурсов.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Проверка файловых систем, смонтированных с опасными опциями
При аудите Linux обычно проверяют права доступа и SUID-биты. Но не менее важно посмотреть, как смонтированы файловые системы.
Если временный каталог или пользовательский раздел смонтирован с
▪️ Посмотреть все точки монтирования
Самый удобный способ:
▪️ На что обратить внимание
Опции монтирования:
•
•
•
Для каталогов вроде
▪️ Пример проверки
Более безопасный вариант:
▪️ Проверка через fstab
Чтобы убедиться, что настройки сохранятся после перезагрузки:
▪️ Почему это важно
Представьте, что злоумышленник смог записать файл в
Несколько минут на проверку параметров монтирования могут устранить целый класс потенциальных проблем ещё до того, как они будут использованы.
BashTex📱 #scripts #linux
При аудите Linux обычно проверяют права доступа и SUID-биты. Но не менее важно посмотреть, как смонтированы файловые системы.
Если временный каталог или пользовательский раздел смонтирован с
exec, suid или dev, это может значительно расширить поверхность атаки.Самый удобный способ:
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
Или классический вариант:mount
Опции монтирования:
•
exec - разрешает запуск исполняемых файлов.•
suid - позволяет работать SUID/SGID-битам.•
dev - разрешает использование файлов устройств.Для каталогов вроде
/tmp, /var/tmp или /dev/shm обычно безопаснее использовать противоположные опции:noexec,nosuid,nodev
findmnt -no TARGET,OPTIONS /tmp
Если вывод содержит:rw,relatime
значит ограничения отсутствуют.Более безопасный вариант:
rw,nosuid,nodev,noexec
Чтобы убедиться, что настройки сохранятся после перезагрузки:
grep -vE '^\s*#|^$' /etc/fstab
Ищите разделы, где для временных или пользовательских файловых систем не заданы защитные опции.Представьте, что злоумышленник смог записать файл в
/tmp. Если раздел смонтирован с exec, его можно сразу запустить. Если ещё и разрешён suid или dev, последствия могут быть значительно серьёзнее.Несколько минут на проверку параметров монтирования могут устранить целый класс потенциальных проблем ещё до того, как они будут использованы.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Скрипт поиска процессов с аномальным потреблением памяти
Когда на сервере заканчивается память, первое желание - открыть
▪️ Быстрый рейтинг по RSS
Размер физической памяти, занимаемой процессом (RSS), можно посмотреть так:
▪️ Автоматическая проверка
Например, вывести процессы, использующие больше 1 ГБ памяти:
▪️ Если нужен максимум информации
Часть данных о процессе хранится в
Эти значения могут сильно отличаться.
▪️ Не путайте RSS и VSZ
Большой
При поиске “пожирателей” памяти обычно ориентируются именно на
▪️ Почему это важно
Периодическая сортировка процессов по RSS помогает заметить утечки памяти ещё до того, как сработает OOM Killer. Особенно полезно для Java, Python, Node.js и других долгоживущих сервисов.
BashTex📱 #bash #linux
Когда на сервере заканчивается память, первое желание - открыть
top. Но он показывает только текущее состояние. Для автоматизации удобнее получить список самых “тяжёлых” процессов и использовать его в скриптах.Размер физической памяти, занимаемой процессом (RSS), можно посмотреть так:
ps -eo pid,user,comm,rss --sort=-rss | head -10
Поле rss выводится в килобайтах, поэтому сразу видно, кто потребляет больше всего ОЗУ.Например, вывести процессы, использующие больше 1 ГБ памяти:
ps -eo pid,comm,rss \
| awk '$3 > 1048576 {
printf "%-8s %-20s %.1f MB\n", $1, $2, $3/1024
}'
Такой вывод уже удобно отправлять в отчёт или систему мониторинга.Часть данных о процессе хранится в
/proc:grep -E 'VmRSS|VmSize' /proc/1234/status
VmRSS - реально занятая физическая память.VmSize - всё адресное пространство процесса, включая ещё не загруженные страницы.Эти значения могут сильно отличаться.
Большой
VSZ ещё не означает проблему. Многие приложения резервируют память заранее, но фактически используют лишь небольшую её часть.При поиске “пожирателей” памяти обычно ориентируются именно на
RSS.Периодическая сортировка процессов по RSS помогает заметить утечки памяти ещё до того, как сработает OOM Killer. Особенно полезно для Java, Python, Node.js и других долгоживущих сервисов.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Анализ активных UNIX-сокетов: поиск неожиданных IPC-соединений
При аудите обычно смотрят TCP- и UDP-порты, но многие сервисы вообще не используют сеть. Вместо этого они обмениваются данными через UNIX-сокеты.
Именно поэтому их тоже стоит периодически проверять.
▪️ Посмотреть все UNIX-сокеты
Самый удобный способ:
▪️ Получить больше информации
Если нужны процессы-владельцы:
▪️ На что обратить внимание
Особый интерес представляют сокеты в нестандартных местах:
▪️ Найти сокеты через файловую систему
▪️ Когда это полезно
UNIX-сокеты используют Docker, Podman, PostgreSQL, Redis, Nginx, PHP-FPM, systemd и десятки других сервисов.
Неожиданный сокет может указывать на недавно установленное ПО, самописный сервис или процесс, который не должен работать на сервере.
▪️ Почему это важно
Во многих инцидентах внимание уделяют только открытым сетевым портам. Но локальный IPC тоже может стать точкой входа или способом взаимодействия между процессами. Проверка UNIX-сокетов помогает увидеть часть инфраструктуры, которая остаётся незаметной при обычном аудите сети.
BashTex📱 #bash #linux
При аудите обычно смотрят TCP- и UDP-порты, но многие сервисы вообще не используют сеть. Вместо этого они обмениваются данными через UNIX-сокеты.
Именно поэтому их тоже стоит периодически проверять.
Самый удобный способ:
ss -xl
Ключ -x показывает UNIX-сокеты, а -l - только те, которые находятся в режиме ожидания соединений.Если нужны процессы-владельцы:
ss -xlp
Например:u_str LISTEN 0 128 /run/docker.sock
users:(("dockerd",pid=812,fd=7))
Сразу видно, какой процесс создал сокет.Особый интерес представляют сокеты в нестандартных местах:
/tmp/
/dev/shm/
/home/user/
Большинство системных сервисов используют /run или /var/run. Если сокет появился в /tmp, стоит проверить, кто его создал и зачем.find / -type s 2>/dev/null
Это покажет все файлы типа socket, даже если они сейчас не используются.UNIX-сокеты используют Docker, Podman, PostgreSQL, Redis, Nginx, PHP-FPM, systemd и десятки других сервисов.
Неожиданный сокет может указывать на недавно установленное ПО, самописный сервис или процесс, который не должен работать на сервере.
Во многих инцидентах внимание уделяют только открытым сетевым портам. Но локальный IPC тоже может стать точкой входа или способом взаимодействия между процессами. Проверка UNIX-сокетов помогает увидеть часть инфраструктуры, которая остаётся незаметной при обычном аудите сети.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
xargs против while read: где быстрее и безопаснееОбе конструкции позволяют обработать список файлов или строк, но работают они по-разному. Из-за этого одна может быть заметно быстрее, а другая - безопаснее.
xargsДопустим, нужно удалить все
.log-файлы:find . -name "*.log" | xargs rm
xargs собирает несколько аргументов и передаёт их одной команде, поэтому вместо сотен запусков rm будет всего несколько.Для большого количества файлов разница в производительности может быть существенной.
По умолчанию
xargs разделяет вход по пробелам и переводам строки.Если встретится файл:
my file.log
илиbackup
2025.log
команда отработает некорректно.Безопасный вариант:
find . -name "*.log" -print0 | xargs -0 rm
Здесь разделителем становится символ NULL, поэтому пробелы и спецсимволы больше не проблема.while read
Если над каждой строкой нужно выполнить несколько действий:
find . -name "*.log" -print0 |
while IFS= read -r -d '' file; do
echo "Deleting: $file"
rm "$file"
done
Такой код легче расширять: добавить проверки, логирование, условия или обработку ошибок.Для простого запуска одной команды обычно выигрывает
xargs.Для сложной логики, где каждая строка проходит несколько этапов обработки, удобнее использовать
while read.Многие используют
xargs и while read как взаимозаменяемые инструменты. На практике выбор зависит не только от скорости, но и от формата входных данных. Если есть вероятность встретить пробелы, переносы строк или необычные символы в именах файлов, безопасные варианты - xargs -0 или while read -d ''.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
shopt: малоизвестные настройки Bash, которые меняют поведение shellБольшинство пользователей знают про
set -e или set -u, но в Bash есть ещё один мощный инструмент настройки - shopt.С его помощью можно включать и отключать десятки дополнительных возможностей оболочки.
shopt
Или только включённые:shopt -s
globstar - рекурсивный поиск без findПо умолчанию:
ls **/*.log
не сработает.Включаем:
shopt -s globstar
Теперь:ls **/*.log
найдёт все .log-файлы во вложенных каталогах.nullglob - если файлов нетБез этой опции:
for file in *.log; do
echo "$file"
done
выведет:*.log
Вместо пустого списка.Исправляем:
shopt -s nullglob
Теперь цикл просто не выполнится.dotglob - учитывать скрытые файлыПо умолчанию
* не включает файлы, начинающиеся с точки.После:
shopt -s dotglob
они тоже попадут в результат.failglob - защита от опечатокЕсли шаблон не совпал ни с одним файлом:
rm *.bak
с failglob Bash сразу сообщит об ошибке вместо передачи шаблона команде.shopt -s failglob
Это помогает избежать неожиданных сценариев в автоматизации.Несколько опций
shopt способны заметно изменить поведение Bash без переписывания скриптов. Особенно полезны globstar, nullglob и failglob - они делают работу с шаблонами более удобной и предсказуемой.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1