Bash Советы
1.85K subscribers
53 photos
8 videos
4 links
🚀 Секреты и советы по Bash

🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!

💻 Прокачивай терминал вместе с нами! 👇
Download Telegram
Спецсимволы в bash

Далее перечислены символы и синтаксические конструкции, имеющее особое значение в bash. Для ввода спецсимволов как они есть используют кавычки или спецсимвол \ отменяющий специальное значение следующего символа

\ Экранирование. Отменяет специальное значение следующего символа
\\ Символ "\"

# Комментарий, не работает в кавычках и в некоторых подстановках переменных и преобразовании основания чисел
echo "Это #не комментарий"
echo 'Это # не комментарий’
echo Это \# не комментарий
echo Это # Вот комментарий.
echo ${PATH#*:} #Специальная переменная
echo $(( 2#101011 )) #Преобразование системы счисления в арифметической подстановке.

>, >> - перенаправление стандартного вывода программы в файл
< - перенаправление стандартного ввода программы из файла
<<TERM перенаправление стандартного ввода программы из текста текущего скрипта со следующей строки до строки, состоящей из слова TERM.
|- перенаправление стандартного вывода программы на стандартный ввод другой программы

; Разделитель команд в строке
echo hello; echo world

;; Разделитель альтернатив в операторе case
case "$VARiable" in
abc) echo "$VARiable = abc" ;;
xyz) echo "$VARiable = xyz" ;;
esac

. Аналог команды source (#include в С++). Выполняет скрипт в текущем интерпретаторе.
. myconf

".." Двойные кавычки, отменяют действие спецсимволов кроме $ .. и \

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

: Нулевая команда, всегда возвращает нулевой код ответа. В сочетании с перенаправлением ">" создает файл, или обнуляет существующий. В сочетании с перенаправлением ">>" создает файл, или изменяет время модификации существующего
:> data.xxx # File “data.xxx” now empty.
(можно и без двоеточия)

Шаблоны в именах файлов. Если подходящие имена находятся, то они подставляются в командную строку как отдельные аргументы (возможно с пробелами внутри). Если имена не находятся, то шаблон остается как есть.

* Шаблон заменяющий любую последовательность символов
? Шаблон заменяющий ровно один символ
[xyz] Шаблон заменяющий один из перечисленных символов
{xxx,yyy,zzz,...} Подстановка одного из вариантов в шаблон. В скобках не должно быть неэкранированных пробелов
grep Linux file*.{txt,htm*} # Ищет слово “Linux” в файлах вида “fileA.txt”, “file2.txt”, “fileR.html”, “file-87.htm”, etc.

$ Подстановка значения переменной, арифметического выражения или стандартного вывода программы. Если значение содержит пробелы, то при подстановке оно разбивается на отдельные аргументы.
$A содержимое переменной A
$$ PID процесса
$? Код возврата из последней выполненной программы или функции, а также код возврата самого скрипта
$((2*2)) подстановка результата вычисления арифметического выражения
$(cmd) подстановка стандартного вывода программы
... тоже, что и $(...) – подстановка стандартного вывода программы

Пример: A=EE; echo $A $(echo QQ) $((7+5))
Результат: EE QQ 12
Ошибка: $A=ZZ
Результат: bash: EE=ZZ: command not found

(...) Группировка команд
(A=hello; echo $A)
Для выполнения группы в скобках запускается новый интерпретатор
A=123
(A=321)
echo A = $A # A = 123
# "A" внутри скобок – локальная переменная.

(...) Создание массива ( только в bash версии > 2)
Array=(element1 element2 element3)

[] Элемент массива ( только в bash версии > 2)
Array[1]=slot_1
echo ${Array[1]}

{1..10} - подстановка чисел от 1 до 10
{c..n} - подстановка символов от "c" до "n"

{...} Создание безымянной функции, удобно для перенаправления ввода/вывода нескольких команд в один файл. В отличие от настоящей функции видимости переменных не изменяется.
PACK=mysql
{
echo
echo "Archive Listing:"
rpm -qpl ${PACK} # Список фалов в пакете rpm
echo
rpm -i --test ${PACK} # Проверка, установлен ли пакет.
} > "${PACK}.txt" весь вывод в один файл.

[...] Встроенная функция test для вычисления логических выражений

((...)) Арифметическая подстановка, вычисляет арифметическое выражение в стиле языка Си внутри скобок

& - запуск программы в фоновом режиме
bash$ sleep 10 &
[1] 850
[1]+ Done sleep 10

👉@bash_srv
🧠 Bash-совет дня: Проверка скорости интернет-соединения прямо из терминала

Если тебе нужно быстро проверить скорость интернета на сервере (например, VPS), не устанавливая громоздкие GUI-программы — вот решение:


#!/bin/bash

# Проверяем наличие speedtest-cli
if ! command -v speedtest &> /dev/null; then
echo " Устанавливаем speedtest-cli..."
apt update && apt install -y speedtest-cli # Для Debian/Ubuntu
# yum install -y speedtest-cli # Для RHEL/CentOS
fi

# Запускаем тест скорости
echo "🚀 Проверяем скорость интернет-соединения..."
speedtest


📝 Альтернатива без установки — через curl:


curl -s https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py | python3 -


📊 Удобно использовать при диагностике проблем с сетью, особенно на серверах в разных дата-центрах.

👉@bash_srv
🚀 Bash-совет дня: Быстрое сканирование открытых портов с помощью bash и /dev/tcp

Зачем ставить nmap, если можно быстро просканировать порты встроенными средствами bash? Вот простой однострочный скрипт:


for port in {20..1024}; do
(echo > /dev/tcp/127.0.0.1/$port) >/dev/null 2>&1 && echo "Порт $port открыт"
done


📌 Что делает скрипт:

* Использует встроенную возможность Bash подключаться к TCP-портам через псевдофайлы /dev/tcp/host/port.
* Проверяет диапазон портов от 20 до 1024 на локальной машине.
* Если порт доступен — выводит сообщение, что он открыт.

🔒 Можно заменить 127.0.0.1 на любой IP-адрес сервера в сети.
💡 Отличный способ быстро проверить, что открыто, когда нет доступа к полноценным утилитам.

👉@bash_srv
🧠 Bash совет дня — Отслеживаем подозрительные sudo-команды в реальном времени 🕵️

Хочешь знать, кто и что запускает через sudo прямо сейчас? Настроим простой мониторинг:


#!/bin/bash

logfile="/var/log/auth.log"

tail -F "$logfile" | grep --line-buffered "sudo" | while read line; do
echo "[ALERT] 🔐 $(date): $line"
done


📌 Что делает:

* Следит за /var/log/auth.log в реальном времени.
* Отфильтровывает строки, связанные с sudo.
* Выводит каждое срабатывание с пометкой времени.

🔥 Пример вывода:


[ALERT] 🔐 2025-05-15 10:23:42: user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/bin/bash


💡 Используй для:

* Мониторинга активности админов или подозрительных действий.
* Настройки моментального оповещения (можно расширить, чтобы слать в Telegram, Slack и т.д.).

📦 Можно оформить как systemd-сервис, чтобы монитор запускался автоматически.

👉@bash_srv
🕵️ Ищем процессы, которые используют удалённые (удалённые, но не освобождённые) файлы

Бывает, что ты удаляешь лог или большой файл, а место на диске не освобождается? Это потому, что файл всё ещё открыт каким-то процессом! Вот скрипт, который найдёт таких «виновников»:


#!/bin/bash

echo "🔍 Ищем процессы, держащие открытые удалённые файлы..."
lsof | grep '(deleted)' | awk '{print $2}' | sort -u | while read -r pid; do
echo "PID: $pid | Команда: $(ps -p $pid -o comm=)"
done


📌 Как использовать:


chmod +x find_deleted.sh
./find_deleted.sh


💡 Подсказка: иногда помогает systemctl restart соответствующего сервиса, чтобы освободить место.

👉@bash_srv
🔥 Bash-фишка дня: замена строк в файле без sed и awk

Иногда хочется быстро заменить строку в файле без сложных конструкций. Вот способ сделать это с чистым Bash и while read:

🛠 Скрипт: заменить слово в файле


#!/bin/bash

INPUT="config.txt"
OUTPUT="config_new.txt"
SEARCH="localhost"
REPLACE="127.0.0.1"

while IFS= read -r line; do
echo "${line//$SEARCH/$REPLACE}"
done < "$INPUT" > "$OUTPUT"


📌 Что тут происходит:

* IFS= read -r line — читаем файл построчно, без обрезки пробелов.
* ${line//$SEARCH/$REPLACE} — заменяем все вхождения $SEARCH на $REPLACE.
* Результат сохраняем в новый файл.

⚡️ Подходит, когда sed недоступен (да, бывает) или нужна более понятная логика замены.

👉@bash_srv
🔁 Как перезапускать сервис только если он завис?

Иногда не хочется перезапускать сервис "на всякий случай", но вот если он реально завис — другое дело. Вот простой способ проверять, активен ли сервис, и перезапускать его при зависании:


#!/bin/bash

SERVICE="nginx"

if ! systemctl is-active --quiet "$SERVICE"; then
echo "$(date): $SERVICE не активен, пробую перезапустить..." >> /var/log/service_monitor.log
systemctl restart "$SERVICE"
else
echo "$(date): $SERVICE работает нормально" >> /var/log/service_monitor.log
fi


🛠 Можно добавить в крон, например, проверку каждые 5 минут:


*/5 * * * * /usr/local/bin/check_nginx.sh


📁 Не забудь сделать скрипт исполняемым:


chmod +x /usr/local/bin/check_nginx.sh


💡 Можно заменить nginx на любой другой системный сервис.

👉@bash_srv
⚙️ Bash: Мониторинг пользователей в системе в реальном времени

Иногда нужно понять, кто из пользователей сейчас в системе и что они делают. Встречай удобную команду на базе watch и w:


watch -n 2 w


📌 Что делает эта команда:

* watch -n 2 — каждые 2 секунды выполняет указанную команду
* w — показывает, кто залогинен, откуда, сколько времени в системе и что выполняет

👀 Отлично подходит для ситуаций:

* Отладка скриптов, когда нужно смотреть, кто подключается
* Мониторинг активности сотрудников или админов
* Выявление подозрительных сессий SSH

💡 А если хочешь видеть только логины, без подробностей:


watch -n 2 who


Полезно держать на втором экране или в отдельной вкладке терминала 🧠

👉@bash_srv
🗑️ Bash-совет дня: safe_rm — «корзина» для удаляемых файлов

Сколько раз вы случайно удаляли важный конфиг? Давайте сделаем rm более дружелюбным — вместо мгновенного уничтожения файлы будут складываться в «корзину» и автоматически очищаться спустя 30 дней.


#!/usr/bin/env bash
# safe_rm — перемещает удаляемые файлы в локальную «корзину»

TRASH_DIR="$HOME/.local/share/Trash/files" # куда складываем
mkdir -p "$TRASH_DIR"

stamp=$(date +%Y-%m-%d_%H-%M-%S)

for item in "$@"; do
if [[ ! -e $item ]]; then
printf '⚠️ %s: no such file or directory\n' "$item" >&2
continue
fi
mv -- "$item" "$TRASH_DIR/$(basename "$item")_$stamp"
done

# авто-очистка файлов, которым больше 30 дней
find "$TRASH_DIR" -type f -mtime +30 -delete 2>/dev/null


Быстрый старт


sudo install -m 755 safe_rm /usr/local/bin/
echo "alias rm='safe_rm'" >> ~/.bashrc && source ~/.bashrc


Проверяем


touch important.cfg
rm important.cfg
ls ~/.local/share/Trash/files # Файл на месте 🎉


> Лайфхак:
> Хотите разные сроки хранения? Меняйте -mtime +30 на нужное количество дней.
> Регулярные выражения в find позволяют тоньше выбирать, что чистить (например, только логи *_$(date +%Y-%m-*)).

Спасайте нервы и конфиги! 😉

👉@bash_srv
Извлечение уникальных IP-адресов из логов Apache

Иногда нужно быстро получить список всех клиентов, обращавшихся к вашему веб-серверу. Мини-скрипт на Bash с регулярным выражением поможет вытащить и сохранить все уникальные IP-адреса:


#!/usr/bin/env bash

# 📁 Файл логов Apache
LOG_FILE="/var/log/apache2/access.log"

# 📄 Файл для сохранения уникальных IP
OUT_FILE="/var/log/unique_ips_$(date +%F).txt"

# 🛠️ Извлекаем все IPv4, сортируем и убираем дубликаты
grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' "$LOG_FILE" \
| sort \
| uniq > "$OUT_FILE"

echo " Список уникальных IP-адресов сохранён в $OUT_FILE"


Как это работает

1. grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' — опция -E включает расширенные регулярки, -o выводит только совпадения. Регулярка ищет четыре числа от 0 до 999 через точки.
2. sort упорядочивает адреса для корректной работы uniq.
3. uniq удаляет повторяющиеся строки, оставляя только уникальные IP.

Совет по автоматизации
Если вы хотите ежедневно обновлять этот список, добавьте задачу в cron:


0 1 * * * /usr/local/bin/extract_ips.sh >> /var/log/extract_ips_cron.log 2>&1


Это запустит скрипт каждый день в 1:00 и сохранит результат с датой в имени файла.

👉@bash_srv
🚀 Полезный Bash-скрипт для архивации старых логов 🚀

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

1. Находит файлы с расширением .log, изменённые более чем N дней назад.
2. Архивирует их в тарболл с датой.
3. Удаляет оригиналы после успешного архива.


#!/usr/bin/env bash
#
# Архивация старых логов >7 дней
# Сохраняет в /var/backups/logs/YYYY-MM-DD_logs.tar.gz

# Настройки
LOG_DIR="/var/log" # Каталог с логами
BACKUP_DIR="/var/backups/logs" # Куда складывать архивы
DAYS_OLD=7 # Возраст файлов в днях

# Создаём папку для бэкапов, если нет
mkdir -p "$BACKUP_DIR"

# Текущая дата
DATE=$(date '+%Y-%m-%d')

# Найти *.log старше N дней и упаковать в архив
find "$LOG_DIR" -type f -regextype posix-extended -regex ".*/[a-zA-Z0-9_-]+\.log$" \
-mtime +"$DAYS_OLD" -print0 | \
tar --null -czf "$BACKUP_DIR/${DATE}_logs.tar.gz" --files-from -

# Проверка успешности и удаление исходников
if [[ $? -eq 0 ]]; then
echo " Архив создан: $BACKUP_DIR/${DATE}_logs.tar.gz"
# Удаляем старые логи
find "$LOG_DIR" -type f -regextype posix-extended -regex ".*/[a-zA-Z0-9_-]+\.log$" \
-mtime +"$DAYS_OLD" -delete
echo "🗑️ Оригиналы удалены."
else
echo " Ошибка при создании архива!"
exit 1
fi


Как это работает

* find … -regextype posix-extended -regex ".*/[a-zA-Z0-9_-]+\.log$"
Использует регулярное выражение, чтобы найти все файлы с именами, состоящими из букв, цифр, подчёркиваний или дефисов, и оканчивающиеся на .log.
* Опция -mtime +7 выбирает файлы старше 7 дней.
* tar --null --files-from - позволяет безопасно работать с именами, содержащими пробелы.
* При успешном создании архива исходные файлы удаляются командой -delete в find.

Совет:
Добавьте этот скрипт в cron, чтобы он выполнялся автоматически, например, каждый день в 2:00:


0 2 * * * /usr/local/bin/archive_logs.sh >> /var/log/archive_logs_cron.log 2>&1


👍 Надеюсь, пригодится!

👉@bash_srv
🚀 Мониторим активные подключения к серверу по SSH

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


who | grep 'pts' | awk '{print $1, $2, $5}'


Что делает этот скрипт?

* who — выводит список всех вошедших пользователей.
* grep 'pts' — фильтрует только те строки, что связаны с терминалами SSH.
* awk '{print $1, $2, $5}' — красиво выводит имя пользователя, терминал и IP-адрес.

📋 Пример вывода:


admin pts/0 (192.168.1.55)
root pts/1 (10.0.0.23)


Теперь ты всегда в курсе, кто подключён к твоему серверу! 😉

👉@bash_srv
🧹 Bash-скрипт для очистки старых логов с уведомлением

Иногда логи занимают слишком много места, и их нужно периодически чистить. Этот скрипт удаляет логи старше 14 дней в заданной папке и шлёт уведомление на почту, если удалено более 500 МБ.


#!/bin/bash

LOG_DIR="/var/log"
DAYS=14
MAX_REMOVED_MB=500
EMAIL="admin@yourdomain.com"

# Подсчитываем общий размер файлов, которые будут удалены
REMOVED_SIZE=$(find "$LOG_DIR" -type f -mtime +$DAYS -print0 | du --files0-from=- -ch | grep total$ | awk '{print $1}')
REMOVED_SIZE_MB=$(echo $REMOVED_SIZE | sed 's/M//' | awk '{print int($1)}')

# Удаляем старые логи
find "$LOG_DIR" -type f -mtime +$DAYS -delete

# Если удалено больше MAX_REMOVED_MB, отправляем уведомление на почту
if [ "$REMOVED_SIZE_MB" -gt "$MAX_REMOVED_MB" ]; then
echo "Удалено логов на $REMOVED_SIZE из $LOG_DIR" | mail -s "Удаление логов" "$EMAIL"
fi


🔹 Что делает скрипт:

* Находит старые логи, считает их общий размер.
* Удаляет только если файлы старше 14 дней.
* Если удалено больше заданного лимита (по умолчанию 500 МБ) — уведомляет по почте.

Обрати внимание:
Для работы уведомления нужна установленная утилита mail (например, из пакета mailutils или sendmail).

👉@bash_srv
🕵️‍♂️ Мониторим новые файлы в каталоге в реальном времени

Иногда нужно узнать, когда в определённой папке появляются новые файлы. Bash + inotifywait помогут:


inotifywait -m -e create --format '%w%f' /path/to/dir | while read NEWFILE; do
echo "🆕 Новый файл: $NEWFILE"
done


📦 Объяснение:

* inotifywait -m — постоянный мониторинг
* -e create — событие создания
* --format '%w%f' — полный путь к новому файлу
* /path/to/dir — нужная папка
* Всё новое сразу отображается в консоли

Установить inotify-tools:


sudo apt install inotify-tools


👉@bash_srv
📈 Мониторинг загрузки CPU и памяти с автоматическими уведомлениями 🚨Часть 1️⃣

Всем привет! Сегодня сделаем Bash-скрипт, который периодически проверяет загрузку процессора и использование памяти, логирует результаты и отправляет уведомление, если показатели превышают заданные пороги. Полезно держать под контролем ресурсы сервера и вовремя реагировать на перегрузки.


#!/usr/bin/env bash
# Название: monitor_resources.sh
# Описание: Мониторит загрузку CPU и память, пишет в лог и уведомляет при превышении порогов.
# Использование: ./monitor_resources.sh 75 80 "/путь/до/notify.sh" "/var/log/resource_monitor.log"

# ---------------------------
# Параметры:
# $1 - порог нагрузки CPU в % (например, 75)
# $2 - порог использования RAM в % (например, 80)
# $3 - (опционально) скрипт для уведомления (при превышении любого порога)
# $4 - (опционально) файл лога (по умолчанию /var/log/resource_monitor.log)
# ---------------------------

CPU_THRESHOLD="${1:-75}"
RAM_THRESHOLD="${2:-80}"
NOTIFY_SCRIPT="$3"
LOG_FILE="${4:-/var/log/resource_monitor.log}"

# Функция: Получает текущую загрузку CPU в процентах (суммарно по всем ядрам)
get_cpu_usage() {
# Используем команду top в batch-режиме один раз, парсим строку "%Cpu(s)"
local cpu_idle
cpu_idle=$(top -bn1 | grep '^%Cpu' | awk '{print $8}' | tr -d ',%i')
# cpu_idle — процент простаивающего CPU, остальное считается занятостью
local cpu_usage=$((100 - cpu_idle))
echo "$cpu_usage"
}

# Функция: Получает текущее использование RAM в процентах
get_ram_usage() {
# Используем команду free, берем строку Mem:, вычисляем (used/total)*100
local total mem_free buff_cache used
read -r total mem_free buff_cache used _ < <(free -m | awk '/^Mem:/ {print $2, $4, $6, $3}')
# Общее доступное для процессов = free + buff/cache
local available=$((mem_free + buff_cache))
local ram_usage=$(( ( (total - available) * 100 ) / total ))
echo "$ram_usage"
}

# Функция: Записывает в лог текущие показатели с датой и временем
write_log() {
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] CPU: ${CPU}% | RAM: ${RAM}%" >> "$LOG_FILE"
}

# Функция: Проверяет пороги и при необходимости вызывает скрипт уведомления
check_thresholds() {
local alert_messages=()

if (( CPU > CPU_THRESHOLD )); then
alert_messages+=("CPU превышен: текущая загрузка ${CPU}% (порог ${CPU_THRESHOLD}%)")
fi

if (( RAM > RAM_THRESHOLD )); then
alert_messages+=("RAM превышен: текущее использование ${RAM}% (порог ${RAM_THRESHOLD}%)")
fi

if [[ ${#alert_messages[@]} -gt 0 ]]; then
local full_message="🚨 WARNING на $(hostname):\n$(printf '%s\n' "${alert_messages[@]}")"
echo -e "$full_message" >> "$LOG_FILE"
if [[ -x "$NOTIFY_SCRIPT" ]]; then
# Передаем уведомление как один аргумент (с переводами строк)
"$NOTIFY_SCRIPT" "$full_message"
echo "✔️ Уведомление отправлено через $NOTIFY_SCRIPT" >> "$LOG_FILE"
else
echo "⚠️ Скрипт уведомления не доступен или не указан." >> "$LOG_FILE"
fi
fi
}

# Основной блок
CPU=$(get_cpu_usage)
RAM=$(get_ram_usage)
write_log
check_thresholds

exit 0




Как это работает 📋

1. get_cpu_usage

* top -bn1 запускает top в неинтерактивном режиме один раз (batch mode).
* Парсим строку вида %Cpu(s): 3.0 us, 1.0 sy, 0.0 ni, 95.5 id, ... и берем поле с процентом простаивающего CPU (id).
* cpu_usage = 100 - cpu_idle — получаем загрузку в процентах.

2. get_ram_usage

* free -m выводит статистику по памяти в мегабайтах. Строка Mem: содержит total, used, free, shared, buff/cache, available.
* Чтобы учесть буфер/кэш, вычисляем available = free + buff/cache.
* ram_usage = ((total - available) * 100) / total — процент реально занятой памяти.

3. Запись в лог

* В файл (по умолчанию /var/log/resource_monitor.log) пишется строка с текущими значениями CPU и RAM вместе с временной меткой.
* Если файл не существует, он будет создан автоматически (не забудьте, чтобы скрипт имел права записи в эту директорию).

Продолжение в след. посте 👇

👉@bash_srv
📈 Мониторинг загрузки CPU и памяти с автоматическими уведомлениями 🚨Часть 2️⃣

4. Проверка порогов

* Сравниваем переменные CPU и RAM с CPU_THRESHOLD и RAM_THRESHOLD.
* Если превышен хотя бы один порог, формируем сообщение об ошибках (несколько строк, если оба ресурса в аварийном состоянии).
* Записываем предупреждение в тот же лог.
* При наличии исполняемого скрипта $NOTIFY_SCRIPT (например, отправка письма, пуша в Telegram, Slack, и т.д.) вызываем его, передавая всю текстовую информацию одним аргументом.
* Если скрипт уведомления не указан или он не помечен как исполняемый, просто логируем, что уведомление не отправлено.



Пример использования 🖥️

1. Создаем скрипт уведомления (например, notify.sh), который отправит сообщение в Telegram через Bot API (пример упрощённый):


#!/usr/bin/env bash
# notify.sh
# Использование: ./notify.sh "Ваше сообщение"
CHAT_ID="123456789"
BOT_TOKEN="1234:ABCD..."
MESSAGE="$1"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="$MESSAGE"


Не забудьте сделать его исполняемым:


chmod +x /path/to/notify.sh


2. Сам скрипт мониторинга (сохраняем как /usr/local/bin/monitor_resources.sh):


chmod +x /usr/local/bin/monitor_resources.sh


3. Добавляем в cron для регулярного выполнения, например, каждые 5 минут:


*/5 * * * * /usr/local/bin/monitor_resources.sh 75 80 /path/to/notify.sh /var/log/resource_monitor.log


* Каждые 5 минут скрипт будет проверять ресурсы.
* Если загрузка CPU превысит 75% или использование RAM превысит 80%, вы получите пуш в Telegram.
* Все показатели и события будут храниться в /var/log/resource_monitor.log.



Регулярные выражения для анализа логов 🛠️

Чтобы быстро найти в логе все моменты, когда была высокая загрузка, можно воспользоваться grep с регуляркой на поиск слова WARNING или WARNING на (в зависимости от вашего формата):


grep -E "WARNING на" /var/log/resource_monitor.log | tail -n 20


* -E включает расширенные регэкспы, чтобы мы могли сразу писать более выразительные шаблоны.
* Если нужно искать как CPU, так и RAM-превышения, можно просто фильтровать по ключевому слову WARNING.

А чтобы извлечь только числовые значения CPU и RAM (например, для построения графика), можно использовать такую регулярку:


grep -oP "(?<=CPU: )\d+|(?<=RAM: )\d+" /var/log/resource_monitor.log


* -oP — включаем Perl-совместимые регулярки и печатаем только совпадения.
* (?<=CPU: )\d+ находит числа, стоящие после CPU: . То же для RAM: .
* В результате вы получите список чисел: сначала процент CPU, затем процент RAM, затем снова CPU и RAM и т.д. Можно перенаправить их в CSV для визуализации.


Советы по доработке

* Графическое представление: можно раз в сутки запускать ещё один скрипт, который из лога выдергивает данные за последние 24 часа и рисует график (с помощью gnuplot или Python).
* Добавить HDD/SSD мониторинг: аналогично можно проверять доступное место на диске (через df -h и awk), объединив два вида проверки в одном инструменте.
* Динамические пороги: если у вас в пиковое время допустимо более высокое значение, можно задавать пороги исходя из времени суток — через date +%H проверять час и переключаться между разными значениями.

Надеюсь, этот скрипт упростит вам задачу контроля ресурсов и поможет своевременно реагировать на перегрузки серверов!

👉@bash_srv
Сегодня я хочу поделиться простым, но очень полезным Bash-скриптом для автоматического резервного копирования директорий с ротацией старых бэкапов. Такой скрипт пригодится, если необходимо сохранять копии важных данных и при этом не засорять диск старыми архивами.


🔄 Скрипт: Backup с ротацией


#!/usr/bin/env bash

# ================================
# Скрипт: backup_rotate.sh
# Автор: https://t.me/bash_srv
# Описание: Создаёт архив указанной директории,
# хранит только последние N бэкапов, удаляя старые.
# ================================

# Настройки
SOURCE_DIR="/var/www/my_project" # Директория, которую резервируем
DEST_DIR="/backups/my_project" # Директория для хранения бэкапов
RETENTION_DAYS=7 # Сколько дней хранить бэкапы

# Текущее время для имени архива
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
ARCHIVE_NAME="backup_${DATE}.tar.gz"

# Проверяем, что исходная директория существует
if [[ ! -d "$SOURCE_DIR" ]]; then
echo " Исходная директория $SOURCE_DIR не найдена!"
exit 1
fi

# Создаём директорию назначения, если её нет
mkdir -p "$DEST_DIR"

# Создаём архив
tar -czf "${DEST_DIR}/${ARCHIVE_NAME}" -C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")"
if [[ $? -eq 0 ]]; then
echo " Создан бэкап: ${DEST_DIR}/${ARCHIVE_NAME}"
else
echo " Ошибка при создании архива!"
exit 1
fi

# Удаляем старые бэкапы старше RETENTION_DAYS
find "$DEST_DIR" -type f -name "backup_*.tar.gz" -mtime +${RETENTION_DAYS} -print -delete
echo "🗑️ Удалены бэкапы старше ${RETENTION_DAYS} дней."

exit 0



📝 Пояснение к скрипту

1. Настройки переменных:

🔹 SOURCE_DIR — путь к директории, которую нужно сохранить (например, веб-проект, база данных и т.д.).
🔹 DEST_DIR — куда складываем архива (может быть локальная папка или смонтированный удалённый диск).
🔹 RETENTION_DAYS — сколько дней хранить бэкапы. Всё, что старше этого значения, будет удаляться автоматически.
2. Скрипт проверяет, существует ли исходная директория. Если нет — выводит ошибку и завершает работу.
3. Создаётся папка назначения (mkdir -p), чтобы избежать ошибок, если её ещё нет.
4. Делается tar.gz - архив директории, причём для удобства используется команда:


tar -czf ${DEST_DIR}/${ARCHIVE_NAME} -C $(dirname $SOURCE_DIR) $(basename $SOURCE_DIR)


- Это позволяет не копировать весь путь в архив, а только нужную папку.
5. Если архивирование прошло успешно (код возврата 0) — выводим сообщение об успехе.
6. Далее команда find ищет файлы-архивы старше RETENTION_DAYS дней и удаляет их. Параметр -mtime +N означает “более N дней назад”. Опция -print -delete сначала покажет, что удаляется, а потом удалит.
7. В конце скрипт выводит, сколько старых бэкапов удалено, и завершает работу.


📌 Как использовать

1. Скопируйте скрипт в файл, например:


sudo nano /usr/local/bin/backup_rotate.sh

2. Сделайте его исполняемым:


sudo chmod +x /usr/local/bin/backup_rotate.sh

3. Отредактируйте переменные в начале скрипта под свои нужды:


SOURCE_DIR="/path/to/your/data"
DEST_DIR="/path/to/backup/location"
RETENTION_DAYS=7

4. Запустите вручную, чтобы протестировать:


/usr/local/bin/backup_rotate.sh

5. Если всё работает как надо, добавьте задание в ``````bash
crontab``````bash
для автоматического запуска. Например, чтобы делать бэкап каждый день в 3:00:


sudo crontab -e


И добавить строку:


0 3 * * * /usr/local/bin/backup_rotate.sh >> /var/log/backup_rotate.log 2>&1


Здесь мы также перенаправляем вывод в лог-файл, чтобы отслеживать успешные и неуспешные запуски. 📜

👉@bash_srv
Вдогонку к посту выше, скрипт можно доработать, например:


🔹🔒 Шифрование архива: можно добавить gpg для шифровки бэкапа, если вы сохраняете его во внешнем облаке.
🔹📤 Загрузка в облако: после создания архива добавить команду для выгрузки в Amazon S3/Google Cloud Storage/FTP.
🔹📧 Уведомления: вставить отправку письма или Telegram-уведомление об успешном/неудачном бэкапе.
🔹📂 Разные политики ротации: вместо удаления по возрасту, можно хранить фиксированное количество последних архивов:


ls -1t "$DEST_DIR"/backup_*.tar.gz | tail -n +6 | xargs rm -f


- Это будет хранить только 5 свежих бэкапов.

Надеюсь, этот скрипт упростит вам жизнь и поможет защитить ваши данные! Если возникнут вопросы или идеи осовременить решение — пишите в комментариях. 😊

👉@bash_srv
💡 Bash-совет: Анализ самых активных IP в логах веб-сервера 🐚🚀

Когда на сервере много трафика, полезно быстро узнать, какие IP-адреса обращаются к веб-серверу больше всего. Предлагаю скрипт, который:

1. Извлекает IP из access.log (или любого другого лог-файла).
2. Считает количество запросов от каждого IP.
3. Сортирует и показывает топ N «запросчиков».


📋 Скрипт: top_ips.sh


#!/usr/bin/env bash

# --------------------------------------------
# Скрипт для поиска топ-N IP-адресов в логах
# Автор: @bash_srv
# --------------------------------------------

# Путь к лог-файлу (по умолчанию /var/log/nginx/access.log)
LOGFILE="/var/log/nginx/access.log"

# Сколько адресов показать (по умолчанию 10)
TOP_N=10

# Временный файл для списка всех IP
TEMP="/tmp/all_ips_$(date +%Y%m%d_%H%M%S).txt"

# Проверка, что лог-файл существует
if [[ ! -f "$LOGFILE" ]]; then
echo " Лог-файл '$LOGFILE' не найден!"
exit 1
fi

echo "🔎 Извлекаем IP-адреса из $LOGFILE и рассчитываем топ $TOP_N..."

# 1. Извлекаем первый столбец (обычно там IP), записываем во временный файл
awk '{print $1}' "$LOGFILE" > "$TEMP"

# 2. Считаем повторы, сортируем по убыванию, выводим топ N
echo -e "\n📊 Топ $TOP_N IP-адресов (по количеству запросов):"
sort "$TEMP" | uniq -c | sort -nr | head -n "$TOP_N" | awk '{printf "%s запросов — %s\n", $1, $2}'

# 3. Убираем временный файл
rm -f "$TEMP"

echo -e "\n Готово!"



📝 Как это работает

1. LOGFILE — путь к вашему файлу логов Nginx/Apache.

Для Apache обычно /var/log/apache2/access.log, для Nginx — /var/log/nginx/access.log.
Если у вас другой путь, просто адаптируйте переменную LOGFILE.

2. Команда awk '{print $1}' "$LOGFILE":

Берёт первый столбец в каждой строке лога (IP-адрес).
Сохраняет все адреса во временный файл $TEMP.

3. sort "$TEMP" | uniq -c | sort -nr | head -n "$TOP_N":

sort упорядочивает список IP по возрастанию.
uniq -c объединяет подряд идущие одинаковые строки и выводит количество повторений.
Второй sort -nr сортирует по числу запросов (включая самое большое значение сверху).
head -n "$TOP_N" берёт первые N строк (топ N IP).

4. awk '{printf "%s запросов — %s\n", $1, $2}' форматирует вывод:

Например: 1234 запросов — 192.168.1.100.

5. По завершении удаляется временный файл $TEMP для чистоты.


🔧 Как улучшить и кастомизировать

Датафильтрация: если нужен анализ только за последние N дней, можно применять grep с date:


# Пример: IP-адреса из логов за сегодня
TODAY=$(date '+%d/%b/%Y')
grep "$TODAY" "$LOGFILE" | awk '{print $1}' > "$TEMP"


Здесь date '+%d/%b/%Y' выдаёт, например, 05/Jun/2025, что совпадает со строками формата Nginx-лога.

Анализ URL: можно аналогично извлекать запрашиваемые URL:


awk '{print $7}' "$LOGFILE" | sort | uniq -c | sort -nr | head -n 10


Это покажет топ-10 запрашиваемых путей.

Выгрузка в файл/почту: чтобы сохранить результаты или отправить их администратору:


OUTPUT="/tmp/top_ips_report.txt"
sort "$TEMP" | uniq -c | sort -nr | head -n "$TOP_N" > "$OUTPUT"
mail -s "Топ IP-адресов на $(hostname)" admin@example.com < "$OUTPUT"


Интеграция в cron: автоматизируйте ежедневный отчёт:


# crontab -e
30 0 * * * /usr/local/bin/top_ips.sh >> /var/log/top_ips.log


Это запустит скрипт каждый день в 00:30 и добавит результаты в /var/log/top_ips.log.


🔔 Вывод: Используя этот простой Bash-скрипт, вы сможете в пару команд узнать, какие IP-адреса генерируют наибольшую нагрузку на ваш веб-сервер. Это поможет вовремя выявить подозрительные активности, защититься от DDoS-атак или просто понять, кто чаще всего посещает сайт.

👉@bash_srv
Bash-совет: анализ неудачных SSH-логинов и бан «горячих» IP 🔒🐚

Хотите быстро узнать, какие IP вызывают максимум неудачных попыток входа в SSH, и оперативно заблокировать самых настырных? Ниже скрипт:


#!/usr/bin/env bash
# ssh_fail_analyzer.sh
# Анализ неудачных SSH-попыток и вывод TOP-10 IP

LOG_FILE="/var/log/auth.log" # путь к логам (для CentOS: /var/log/secure)
TOPN=10 # сколько IP показывать

echo "Топ $TOPN IP с неудачными SSH-входами:"
grep -E "Failed password for" "$LOG_FILE" \
| grep -oP '(?<=from )[\d\.]+' \
| sort \
| uniq -c \
| sort -rn \
| head -n "$TOPN"


Как это работает

1. grep -E "Failed password for"
Ищем все строки с неудачными попытками.
2. grep -oP '(?<=from )\[\d.]+'
С помощью PCRE-регулярки достаём только IP-адреса после слова "from".
3. sort | uniq -c | sort -rn
Сортируем, считаем вхождения и выводим в порядке убывания.
4. head -n "\$TOPN"
Ограничиваем результат топ-10.


🛠 Можно добавить в crontab ежедневный запуск и автоматическую отправку отчёта на почту или сразу бан «горячих» IP через iptables:


# в crontab: каждый день в 00:10
10 0 * * * /path/to/ssh_fail_analyzer.sh | mail -s "SSH Fail Report" admin@example.com


Или сразу блокировать подозрительные IP, если они превысили порог:


THRESHOLD=50
for ip in $(grep -E "Failed password for" "$LOG_FILE" \
| grep -oP '(?<=from )[\d\.]+' \
| sort | uniq -c \
| awk -v t="$THRESHOLD" '$1 > t {print $2}'); do
iptables -I INPUT -s "$ip" -j DROP
echo "$(date): Заблокирован $ip за превышение $THRESHOLD неудачных попыток" >> /var/log/ssh_ban.log
done


👉@bash_srv
🔍 Мониторинг сервисов Linux и автоматический перезапуск 🛠️

Иногда сервисы на сервере «внезапно» падают, а вы об этом узнаёте лишь по жалобам пользователей. Предлагаю простой Bash-скрипт, который:

1. Проверяет статус списка сервисов
2. При необходимости перезапускает их
3. Логирует все действия


#!/usr/bin/env bash
# автор: https://t.me/bash_srv
# Список сервисов для мониторинга
services=(nginx sshd mysqld)

# Файл логов
logfile="/var/log/service_monitor.log"

for svc in "${services[@]}"; do
status=$(systemctl is-active "$svc")

if [[ "$status" != "active" ]]; then
echo "$(date '+%F %T') ❗️ Сервис $svc статус: $status. Перезапускаем..." >> "$logfile"
systemctl restart "$svc"

if [[ $? -eq 0 ]]; then
echo "$(date '+%F %T') ✔️ Сервис $svc успешно перезапущен" >> "$logfile"
else
echo "$(date '+%F %T') Не удалось перезапустить $svc" >> "$logfile"
fi
fi
done


🗓️ Как запустить по расписанию
Добавьте в crontab (например, каждый 5-й минут):


*/5 * * * * /path/to/service_monitor.sh



🔎 Пара совета по регулярным выражениям
Для анализа логов удобно собирать все строки с ошибками:


grep -Ei "(error|fail|critical|panic)" /var/log/syslog


-E включает расширенные регэкспы
-i — нечувствительность к регистру
Настройте свой набор ключевых слов для поиска 🎯


Пишите в комментариях, какие сервисы вы бы добавили в список мониторинга!

👉@bash_srv