Автоматическая синхронизация каталогов по списку хостов
Когда один и тот же каталог нужно поддерживать в актуальном состоянии на нескольких серверах, самый простой инструмент:
▪️ Простой пример: синхронизация по списку хостов. Допустим, есть файл
🛠 Скрипт:
Скрипт:
Синхронизирует каталог на каждый хост;
Удаляет лишние файлы (
Передает только изменения (
Работает со сколько угодно хостами записанными в
▪️ Плюс: можно добавить контроль доступности
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
Проверка слабых паролей пользователей
Важно понимать: мы не проверяем сами пароли и не подбираем их. Мы только выявляем пользователей, у кого высокий риск слабого пароля, анализируя политики и метаданные.
▪️ Что можно проверить
Возраст пароля, если пароль не меняли 500+ дней - тревожный знак;
Минимальный и максимальный срок действия (политики
Пользователи с never expires, часто признак устаревших или слабозащищенных аккаунтов;
Аккаунты с неограниченным логином (
🛠 Скрипт
▪️ Чтение результатов
BashTex📱 #bash
Важно понимать: мы не проверяем сами пароли и не подбираем их. Мы только выявляем пользователей, у кого высокий риск слабого пароля, анализируя политики и метаданные.
Возраст пароля, если пароль не меняли 500+ дней - тревожный знак;
Минимальный и максимальный срок действия (политики
PASS_MAX_DAYS);Пользователи с never expires, часто признак устаревших или слабозащищенных аккаунтов;
Аккаунты с неограниченным логином (
chage -l).
#!/usr/bin/env bash
echo "user,last_change,max_days,warning,expires"
for user in $(cut -d: -f1 /etc/shadow); do
info=$(chage -l "$user" 2>/dev/null)
last_change=$(echo "$info" | grep "Last password change" | cut -d: -f2 | xargs)
max_days=$(echo "$info" | grep "Maximum" | awk '{print $4}')
warning=$(echo "$info" | grep "Warning" | awk '{print $4}')
expires=$(echo "$info" | grep "Password expires" | cut -d: -f2 | xargs)
echo "$user,$last_change,$max_days,$warning,$expires"
done
max_days = 99999 - это значит, что политика отсутствует, пароль вечныйexpires = never означает, что аккаунт может быть заброшенным или небезопаснымlast_change слишком старый - стоит пройтись по пользователям и потребовать сменыBashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Как находить зависшие задачи запущенные cron
Зависшие cron-задачи - это классика: скрипт повис в I/O, процесс ждет лок, завис ssh и сервер уже не делает регулярные бэкапы, не чистит кеши и не обновляет индексы. Но поймать такие случаи можно и нужно, я расскажу про самый простой способ: cron запускает процессы с PPID = PID cron’а или запускает их в окружении cron. Мы можем искать процессы, запущенные с COMMAND и PPID, и проверять их время жизни.
🛠 Скрипт
▪️ Настройка
Поставьте
Добавьте скрипт в
BashTex📱 #bash
Зависшие cron-задачи - это классика: скрипт повис в I/O, процесс ждет лок, завис ssh и сервер уже не делает регулярные бэкапы, не чистит кеши и не обновляет индексы. Но поймать такие случаи можно и нужно, я расскажу про самый простой способ: cron запускает процессы с PPID = PID cron’а или запускает их в окружении cron. Мы можем искать процессы, запущенные с COMMAND и PPID, и проверять их время жизни.
#!/usr/bin/env bash
# Максимальное время выполнения задачи (в секундах)
MAX=1800 # 30 минут
now=$(date +%s)
# Ищем процессы, которые запустил cron
ps -eo pid,ppid,etimes,cmd | grep -v grep | while read pid ppid et cmd; do
# ppid == 1 и команды в /etc/cron* — частый кейс
if [[ "$ppid" -eq 1 && "$cmd" == *cron* ]]; then
continue
fi
# Задачи cron обычно запускаются как sh -c "..."
if [[ "$cmd" == *"/etc/cron"* || "$cmd" == *"CRON"* ]]; then
if (( et > MAX )); then
echo "Зависшая задача: PID=$pid, работает уже ${et}s"
fi
fi
done
Поставьте
MAX под вашу норму времени выполнения задач.Добавьте скрипт в
/etc/cron.hourly - будете получать регулярный отчет.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Массовое переименование файлов по шаблону
▪️ Вариант 1: rename. Если нужно заменить часть имени:
Удалить префикс:
Добавить суффикс перед расширением:
▪️ Вариант 2: sed + цикл. Когда шаблон сложный или нужно сгенерировать новое имя:
Можно применять любую логику, хоть разбивать строку на части.
▪️ Вариант 3: Bash expansion. Если у файлов есть общий номер или маска:
Переименование 01 в 001:
⚠️ Совет: Перед
Если вывод выглядит правильно, то можно убирать
BashTex📱 #bash
# Заменить "old" на "new" во всех именах
rename 's/old/new/' *.txt
Удалить префикс:
rename 's/^prefix_//' *.log
Добавить суффикс перед расширением:
rename 's/\.jpg$/_edited.jpg/' *.jpg
for f in *.mp4; do
new=$(echo "$f" | sed 's/episode_/ep-/; s/_final//')
mv "$f" "$new"
done
Можно применять любую логику, хоть разбивать строку на части.
# Добавить нумерацию
n=1
for f in *.png; do
mv "$f" "img_$(printf "%03d" $n).png"
((n++))
done
Переименование 01 в 001:
for f in *.txt; do
mv "$f" "$(printf "%03d".txt "${f%.txt}")"
done
mv всегда смотрите, что получится:
for f in *.txt; do
echo mv "$f" "new-$f"
done
Если вывод выглядит правильно, то можно убирать
echo.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Проверка целостности системных пакетов через пакетный менеджер
Если есть подозрение на вмешательство в систему: подмену бинарников, изменение конфигов, в таком случае первым делом стоит проверить: файлы пакетов соответствуют тому, что установлено из репозиториев?
Linux-дистрибутивы уже умеют делать это штатно. Нужно только правильно спросить.
▪️ RPM-базовые системы (CentOS, RHEL, Rocky, Fedora). Команда:
Формат вывода:
Чтобы увидеть только реальные расхождения, можно отфильтровать шум:
▪️ Debian/Ubuntu: debsums. Если система на DEB-пакетах:
Проверка конкретного пакета:
BashTex📱 #bash #security
Если есть подозрение на вмешательство в систему: подмену бинарников, изменение конфигов, в таком случае первым делом стоит проверить: файлы пакетов соответствуют тому, что установлено из репозиториев?
Linux-дистрибутивы уже умеют делать это штатно. Нужно только правильно спросить.
sudo rpm -Va
Она проверяет все файлы всех пакетов, сверяя:
размер
хеш
права
владельца
время модификации
Формат вывода:
S.5....T. /usr/bin/ssh
Где:S- размер отличается5- хеш не совпадаетT- время модификации изменено
Чтобы увидеть только реальные расхождения, можно отфильтровать шум:
sudo rpm -Va | grep -v '^..c'
..c - это конфиги, которые обычно меняются вручную.
sudo apt install debsums
sudo debsums -s
-s выводит только файлы, чьи MD5-суммы не совпадают с эталоном из репозитория.Проверка конкретного пакета:
sudo debsums -s openssh-server
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
Живой мониторинг процессов с цветом и сортировкой
watch - недооцененный инструмент. Он превращает любую команду в живую панель наблюдения, обновляя вывод каждые N секунд. Если добавить цвет, сортировку и фильтры у вас получается почти мини
▪️ Базовый пример: отслеживание топ-процессов
▪️ Цветной вывод внутри watch. Если команда выводит ANSI-цвета, watch их покажет, но нужно включить
Или:
▪️ Подсветка подозрительных процессов. Например, ищем процессы, использующие много памяти (>10%):
Процессы >10% MEM подсвечиваются красным.
▪️ Отслеживание процессов конкретного пользователя
▪️ Комбинация watch + pgrep. Смотрим, что делает группа процессов по паттерну:
▪️ Небольшой дашборд: несколько метрик за раз (через bash -c)
BashTex📱 #bash #utils
watch - недооцененный инструмент. Он превращает любую команду в живую панель наблюдения, обновляя вывод каждые N секунд. Если добавить цвет, сортировку и фильтры у вас получается почти мини
htop без внешних утилит.
watch -n 1 'ps aux --sort=-%cpu | head -20'
-n 1- обновление каждую секунду--sort=-%cpu- сортировка по нагрузкеhead -20- только важные строки
-c:
watch -c 'ps aux | grep --color=always nginx'
Или:
watch -c 'ps aux --sort=-%mem | head -15'
watch -n 1 -c '
ps aux --sort=-%mem \
| awk '\''$4>10{print "\033[31m"$0"\033[0m"} $4<=10{print}'\'''
Процессы >10% MEM подсвечиваются красным.
watch 'ps -u deploy --sort=-%cpu | head'
watch 'pgrep -fl python | sort'
watch -n 2 -c '
echo "== CPU =="; ps aux --sort=-%cpu | head -5;
echo "";
echo "== MEM =="; ps aux --sort=-%mem | head -5;
'
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁15
🔧 Для системных администраторов и IT-специалистов!
Ищете надежный источник знаний и поддержки? Тогда вам к нам!
📚 Что у нас есть:
- Книги по Cisco Systems, Mikrotik, VoIP, Linux и Windows Server
- Руководства по сетевым технологиям
- 📽 Видеоуроки на актуальные темы
- 🤝 Поддержка от сообщества
Присоединяйтесь к нашему сообществу профессионалов: @sysadmin1
Ищете надежный источник знаний и поддержки? Тогда вам к нам!
📚 Что у нас есть:
- Книги по Cisco Systems, Mikrotik, VoIP, Linux и Windows Server
- Руководства по сетевым технологиям
- 📽 Видеоуроки на актуальные темы
- 🤝 Поддержка от сообщества
Присоединяйтесь к нашему сообществу профессионалов: @sysadmin1
🔥1
Проверка доступности сервисов с автоперезапуском
Иногда нужен не Zabbix, а простейший контроль жив или нет. Для HTTP-сервисов это легко решается связкой
▪️ Базовая проверка доступности
-s - тихо
-f - ошибка, если HTTP ≠ 2xx
exit-код ≠ 0 - сервис недоступен
▪️ Автоперезапуск сервиса
▪️ Защита от флаппинга (несколько неудач подряд)
Рестарт только если сервис падает несколько раз подряд.
▪️ Запуск по cron
BashTex📱 #bash #utils
Иногда нужен не Zabbix, а простейший контроль жив или нет. Для HTTP-сервисов это легко решается связкой
curl + systemctl.
curl -sf http://127.0.0.1:8080/health || echo "DOWN"
-s - тихо
-f - ошибка, если HTTP ≠ 2xx
exit-код ≠ 0 - сервис недоступен
SERVICE=myapp
URL=http://127.0.0.1:8080/health
if ! curl -sf --max-time 3 "$URL"; then
logger "watchdog: $SERVICE is down, restarting"
systemctl restart "$SERVICE"
fi
--max-time защищает от зависших запросовlogger пишет в syslog (удобно для аудита)
FAILS=/run/myapp.watchdog.fail
MAX=3
if ! curl -sf "$URL"; then
n=$(($(cat "$FAILS" 2>/dev/null || echo 0)+1))
echo "$n" > "$FAILS"
[[ $n -ge $MAX ]] && systemctl restart "$SERVICE"
else
rm -f "$FAILS"
fi
Рестарт только если сервис падает несколько раз подряд.
*/1 * * * * /usr/local/bin/watchdog.sh
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Быстрый сбор системной информации одной командой
Когда нужно быстро понять, что за система перед тобой, без Ansible и inventory - достаточно одного короткого скрипта.
🛠 Мини-инвентаризация за один запуск
▪️ Компактный вариант в одну строку
Удобно кидать в чат или запускать на десятках хостов по SSH.
▪️ Формат для логов/отчетов
Можно сохранять как снапшот состояния перед деплоем или обновлением.
BashTex📱 #bash
Когда нужно быстро понять, что за система перед тобой, без Ansible и inventory - достаточно одного короткого скрипта.
#!/usr/bin/env bash
echo "=== SYSTEM ==="
uname -a
echo -e "\n=== CPU / MEM ==="
free -h
echo -e "\n=== DISK ==="
df -hT | grep -v tmpfs
echo -e "\n=== NETWORK ==="
ip -br addr
Подходит для:
первичного осмотра сервера;
SSH-подключений к незнакомой машине;
логирования состояния перед изменениями.
uname -srmo; free -h; df -hT | awk 'NR==1||!/tmpfs/'; ip -br a
Удобно кидать в чат или запускать на десятках хостов по SSH.
{
uname -srmo
free -h
df -hT
ip -br a
} > sysinfo.txt
Можно сохранять как снапшот состояния перед деплоем или обновлением.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Проверка подвисших NFS-монтов и их исправление
1️⃣ Находим NFS-монты
И проверяем, жив ли маунт:
2️⃣ Проверяем доступность сервера
Если команда висит или падает - это означает, что сервер недоступен, маунт мертв.
3️⃣ Аккуратное отключение (без убийства процессов)
4️⃣ Автовосстановление
Или перезапуск через fstab:
Или мини-watchdog
BashTex📱 #bash #utils
mount | grep nfs
И проверяем, жив ли маунт:
mountpoint -q /mnt/nfs && echo OK || echo BROKEN
showmount -e nfs-server
Если команда висит или падает - это означает, что сервер недоступен, маунт мертв.
umount -l /mnt/nfs
-l (lazy umount) сразу убирает маунт из системы, а реальные дескрипторы закроются, когда процессы отпустят их.
mount /mnt/nfs && echo "NFS restored"
Или перезапуск через fstab:
mount -a -t nfs
Или мини-watchdog
check_nfs() {
mountpoint -q "$1" || return
timeout 3 ls "$1" >/dev/null || umount -l "$1"
}
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Анализ больших логов за секунды
▪️ Быстрый фильтр по событию
grep читает файл построчно, подходит даже для очень больших логов.
▪️ Извлечение нужных полей
Допустим, формат:
Берём только IP:
▪️ Агрегация и подсчет
Топ источников ошибок:
Результат:
▪️ Группировка по пользователям
BashTex📱 #bash
grep "ERROR" app.log
grep читает файл построчно, подходит даже для очень больших логов.
Допустим, формат:
2026-01-20 12:01:33 ERROR user=alice ip=10.0.0.5
Берём только IP:
grep "ERROR" app.log | awk '{print $NF}'
Топ источников ошибок:
grep "ERROR" app.log \
| awk '{print $NF}' \
| sort \
| uniq -c \
| sort -nr
Результат:
120 10.0.0.5
87 10.0.0.3
grep "ERROR" app.log \
| awk -F'user=' '{print $2}' \
| awk '{print $1}' \
| sort | uniq -c
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁4
Массовое обновление конфигов через шаблоны
▪️ Шаблон конфига
▪️ Задаём переменные
▪️ Массовая генерация конфигов
На выходе:
▪️ Dry-run перед применением
▪️ Применение с бэкапом
▪️ Использование:
массовая смена портов/доменов
автогенерация конфигов при деплое
одинаковые шаблоны на разных хостах
BashTex📱 #bash #utils
configs/app.conf.tpl
server_name=${HOST};
listen=${PORT};
env=${ENV};
max_clients=${MAX_CLIENTS};
export HOST=bashtex.com
export PORT=8080
export ENV=prod
export MAX_CLIENTS=500
mkdir -p out
for tpl in configs/*.tpl; do
envsubst < "$tpl" > "out/$(basename "${tpl%.tpl}")"
done
На выходе:
out/app.conf
out/other.conf
...
envsubst < configs/app.conf.tpl | diff -u /etc/app/app.conf -
for f in out/*.conf; do
sudo cp -a "/etc/app/$(basename "$f")"{,.bak}
sudo cp "$f" /etc/app/
done
массовая смена портов/доменов
автогенерация конфигов при деплое
одинаковые шаблоны на разных хостах
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Замена части файла через временный буфер
Иногда
▪️ Задача
Заменить блок между маркерами
▪️ Идея
читаем файл построчно;
отслеживаем, где мы находимся;
пишем результат во временный буфер;
атомарно подменяем файл;
🛠 Реализация
▪️ Что здесь важно
BashTex📱 #bash #utils
Иногда
sed слишком грубый инструмент: нужны условия, состояние, счетчики. В таких случаях проще пройтись по файлу построчно и собрать новый контент вручную.Заменить блок между маркерами
# BEGIN и # END, не трогая остальной файл.читаем файл построчно;
отслеживаем, где мы находимся;
пишем результат во временный буфер;
атомарно подменяем файл;
in_block=0
tmp=$(mktemp)
while IFS= read -r line; do
case "$line" in
"# BEGIN"*)
in_block=1
echo "$line" >>"$tmp"
echo "new content line 1" >>"$tmp"
echo "new content line 2" >>"$tmp"
;;
"# END"*)
in_block=0
echo "$line" >>"$tmp"
;;
*)
(( in_block )) || echo "$line" >>"$tmp"
;;
esac
done < config.conf
mv "$tmp" config.conf
IFS= read -r - сохраняет пробелы и \mktemp - безопасный временный файлmv - атомарная замена (без битых конфигов)BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3