BashTex | Linux
رفتن به کانال در Telegram
Авторский канал для тех, кто хочет глубже погрузиться в мир Linux. Подойдет для разработчиков, системных администраторов и DevOps Реклама: @dad_admin
نمایش بیشتر2 524
مشترکین
اطلاعاتی وجود ندارد24 ساعت
-67 روز
+230 روز
آرشیو پست ها
2 524
Массовое переименование файлов по шаблону
▪️ Вариант 1: rename. Если нужно заменить часть имени:
# Заменить "old" на "new" во всех именах
rename 's/old/new/' *.txt
Удалить префикс:
rename 's/^prefix_//' *.log
Добавить суффикс перед расширением:
rename 's/\.jpg$/_edited.jpg/' *.jpg
▪️ Вариант 2: sed + цикл. Когда шаблон сложный или нужно сгенерировать новое имя:
for f in *.mp4; do
new=$(echo "$f" | sed 's/episode_/ep-/; s/_final//')
mv "$f" "$new"
done
Можно применять любую логику, хоть разбивать строку на части.
▪️ Вариант 3: Bash expansion. Если у файлов есть общий номер или маска:
# Добавить нумерацию
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 📱 #bash2 524
Как находить зависшие задачи запущенные cron
Зависшие 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 📱 #bash2 524
Проверка слабых паролей пользователей
Важно понимать: мы не проверяем сами пароли и не подбираем их. Мы только выявляем пользователей, у кого высокий риск слабого пароля, анализируя политики и метаданные.
▪️ Что можно проверить
Возраст пароля, если пароль не меняли 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 📱 #bash2 524
Когда на новый год попросил побольше ОП, но почему-то теперь вместо винды стоит линукс 😁
BashTex 📱 #юмор
2 524
Автоматическая синхронизация каталогов по списку хостов
Когда один и тот же каталог нужно поддерживать в актуальном состоянии на нескольких серверах, самый простой инструмент:
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 📱 #bash2 524
Работа с архивами без распаковки
Распаковывать архив, чтобы посмотреть один файл - долго, неудобно и занимает место. К тому же большинство форматов позволяют работать прямо по месту.
1️⃣ Просмотр содержимого
tar -tf archive.tar.gz # tar
unzip -l archive.zip # zip
7z l archive.7z # 7z
2️⃣ Grep внутри архива (без извлечения)
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"
3️⃣ Поиск файла по части имени
7z l archive.7z | grep "\.conf"
tar -tf backup.tar | grep "nginx"
unzip -l logs.zip | grep ".log"
BashTex 📱 #bash2 524
Обработка SSH-команд через connection pooling
Если вам нужно выполнить десятки или сотни SSH-команд подряд, стандартный подход ssh host cmd превращается в ад: каждый вызов открывает новое TCP-соединение, делает handshake, обмен ключами, проверку known_hosts и все это ради одной короткой команды. Но SSH умеет работать совершенно иначе, через
multiplexing. Это когда одно физическое SSH-соединение становится трубой для десятков логических каналов. Команды выполняются без задержек, почти как локальные.
▪️ Включаем connection pooling. Создаем master-socket:
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"
Все эти вызовы выполняются почти мгновенно.
▪️ Автоматизация: ~/.ssh/config. Чтобы не писать все вручную:
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 📱 #bash #utils2 524
Отслеживание активности пользователей
Linux хранит всю историю входов в три системные базы:
lastlog - последний логин каждого пользователя
utmp - текущие активные сессии
wtmp - история всех логинов/логаутов
Вот короткий набор инструментов, позволяющий получить максимум информации.
1️⃣ Последние входы всех пользователей (lastlog). Показать, кто реально входит в систему:
lastlog | grep -v "Never logged in"
Фильтр подозрительно старых аккаунтов:
lastlog | awk '$4 ~ /Jan|Feb|Mar|Apr/ && $NF != "**Never**"'
2️⃣ Активные сессии прямо сейчас
who
С IP, временем и TTY:
who --ips
Выделение пользователей с нестандартных подсетей:
who --ips | awk '$5 !~ /^10\.|^192\.168\./'
3️⃣ История всех входов/выходов
last -F
Кто заходил чаще всего:
last | awk '{print $1}' | sort | uniq -c | sort -nr | head
Только удаленные логины:
last | grep -E "pts/[0-9]"
4️⃣ Комбинированный отчет
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 📱 #bash #utils2 524
Оптимизация скорости загрузки сервера
Как находить медленные юниты, диагностировать зависшие цепочки и исправлять задержки
1️⃣ Кто тормозит: анализ времени запуска.
systemd-analyze blame показывает, какие юниты стартуют дольше всех, базовый шаг в поиске проблем.
systemd-analyze blame
2️⃣ Поиск узкого места: критическая цепочка зависимостей. Если юнит стартует быстро, но висит в конце загрузки, то он блокирует чей-то старт или ждет зависимость. Нужно увидеть цепочку задержек:
systemd-analyze critical-chain
3️⃣ Устраняем задержку через override. Правильный способ настроить юнит - это не менять оригинальный файл, а создать override:
sudo systemctl edit docker.service
В открывшийся файл:
[Unit]
After=network.target
Wants=network.target
Применяем изменения:
sudo systemctl daemon-reload
sudo systemctl restart docker
Корректируем цепочку зависимостей, чтобы Docker не ждал медленных сетевых юнитов.
BashTex 📱 #bash #utils2 524
Подборка каналов IT от наших друзей:
🦥 Lazy_Programmer – Для ленивых
📲 Lazy_Programmer – В MAXе тоже есть место для лени
🤩 iwannabeprogrammer — IT-мемы
📲 iwannabeprogrammer – Мы в MAX
🎬 videos_it — База видеоуроков по IT
🐧 Linux_Club — Для Linuxоидов
📔 BOOKS — Читать не перечитать
🇷🇺 our_computer — У нас как в СССР
🔐 LazySecurity — Канал по ИБ
🔥 floppydisky — ITUMOR
📱 codebase_frontend — Красим кнопки
➡️ LazyDevOps — Канал для дев и псов
🐈⬛️ LazyTester — Протестируй канал!
2 524
Bash-аналитика для iptables/nftables
Большинство сетевых политик обрастает десятками правил, но какие из них реально срабатывают, а какие просто мертвый груз? Разберемся и составим набор команд.
1️⃣ Статистика хитов iptables.
iptables хранит счетчики прямо в правилах:
iptables -L INPUT -v -n
Поле pkts/bytes - это наши хиты.
Мини-скрипт для выборки топ-работающих правил:
iptables -L INPUT -v -n \
| awk '/ACCEPT|DROP/ {printf "%10s %s\n", $1, $0}' \
| sort -nr
Покажет самые горячие правила.
2️⃣ nftables: счетчики + export
nft list ruleset | grep -A1 'counter'
Bash-анализ:
nft list ruleset \
| awk '/counter/ {print $2, $3}' \
| sort -nr
3️⃣ Агрегация логов, какие действия реально происходят. Многие правила пишут в syslog (LOG prefix "iptables-"). Вытащим статистику по префиксам:
grep "iptables-" /var/log/syslog \
| awk '{print $NF}' \
| sort | uniq -c | sort -nr
Покажет, что именно чаще всего логирует firewall.
4️⃣ Комбинированный отчет
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 📱 #bash #utils2 524
Многоуровневый логинг
Большинство скриптов просто пишут все в 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
▪️ Перенаправление в консоль при необходимости. Например, показывать ERROR сразу на экране:
exec 5> >(tee -a error.log >&2)
Или дебаг-режим в реальном времени:
exec 4> >(sed 's/^/[DBG]/' >&2)
BashTex 📱 #bash #utils2 524
2 524
Автопоиск подвисших сетевых соединений и перезапуск сервисов
Если сервис начинает подвисать, это часто видно по сети: соединения зависают в SYN-SENT, CLOSE-WAIT или сидят в одном состоянии слишком долго. Это можно определить прямо в bash, без netstat/ss.
1️⃣ Читаем таблицу соединений из /proc/net/tcp
Формат /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
2️⃣ Привязка inode к PID процесса. Каждый сокет отображается как /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
}
3️⃣ Перезапуск сервиса
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 📱 #bash #utils2 524
На Stepik вышел курс по Linux
Внутри 20+ модулей: от установки Linux и работы с файлами до сетей, прав, дисков, процессов, автоматизации на Bash и многого другого. Всё сразу закрепляется на практике (200+ заданий с автопроверкой)
Материал подаётся понятным языком, шаг за шагом, на реальных примерах и с наглядными схемами.
После прохождения вы получите сертификат, который можно добавить в резюме.
Есть бесплатные демо-уроки для ознакомления. В ближайшие 48ч курс доступен со скидкой 25% по промокоду «
ADMIN25»: открыть курс на Stepik
P.S. Курс можно купить в подарок на Новый год2 524
Параллельный запуск задач с приоритетами
Когда нужно запускать много задач, но с разным приоритетом и контролем конкуренции, можно собрать простой планировщик задач. Мы создаем: очереди: 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 📱 #bash2 524
Ротация директорий
Когда нужно хранить несколько срезов состояния проекта или конфигов, удобно использовать ротацию директорий. Это быстрый, прозрачный и полностью файловый способ отката.
Предположим, у нас есть рабочая директория
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 📱 #bash2 524
Распределенный журнал событий через SSH fan-out
Иногда нужно собрать события с группы серверов и посмотреть их как единый хронологический поток: кто что делал, когда, и на каком хосте. Можно сделать это чисто на bash + SSH.
Для этого:
По SSH запускаем команду на каждом сервере (journalctl, tail, свой лог).
Добавляем timestamp + hostname.
Объединяем и сортируем и получаем общий timeline.
▪️ Fan-out по серверам
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 📱 #bash2 524
Использование socat как универсального канала между скриптами
socat позволяет связать любой источник данных с любым приемником. Bash-скрипты с ним превращаются в гибкие системы обмена сообщениями.
▪️ Bash через UNIX-сокет. Мини-IPC без tmp-файлов и named pipes:
Сервер:
socat UNIX-LISTEN:/tmp/app.sock,fork SYSTEM:'bash handler.sh'
Клиент:
echo "PING" | socat - UNIX-CONNECT:/tmp/app.sock
Отлично подходит для локальных API между скриптами.
2️⃣ Передача данных между серверами (TCP)
Сервер:
socat TCP-LISTEN:9000,fork FILE:/var/log/app.log
Клиент:
socat - TCP:server:9000
Можно в реальном времени стримить логи или метрики.
3️⃣ Замена сложных пайпов. Напрямую соединяем процессы, даже если они не умеют работать с stdin/stdout:
socat EXEC:"cmd1" EXEC:"cmd2"
Аналог cmd1 | cmd2, но без ограничений пайпа (например, поддержка bidirectional).
4️⃣ Двунаправленный канал в скрипте. Например, общение с интерактивным сервисом:
socat - TCP:localhost:8080 | while read l; do
echo ">> $l"
done
Можно строить собственные протоколы поверх TCP.
5️⃣ Быстрый импровизированный RPC
Сервер:
socat TCP-LISTEN:7000,reuseaddr,fork SYSTEM:'bash rpc-handler.sh'
Клиент:
echo '{"cmd":"status"}' | socat - TCP:host:7000
BashTex 📱 #bash #utils
اکنون در دسترس! پژوهش تلگرام ۲۰۲۵ — مهمترین بینشهای سال 
