Генерация unit файлов из шаблонов
Если у вас десятки сервисов, работающих по схожей схеме (например, несколько python или node-приложений), руками плодить unit-файлы в
▪️ Простейший шаблон. Создаем
▪️ Генерация через bash
▪️ Массовая генерация из списка. Храним параметры сервисов в CSV:
А bash все развернет:
BashTex📱 #bash #utils
Если у вас десятки сервисов, работающих по схожей схеме (например, несколько python или node-приложений), руками плодить unit-файлы в
/etc/systemd/system - сомнительное удовольствие. Правильнее и логичнее будет автоматизировать путем генерирации юнитов из шаблонов через bash.service.tpl:
[Unit]
Denoscription={{NAME}} service
After=network.target
[Service]
Type=simple
User={{USER}}
WorkingDirectory={{WORKDIR}}
ExecStart={{EXEC}}
Restart=always
[Install]
WantedBy=multi-user.target
#!/bin/bash
set -euo pipefail
TEMPLATE="./service.tpl"
OUTPUT_DIR="/etc/systemd/system"
generate_unit() {
local name="$1" user="$2" workdir="$3" exec="$4"
local outfile="$OUTPUT_DIR/${name}.service"
sed \
-e "s|{{NAME}}|$name|g" \
-e "s|{{USER}}|$user|g" \
-e "s|{{WORKDIR}}|$workdir|g" \
-e "s|{{EXEC}}|$exec|g" \
"$TEMPLATE" > "$outfile"
echo "Сервис $name создан: $outfile"
}
# Пример использования
generate_unit "myapp" "deploy" "/opt/myapp" "/opt/myapp/venv/bin/python app.py"
systemctl daemon-reload
systemctl enable myapp --now
name,user,workdir,exec
app1,deploy,/opt/app1,/opt/app1/start.sh
app2,deploy,/opt/app2,/usr/bin/python3 /opt/app2/run.py
А bash все развернет:
#!/bin/bash
while IFS=, read -r name user workdir exec; do
[[ "$name" == "name" ]] && continue # пропускаем заголовок
generate_unit "$name" "$user" "$workdir" "$exec"
done < services.csv
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🤨1
Резервное копирование Docker volumes без остановки контейнеров
Когда в контейнере крутится прод, остановка ради бэкапа будет невозможной роскошью. Но docker volumes можно сохранять, без остановки, если правильно защититься от: открытых файлов, неконсистентных записей и гонок при чтении.
1️⃣ Проблема горячих бэкапов
Если контейнер пишет в volume во время архивации:
файлы могут быть разорваны,
часть транзакций попадет в архив, а часть нет,
каталог может измениться, пока его читает tar.
Чтобы избежать этого, нужен мягкий снапшот: заморозить структуру, дождаться закрытия файлов и архивировать.
Мы это реализуем через:
проверку открытых дескрипторов lsof
копию структуры через freeze-режим
tar с фиксированным списком файлов
2️⃣ Определяем volume и контейнер
3️⃣ Ждем, пока контейнер перестанет писать. Контейнер может продолжать работать, но нам важно дождаться момента тишины.
Это не блокирует процесс, просто ждёт микропаузу между транзакциями.
4️⃣ Создаем снапшот список файлов
Важно: tar должен использовать фиксированный список, а не динамическое дерево.
Так мы замораживаем текущее состояние структуры.
5️⃣ Архивация без остановки контейнера
Файлы читаются быстрее, чем контейнер успевает их поменять, а вероятность гонки почти нулевая, потому что мы:
дождались отсутствия открытых дескрипторов
зафиксировали список файлов заранее
используем tar с указанием точных путей
6️⃣ Опционально: перезапрос тишины перед чтением больших файлов
Для больших БД/логов:
И внутри цикла архивации:
Это максимально приближает бэкап к снапшот-принципам.
7️⃣ Очистка
8️⃣ Пример полностью готового скрипта. Минимальный файл backup_volume.sh:
BashTex📱 #bash
Когда в контейнере крутится прод, остановка ради бэкапа будет невозможной роскошью. Но docker volumes можно сохранять, без остановки, если правильно защититься от: открытых файлов, неконсистентных записей и гонок при чтении.
Если контейнер пишет в volume во время архивации:
файлы могут быть разорваны,
часть транзакций попадет в архив, а часть нет,
каталог может измениться, пока его читает tar.
Чтобы избежать этого, нужен мягкий снапшот: заморозить структуру, дождаться закрытия файлов и архивировать.
Мы это реализуем через:
проверку открытых дескрипторов lsof
копию структуры через freeze-режим
tar с фиксированным списком файлов
VOLUME="mydata"
BACKUP_DIR="/backups"
STAMP=$(date +%Y%m%d-%H%M)
TARGET="$BACKUP_DIR/$VOLUME-$STAMP.tar.gz"
MOUNTPOINT=$(docker volume inspect "$VOLUME" -f '{{.Mountpoint}}')
wait_until_quiet() {
local path="$1"
local delay=${2:-1}
while lsof +D "$path" >/dev/null 2>&1; do
echo "[*] Volume busy, waiting..."
sleep "$delay"
done
}
Это не блокирует процесс, просто ждёт микропаузу между транзакциями.
Важно: tar должен использовать фиксированный список, а не динамическое дерево.
SNAPLIST=$(mktemp)
find "$MOUNTPOINT" -type f -o -type d | sed "s#^$MOUNTPOINT/##" > "$SNAPLIST"
Так мы замораживаем текущее состояние структуры.
echo "[*] Waiting for files to become quiet..."
wait_until_quiet "$MOUNTPOINT"
echo "[*] Creating hot-backup: $TARGET"
tar -czf "$TARGET" \
-C "$MOUNTPOINT" \
-T "$SNAPLIST"
Файлы читаются быстрее, чем контейнер успевает их поменять, а вероятность гонки почти нулевая, потому что мы:
дождались отсутствия открытых дескрипторов
зафиксировали список файлов заранее
используем tar с указанием точных путей
Для больших БД/логов:
pause_if_lock() {
local file="$1"
while lsof "$file" >/dev/null 2>&1; do
echo "[*] File still in use: $file"
sleep 0.5
done
}
И внутри цикла архивации:
while read -r f; do
pause_if_lock "$MOUNTPOINT/$f"
done < "$SNAPLIST"
Это максимально приближает бэкап к снапшот-принципам.
rm -f "$SNAPLIST"
echo "[+] Backup completed: $TARGET"
#!/usr/bin/env bash
set -euo pipefail
VOLUME="$1"
BACKUP_DIR="/backups"
STAMP=$(date +%Y%m%d-%H%M)
TARGET="$BACKUP_DIR/$VOLUME-$STAMP.tar.gz"
MOUNTPOINT=$(docker volume inspect "$VOLUME" -f '{{.Mountpoint}}')
wait_until_quiet() {
while lsof +D "$1" >/dev/null 2>&1; do
sleep 1
done
}
echo "[*] Volume mountpoint: $MOUNTPOINT"
SNAPLIST=$(mktemp)
find "$MOUNTPOINT" -mindepth 1 -printf '%P\n' > "$SNAPLIST"
echo "[*] Waiting for quiet state..."
wait_until_quiet "$MOUNTPOINT"
echo "[*] Archiving..."
tar -czf "$TARGET" -C "$MOUNTPOINT" -T "$SNAPLIST"
rm -f "$SNAPLIST"
echo "[+] Done: $TARGET"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14
Сбор данных с нескольких серверов
Конструкция позволяет сравнивать состояние двух (или нескольких) машин без временных файлов, параллельно и максимально быстро.
Process substitution создает виртуальные файлы, в которые пишется вывод команд. SSH-запросы выполняются параллельно, а diff думает, что сравнивает два обычных файла:
▪️ Лучшие практические примеры
▪️ Сравнение пакетов
▪️ Конфиги (sshd_config)
▪️ Сетевые соединения
▪️ Docker-контейнеры
▪️ Мини-функция
Использование:
BashTex📱 #bash #utils
<(ssh host1 cmd) vs <(ssh host2 cmd)
Конструкция позволяет сравнивать состояние двух (или нескольких) машин без временных файлов, параллельно и максимально быстро.
Process substitution создает виртуальные файлы, в которые пишется вывод команд. SSH-запросы выполняются параллельно, а diff думает, что сравнивает два обычных файла:
diff <(ssh h1 cmd) <(ssh h2 cmd)
diff <(ssh h1 "dpkg -l | sort") \
<(ssh h2 "dpkg -l | sort")
diff -u <(ssh h1 "grep -v '^#' /etc/ssh/sshd_config") \
<(ssh h2 "grep -v '^#' /etc/ssh/sshd_config")
diff <(ssh h1 "ss -tuna | sort") \
<(ssh h2 "ss -tuna | sort")
diff <(ssh h1 "docker ps --format '{{.Names}} {{.Image}}' | sort") \
<(ssh h2 "docker ps --format '{{.Names}} {{.Image}}' | sort")
compare_hosts() {
diff <(ssh "$1" "$3") <(ssh "$2" "$3")
}
Использование:
compare_hosts node1 node2 "df -h"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Сравнение authorized_keys между серверами
Когда в кластере несколько серверов, важно, чтобы доступ имели одни и те же пользователи с одинаковыми ключами. Несогласованность в authorized_keys будет частой точка входа для проблем.
▪️ Базовый прием: сравнение двух серверов
Сразу видно какие ключи есть только на h1 и какие есть только на h2. Строки отличаются полностью, поэтому легко понять лишние.
▪️ Сравнение директорий для всех пользователей
Использование:
▪️ Мультисерверная проверка списка хостов
Покажет отличия между эталоном и всеми остальными.
▪️ Поиск лишних ключей
Покажет ключи, присутствующие только на h1.
BashTex📱 #bash #utils
Когда в кластере несколько серверов, важно, чтобы доступ имели одни и те же пользователи с одинаковыми ключами. Несогласованность в authorized_keys будет частой точка входа для проблем.
diff <(ssh h1 "sort ~/.ssh/authorized_keys") \
<(ssh h2 "sort ~/.ssh/authorized_keys")
Сразу видно какие ключи есть только на h1 и какие есть только на h2. Строки отличаются полностью, поэтому легко понять лишние.
compare_keys() {
user="$1"
diff <(ssh "$2" "sort /home/$user/.ssh/authorized_keys 2>/dev/null") \
<(ssh "$3" "sort /home/$user/.ssh/authorized_keys 2>/dev/null")
}
Использование:
compare_keys deploy h1 h2
compare_keys admin h1 h2
hosts=(h1 h2 h3)
base="h1"
for h in "${hosts[@]:1}"; do
echo "=== $base vs $h ==="
diff <(ssh "$base" "sort ~/.ssh/authorized_keys") \
<(ssh "$h" "sort ~/.ssh/authorized_keys")
done
Покажет отличия между эталоном и всеми остальными.
ssh h1 "sort ~/.ssh/authorized_keys" \
| grep -vFf <(ssh h2 "sort ~/.ssh/authorized_keys")
Покажет ключи, присутствующие только на h1.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Сложные пайпы в bash
Иногда нужно одновременно: подавать данные в программу, анализировать ее вывод, логировать поток, фильтровать часть данных и все это без временных файлов. Такое легко делается через tee + process substitution.
▪️ Базовый шаблон
и при этом нет temp-файлов, все идёт по fd
▪️ Пример 1: анализ, логирование и фильтрация сразу. Извлекаем ошибки в отдельный файл, а общий вывод обрабатываем:
▪️ Пример 2: split-поток для алертов и статистики
▪️ Пример 3: читаем и пишем в интерактивный процесс. Двунаправленная работа с программой:
Работает как мини-оркестратор для интерактивного ввода/вывода.
BashTex📱 #bash #utils
Иногда нужно одновременно: подавать данные в программу, анализировать ее вывод, логировать поток, фильтровать часть данных и все это без временных файлов. Такое легко делается через tee + process substitution.
cat input.log \
| cmd \
| tee >(grep "ERROR" > errors.log) \
| awk '{print $1, $3}'
cmd принимает stdin от cat;tee дублирует поток: в файл-поток >(grep ...) и дальше в awk;grep работает параллельно, не мешая основному пайпу;и при этом нет temp-файлов, все идёт по fd
journalctl -u nginx \
| tee >(grep 500 >500.log) \
| awk '/request/ {print $NF}'
tail -F app.log \
| tee >(grep CRITICAL | notify-send "ALERT!") \
| awk '{count[$5]++} END {for (i in count) print i, count[i]}'
coproc APP { cmd --interactive; }
echo "status" >&"${APP[1]}"
cat <&"${APP[0]}" \
| tee >(grep ALERT >alerts.log) \
| awk '{print "OUT:", $0}'
Работает как мини-оркестратор для интерактивного ввода/вывода.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Использование socat как универсального канала между скриптами
▪️ Bash через UNIX-сокет. Мини-IPC без tmp-файлов и named pipes:
Сервер:
Клиент:
Отлично подходит для локальных API между скриптами.
2️⃣ Передача данных между серверами (TCP)
Сервер:
Клиент:
Можно в реальном времени стримить логи или метрики.
3️⃣ Замена сложных пайпов. Напрямую соединяем процессы, даже если они не умеют работать с stdin/stdout:
Аналог cmd1 | cmd2, но без ограничений пайпа (например, поддержка bidirectional).
4️⃣ Двунаправленный канал в скрипте. Например, общение с интерактивным сервисом:
Можно строить собственные протоколы поверх TCP.
5️⃣ Быстрый импровизированный RPC
Сервер:
Клиент:
BashTex📱 #bash #utils
socat позволяет связать любой источник данных с любым приемником. Bash-скрипты с ним превращаются в гибкие системы обмена сообщениями.Сервер:
socat UNIX-LISTEN:/tmp/app.sock,fork SYSTEM:'bash handler.sh'
Клиент:
echo "PING" | socat - UNIX-CONNECT:/tmp/app.sock
Отлично подходит для локальных API между скриптами.
Сервер:
socat TCP-LISTEN:9000,fork FILE:/var/log/app.log
Клиент:
socat - TCP:server:9000
Можно в реальном времени стримить логи или метрики.
socat EXEC:"cmd1" EXEC:"cmd2"
Аналог cmd1 | cmd2, но без ограничений пайпа (например, поддержка bidirectional).
socat - TCP:localhost:8080 | while read l; do
echo ">> $l"
done
Можно строить собственные протоколы поверх TCP.
Сервер:
socat TCP-LISTEN:7000,reuseaddr,fork SYSTEM:'bash rpc-handler.sh'
Клиент:
echo '{"cmd":"status"}' | socat - TCP:host:7000
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2
Распределенный журнал событий через SSH fan-out
Иногда нужно собрать события с группы серверов и посмотреть их как единый хронологический поток: кто что делал, когда, и на каком хосте. Можно сделать это чисто на bash + SSH.
Для этого:
По SSH запускаем команду на каждом сервере (journalctl, tail, свой лог).
Добавляем timestamp + hostname.
Объединяем и сортируем и получаем общий timeline.
▪️ Fan-out по серверам
▪️ Централизованное объединение и сортировка
Теперь
BashTex📱 #bash
Иногда нужно собрать события с группы серверов и посмотреть их как единый хронологический поток: кто что делал, когда, и на каком хосте. Можно сделать это чисто на bash + SSH.
Для этого:
По SSH запускаем команду на каждом сервере (journalctl, tail, свой лог).
Добавляем timestamp + hostname.
Объединяем и сортируем и получаем общий timeline.
HOSTS=(srv1 srv2 srv3)
for h in "${HOSTS[@]}"; do
ssh "$h" "journalctl -n 50 --no-pager" | \
awk -v host="$h" '{print strftime("%s"), host, $0}' &
done
wait
{
for h in "${HOSTS[@]}"; do
ssh "$h" "journalctl -n 200 --no-pager" \
| awk -v host="$h" '{print strftime("%s"), host, $0}'
done
} | sort -n > timeline.log
Теперь
timeline.log выглядит так:
1712409123 srv1 sshd[1023]: Accepted password for admin
1712409124 srv3 systemd[1]: Started backup.
1712409125 srv2 docker[532]: Container restarted.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20👍2
Ротация директорий
Когда нужно хранить несколько срезов состояния проекта или конфигов, удобно использовать ротацию директорий. Это быстрый, прозрачный и полностью файловый способ отката.
Предположим, у нас есть рабочая директория
Ротация выглядит так:
snapshot2 ← snapshot1 ← current
🛠 Скрипт ротации
➕ Преимущества
можно открыть любой снапшот обычным
откат в 1 команду:
работает для конфигов, кода и сервисов.
BashTex📱 #bash
Когда нужно хранить несколько срезов состояния проекта или конфигов, удобно использовать ротацию директорий. Это быстрый, прозрачный и полностью файловый способ отката.
Предположим, у нас есть рабочая директория
current/ и несколько ее копий:snapshot1/ - свежий слепокsnapshot2/ - предыдущийlast-good/ - стабильная проверенная версияРотация выглядит так:
snapshot2 ← snapshot1 ← current
BASE="/opt/myapp"
rotate() {
cd "$BASE" || exit 1
rm -rf snapshot2
mv snapshot1 snapshot2 2>/dev/null || true
cp -a current snapshot1
# Обновление last-good, если тесты прошли
if bash run_tests.sh; then
rm -rf last-good
cp -a current last-good
fi
}
rotate
cp -a быстрее архивации;можно открыть любой снапшот обычным
ls/cd;откат в 1 команду:
cp -a last-good currentработает для конфигов, кода и сервисов.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Параллельный запуск задач с приоритетами
Когда нужно запускать много задач, но с разным приоритетом и контролем конкуренции, можно собрать простой планировщик задач. Мы создаем: очереди: high/, normal/, low/, локи для избежания гонок, запуск задач через nice - приоритеты ядра и минимальный воркер, который берет задачи по порядку.
▪️ Структура:
▪️ Воркер:
▪️ Добавление задачи:
▪️ Что это дает?
- Параллельные воркеры (запусти несколько экземпляров)
- Приоритеты через nice
- Исключение гонок через простые файловые lock-и
- Очередь можно смотреть, чистить, дебажить обычными инструментами
BashTex📱 #bash
Когда нужно запускать много задач, но с разным приоритетом и контролем конкуренции, можно собрать простой планировщик задач. Мы создаем: очереди: high/, normal/, low/, локи для избежания гонок, запуск задач через nice - приоритеты ядра и минимальный воркер, который берет задачи по порядку.
queue/
high/
normal/
low/
locks/
pick_task() {
for q in high normal low; do
t=$(ls queue/$q | head -n1 2>/dev/null)
[ -n "$t" ] && echo "$q/$t" && return
done
}
run() {
while true; do
task=$(pick_task)
[ -z "$task" ] && sleep 1 && continue
lock="locks/$(basename "$task").lock"
( set -o noclobber; >"$lock" ) 2>/dev/null || continue
cmd=$(cat "queue/$task")
rm "queue/$task"
case $task in
high/*) nice -n -10 bash -c "$cmd" ;;
normal/*) nice -n 0 bash -c "$cmd" ;;
low/*) nice -n 10 bash -c "$cmd" ;;
esac
rm -f "$lock"
done
}
run
echo "sleep 3 && echo DONE" > queue/high/job1
- Параллельные воркеры (запусти несколько экземпляров)
- Приоритеты через nice
- Исключение гонок через простые файловые lock-и
- Очередь можно смотреть, чистить, дебажить обычными инструментами
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Автопоиск подвисших сетевых соединений и перезапуск сервисов
Если сервис начинает подвисать, это часто видно по сети: соединения зависают в SYN-SENT, CLOSE-WAIT или сидят в одном состоянии слишком долго. Это можно определить прямо в bash, без netstat/ss.
1️⃣ Читаем таблицу соединений из /proc/net/tcp
Мы будем искать ошибочные или зависшие состояния.
2️⃣ Привязка inode к PID процесса. Каждый сокет отображается как
3️⃣ Перезапуск сервиса
▪️ Получаем:
- Автоматический поиск зависших TCP-соединений;
- Связь сокета с реальным процессом;
- Перезапуск только нужного сервиса;
Такой подход полезен для nginx, API-сервисов, баз данных и любых демонов, которые иногда залипают в сетевых состояниях.
BashTex📱 #bash #utils
Если сервис начинает подвисать, это часто видно по сети: соединения зависают в SYN-SENT, CLOSE-WAIT или сидят в одном состоянии слишком долго. Это можно определить прямо в bash, без netstat/ss.
Формат /proc/net/tcp содержит:
local addr/port
remote addr/port
state
inode (ключ!)
Мы будем искать ошибочные или зависшие состояния.
grep -E "$(echo $hung_states | sed 's/ /|/g')" /proc/net/tcp |
while read -r _ _ _ state _ _ _ _ inode _; do
echo "$inode"
done
/proc/$pid/fd/* → socket:[inode].
find_pid_by_inode() {
inode=$1
for p in /proc/[0-9]*/fd/*; do
if readlink "$p" 2>/dev/null | grep -q "socket:\[$inode\]"; then
echo "$p" | cut -d/ -f3
fi
done
}
for inode in $(get_hung_inodes); do
pid=$(find_pid_by_inode "$inode")
svc=$(ps -p "$pid" -o comm=)
echo "Hung socket in PID $pid ($svc)"
case "$svc" in
nginx) systemctl restart nginx ;;
sshd) systemctl restart sshd ;;
myapp) systemctl restart myapp ;;
esac
done
- Автоматический поиск зависших TCP-соединений;
- Связь сокета с реальным процессом;
- Перезапуск только нужного сервиса;
Такой подход полезен для nginx, API-сервисов, баз данных и любых демонов, которые иногда залипают в сетевых состояниях.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
This media is not supported in your browser
VIEW IN TELEGRAM
Я думаю, что все устали и всем пора отдыхать, набираться сил. Все дедлайны позади, а о будущих думать пока не стоит!
Я пожелаю Вам хороших каникул, счастья, здоровья, поменьше выгорания и успехов в новом году!
С наступающим, 2026!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🫡2
Многоуровневый логинг
Большинство скриптов просто пишут все в stdout или stderr. Но bash позволяет делать полноценный логгер, разделяя потоки по уровням и управлять ими динамически во время выполнения.
Для этого, выделяем отдельные файловые дескрипторы:
3> - INFO
4> - DEBUG
5> - ERROR
Каждый можно направить в свой файл или устройство.
▪️ Базовая инициализация логгеров
▪️ Лог-функции с проверкой уровня
▪️ Быстрое переключение уровня. Прямо в процессе выполнения можно менять уровень логов:
▪️ Перенаправление в консоль при необходимости. Например, показывать ERROR сразу на экране:
Или дебаг-режим в реальном времени:
BashTex📱 #bash #utils
Большинство скриптов просто пишут все в stdout или stderr. Но bash позволяет делать полноценный логгер, разделяя потоки по уровням и управлять ими динамически во время выполнения.
Для этого, выделяем отдельные файловые дескрипторы:
3> - INFO
4> - DEBUG
5> - ERROR
Каждый можно направить в свой файл или устройство.
LOGLEVEL="info" # debug|info|error
exec 3>info.log
exec 4>debug.log
exec 5>error.log
log_info() { [[ $LOGLEVEL =~ info|debug ]] && echo "[INFO] $*" >&3; }
log_debug() { [[ $LOGLEVEL == debug ]] && echo "[DEBUG] $*" >&4; }
log_error() { echo "[ERROR] $*" >&5; }
set_loglevel() {
LOGLEVEL="$1"
log_info "Loglevel switched to: $LOGLEVEL"
}
# Пример:
set_loglevel debug
exec 5> >(tee -a error.log >&2)
Или дебаг-режим в реальном времени:
exec 4> >(sed 's/^/[DBG]/' >&2)
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Bash-аналитика для iptables/nftables
Большинство сетевых политик обрастает десятками правил, но какие из них реально срабатывают, а какие просто мертвый груз? Разберемся и составим набор команд.
1️⃣ Статистика хитов iptables.
Поле
Мини-скрипт для выборки топ-работающих правил:
Покажет самые горячие правила.
2️⃣ nftables: счетчики + export
Bash-анализ:
3️⃣ Агрегация логов, какие действия реально происходят. Многие правила пишут в syslog (
Покажет, что именно чаще всего логирует firewall.
4️⃣ Комбинированный отчет
Такой небольшой пакет дает:
топ реальных срабатываний правил,
статистику нагрузочных цепочек,
понимание, что стоит оптимизировать или удалить.
BashTex📱 #bash #utils
Большинство сетевых политик обрастает десятками правил, но какие из них реально срабатывают, а какие просто мертвый груз? Разберемся и составим набор команд.
iptables хранит счетчики прямо в правилах:
iptables -L INPUT -v -n
Поле
pkts/bytes - это наши хиты.Мини-скрипт для выборки топ-работающих правил:
iptables -L INPUT -v -n \
| awk '/ACCEPT|DROP/ {printf "%10s %s\n", $1, $0}' \
| sort -nr
Покажет самые горячие правила.
nft list ruleset | grep -A1 'counter'
Bash-анализ:
nft list ruleset \
| awk '/counter/ {print $2, $3}' \
| sort -nr
LOG prefix "iptables-"). Вытащим статистику по префиксам:
grep "iptables-" /var/log/syslog \
| awk '{print $NF}' \
| sort | uniq -c | sort -nr
Покажет, что именно чаще всего логирует firewall.
echo "[HIT COUNTERS]"
iptables -L INPUT -v -n | awk '/ACCEPT|DROP/ {print $1, $0}' | sort -nr | head
echo "[LOG EVENTS]"
grep "iptables-" /var/log/syslog | awk '{print $NF}' \
| sort | uniq -c | sort -nr | head
Такой небольшой пакет дает:
топ реальных срабатываний правил,
статистику нагрузочных цепочек,
понимание, что стоит оптимизировать или удалить.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Оптимизация скорости загрузки сервера
Как находить медленные юниты, диагностировать зависшие цепочки и исправлять задержки
1️⃣ Кто тормозит: анализ времени запуска.
2️⃣ Поиск узкого места: критическая цепочка зависимостей. Если юнит стартует быстро, но висит в конце загрузки, то он блокирует чей-то старт или ждет зависимость. Нужно увидеть цепочку задержек:
3️⃣ Устраняем задержку через override. Правильный способ настроить юнит - это не менять оригинальный файл, а создать override:
В открывшийся файл:
Применяем изменения:
Корректируем цепочку зависимостей, чтобы Docker не ждал медленных сетевых юнитов.
BashTex📱 #bash #utils
Как находить медленные юниты, диагностировать зависшие цепочки и исправлять задержки
systemd-analyze blame показывает, какие юниты стартуют дольше всех, базовый шаг в поиске проблем.
systemd-analyze blame
systemd-analyze critical-chain
sudo systemctl edit docker.service
В открывшийся файл:
[Unit]
After=network.target
Wants=network.target
Применяем изменения:
sudo systemctl daemon-reload
sudo systemctl restart docker
Корректируем цепочку зависимостей, чтобы Docker не ждал медленных сетевых юнитов.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Отслеживание активности пользователей
Linux хранит всю историю входов в три системные базы:
lastlog - последний логин каждого пользователя
utmp - текущие активные сессии
wtmp - история всех логинов/логаутов
Вот короткий набор инструментов, позволяющий получить максимум информации.
1️⃣ Последние входы всех пользователей (lastlog). Показать, кто реально входит в систему:
Фильтр подозрительно старых аккаунтов:
2️⃣ Активные сессии прямо сейчас
С IP, временем и TTY:
Выделение пользователей с нестандартных подсетей:
3️⃣ История всех входов/выходов
Кто заходил чаще всего:
Только удаленные логины:
4️⃣ Комбинированный отчет
BashTex📱 #bash #utils
Linux хранит всю историю входов в три системные базы:
lastlog - последний логин каждого пользователя
utmp - текущие активные сессии
wtmp - история всех логинов/логаутов
Вот короткий набор инструментов, позволяющий получить максимум информации.
lastlog | grep -v "Never logged in"
Фильтр подозрительно старых аккаунтов:
lastlog | awk '$4 ~ /Jan|Feb|Mar|Apr/ && $NF != "**Never**"'
who
С IP, временем и TTY:
who --ips
Выделение пользователей с нестандартных подсетей:
who --ips | awk '$5 !~ /^10\.|^192\.168\./'
last -F
Кто заходил чаще всего:
last | awk '{print $1}' | sort | uniq -c | sort -nr | head
Только удаленные логины:
last | grep -E "pts/[0-9]"
echo "[ACTIVE SESSIONS]"; who --ips
echo "[LAST LOGINS]"; lastlog | grep -v "Never"
echo "[TOP USERS]"; last | awk '{print $1}' | sort | uniq -c | sort -nr | head
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
Обработка SSH-команд через connection pooling
Если вам нужно выполнить десятки или сотни SSH-команд подряд, стандартный подход ssh host cmd превращается в ад: каждый вызов открывает новое TCP-соединение, делает handshake, обмен ключами, проверку known_hosts и все это ради одной короткой команды. Но SSH умеет работать совершенно иначе, через
▪️ Включаем connection pooling. Создаем master-socket:
Теперь вторичные команды идут через master:
Все эти вызовы выполняются почти мгновенно.
▪️ Автоматизация: ~/.ssh/config. Чтобы не писать все вручную:
Теперь SSH сам создает и держит мастер-сессию 10 минут после последней команды.
▪️ Массовый запуск команд по списку
▪️ Завершение мастер-сессии
BashTex📱 #bash #utils
Если вам нужно выполнить десятки или сотни SSH-команд подряд, стандартный подход ssh host cmd превращается в ад: каждый вызов открывает новое TCP-соединение, делает handshake, обмен ключами, проверку known_hosts и все это ради одной короткой команды. Но SSH умеет работать совершенно иначе, через
multiplexing. Это когда одно физическое SSH-соединение становится трубой для десятков логических каналов. Команды выполняются без задержек, почти как локальные.
ssh -M -S /tmp/ssh-sock-%r@%h:%p user@server
-M - включить master-режим,-S - путь до сокета.Теперь вторичные команды идут через master:
ssh -S /tmp/ssh-sock-%r@%h:%p user@server "hostname"
ssh -S /tmp/ssh-sock-%r@%h:%p user@server "uptime"
ssh -S /tmp/ssh-sock-%r@%h:%p user@server "df -h"
Все эти вызовы выполняются почти мгновенно.
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
Теперь SSH сам создает и держит мастер-сессию 10 минут после последней команды.
#!/bin/bash
for host in $(cat hosts.txt); do
ssh "$host" "uptime" &
done
wait
ssh -O exit -S ~/.ssh/cm-user@host:22 host
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Работа с архивами без распаковки
Распаковывать архив, чтобы посмотреть один файл - долго, неудобно и занимает место. К тому же большинство форматов позволяют работать прямо по месту.
1️⃣ Просмотр содержимого
2️⃣ Grep внутри архива (без извлечения)
tar позволяет выводить файлы в stdout, можно grep через pipe:
Или искать по всем файлам:
zip не умеет прямой потоковой выдачи всех файлов, но может вывести один:
7z (лучший вариант для grep по всем файлам)
Или по конкретному файлу:
3️⃣ Поиск файла по части имени
BashTex📱 #bash
Распаковывать архив, чтобы посмотреть один файл - долго, неудобно и занимает место. К тому же большинство форматов позволяют работать прямо по месту.
tar -tf archive.tar.gz # tar
unzip -l archive.zip # zip
7z l archive.7z # 7z
tar позволяет выводить файлы в stdout, можно grep через pipe:
tar -xOf archive.tar.gz path/to/file.txt | grep "ERROR"
Или искать по всем файлам:
tar -xOf archive.tar.gz $(tar -tf archive.tar.gz) | grep "pattern"
zip не умеет прямой потоковой выдачи всех файлов, но может вывести один:
unzip -p archive.zip logs/app.log | grep "WARN"
7z (лучший вариант для grep по всем файлам)
7z x -so archive.7z | grep "pattern"
Или по конкретному файлу:
7z x archive.7z -so -i!*.log | grep "ERROR"
7z l archive.7z | grep "\.conf"
tar -tf backup.tar | grep "nginx"
unzip -l logs.zip | grep ".log"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Автоматическая синхронизация каталогов по списку хостов
Когда один и тот же каталог нужно поддерживать в актуальном состоянии на нескольких серверах, самый простой инструмент:
▪️ Простой пример: синхронизация по списку хостов. Допустим, есть файл
🛠 Скрипт:
Скрипт:
Синхронизирует каталог на каждый хост;
Удаляет лишние файлы (
Передает только изменения (
Работает со сколько угодно хостами записанными в
▪️ Плюс: можно добавить контроль доступности
BashTex📱 #bash
Когда один и тот же каталог нужно поддерживать в актуальном состоянии на нескольких серверах, самый простой инструмент:
rsync. Но руками гонять его по каждому хосту - это боль. Можно написать маленький скрипт, который делает это автоматически.hosts.txt:
srv1
srv2
srv3
#!/usr/bin/env bash
SRC="/opt/app/"
DEST="/opt/app/"
HOSTS="hosts.txt"
for host in $(cat "$HOSTS"); do
echo "[*] Sync to $host..."
rsync -az --delete "$SRC" "$host:$DEST"
done
Скрипт:
Синхронизирует каталог на каждый хост;
Удаляет лишние файлы (
--delete);Передает только изменения (
-a + -z);Работает со сколько угодно хостами записанными в
hosts.txt
ping -c1 -W1 "$host" >/dev/null || {
echo "$host недоступен, пропускаю"
continue
}
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10