BashTex | Linux
2.49K subscribers
44 photos
8 videos
274 links
Авторский канал для тех, кто хочет глубже погрузиться в мир Linux.

Подойдет для разработчиков, системных администраторов и DevOps

Реклама: @dad_admin
Download Telegram
Меньше if и больше логики в одну строку

Когда вы пишете:


if command; then
echo "OK"
else
echo "Fail"
fi


В мире плачет один котенок…🥺 Ведь есть куда более лаконичная альтернатива:


command && echo "OK" || echo "Fail"


Это логические цепочки (&& и ||), которые позволяют писать коротко и эффективно.

▪️ Принцип short-circuit логики

Bash, как и многие языки, останавливает выполнение цепочки, если уже ясно, что дальше не нужно:

cmd1 && cmd2 - cmd2 выполняется только если cmd1 завершилась успешно (exit 0).
cmd1 || cmd2 - cmd2 выполняется только если cmd1 завершилась с ошибкой (exit ≠ 0).

▪️ Примеры таких условий

📍 Минимизация if:


mkdir newdir && cd newdir


создаст и сразу перейдёт, только если каталог успешно создан.

📍 Команда с fallback:


cp file.txt backup/ || echo "Не удалось скопировать!"


Если cp не удался - сработает echo.

📍 Успех или откат:


make build && echo "Успешно" || echo "Ошибка"


Если echo "Успешно" завершится с ошибкой (что редко, но возможно), то сработает и ||.
Чтобы избежать этого, оберните в скобки:


make build && { echo "Успешно"; } || { echo "Ошибка"; }


📍 Цепочка нескольких условий:


[ -d logs ] && cd logs && ls || echo "Нет каталога logs"


Проверяем наличие каталога
Если есть - заходим и выводим содержимое
Если нет - сообщение

📍 Проверка переменной:


[[ -n $API_KEY ]] && echo "Ключ найден" || echo "Нет ключа"


▪️Более сложные варианты использования

📍 Комбинирование условий:


[[ -f $file && -s $file ]] && echo "Файл существует и не пуст"


📍 Логическая цепочка до первой ошибки:


do_step1 && do_step2 && do_step3 || echo "Ошибка на одном из этапов"


📍 Псевдо-транзакции:


backup && update && restart || rollback


Если что-то пошло не так - rollback.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Продуманно

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁22👨‍💻1
Автоматическое масштабирование ресурсов контейнеров

Казалось бы, нетривиальная задача - нужно, чтобы контейнер автоматически подстраивался под нагрузку: добавлял CPU/memory, когда процесс задыхается, и освобождал ресурсы при простое. Все это без kubernetes, без swarm, просто bash + docker API. Попробуем реализовать.

▪️ План скрипта:

Скрипт опрашивает docker stats --no-stream
Сравнивает текущую загрузку CPU/памяти с порогами
При превышении - обновляет лимиты контейнера через docker update
При простое - возвращает лимиты назад
Все это циклически, с логированием и защитой от дребезга (частых переключений)


🛠 Пример скрипта (называться пусть будет auto-scale.sh)


#!/usr/bin/env bash

CONTAINER="webapp"
CPU_MAX=200000 # 200% CPU
CPU_MIN=50000 # 50% CPU
MEM_MAX="1g"
MEM_MIN="256m"

LOGFILE="/var/log/docker_autoscale.log"
INTERVAL=30
STABILITY=3 # сколько циклов подряд должна держаться нагрузка

cpu_high=0
cpu_low=0

log() { echo "$(date '+%F %T') $*" >> "$LOGFILE"; }

while true; do
read cpu mem <<<$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" "$CONTAINER" \
| awk -F'[ %/]' '{printf "%d %d", $1, $2}')

if (( cpu > 80 )); then
((cpu_high++))
cpu_low=0
elif (( cpu < 30 )); then
((cpu_low++))
cpu_high=0
fi

if (( cpu_high >= STABILITY )); then
log "High load detected ($cpu%). Increasing limits..."
docker update --cpus="2.0" --memory="$MEM_MAX" "$CONTAINER" >/dev/null
cpu_high=0
elif (( cpu_low >= STABILITY )); then
log "Low load detected ($cpu%). Decreasing limits..."
docker update --cpus="0.5" --memory="$MEM_MIN" "$CONTAINER" >/dev/null
cpu_low=0
fi

sleep "$INTERVAL"
done


BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
Генерация таблиц прогресса

Реализация живой таблицы прогресса выполнения сприпта, обновляемой прямо в терминале - без внешних тулз, только tput, trap. Звучит заманчиво.


🛠 Скрипт:


#!/usr/bin/env bash

tasks=("Backup" "Sync configs" "Rebuild cache" "Restart services" "Cleanup")
total=${#tasks[@]}
done=0

# Убираем курсор
tput civis

# При выходе вернуть курсор
trap 'tput cnorm; echo' EXIT

# Заголовок таблицы
printf "%-20s | %-10s | %-10s\n" "Task" "Status" "Progress"
printf -- "---------------------------------------------\n"

# Печатаем пустые строки под таблицу
for ((i=0; i<total; i++)); do
printf "%-20s | %-10s | %-10s\n" "${tasks[i]}" "Pending" "0%"
done

# Запоминаем позицию курсора для обновлений
start_row=$(tput lines)
start_row=$((start_row - total))

# Функция обновления строки
update_row() {
local idx=$1
local status=$2
local progress=$3
tput cup $((start_row + idx)) 0
printf "%-20s | %-10s | %-10s\n" "${tasks[idx]}" "$status" "$progress"
}

# Основной цикл выполнения
for i in "${!tasks[@]}"; do
for p in {10..100..10}; do
update_row "$i" "Running" "${p}%"
sleep 0.1
done
update_row "$i" "Done" "100%"
done

tput cnorm
echo -e "\nВсе задачи завершены!"


▪️ Пояснения:

tput civis / cnorm - скрывает и возвращает курсор.
tput cup row col - перемещает курсор для перерисовки конкретной строки.
trap '...' EXIT - гарантирует возврат нормального состояния терминала даже при Ctrl+C.
printf с фиксированной шириной (%-20s) создает выровненную таблицу.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
This media is not supported in your browser
VIEW IN TELEGRAM
Мужчины мечтают только об одном…

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13🔥3🫡3
Создание песочницы для экспериментов

Иногда нужно проверить какую-то команду, поиграться с конфигами или собрать пакет - но без риска сломать систему. Для этого в linux можно сделать свою мини-песочницу, используя старое доброе chroot и немного bash.

chroot - это механизм, который меняет корень файловой системы для процесса. Все, что он видит, находится внутри изолированного каталога, и даже rm -rf / не затронет настоящую систему (если, конечно, настроено правильно 🤓).


🛠 Скрипт создающий песочницу:


#!/usr/bin/env bash

SANDBOX="/opt/sandbox"
DEBIAN_MIRROR="https://deb.debian.org/debian"
ARCH=$(dpkg --print-architecture)

# Проверка зависимостей
for cmd in debootstrap chroot mount umount; do
command -v $cmd >/dev/null || { echo "$cmd not found"; exit 1; }
done

# Создание окружения, если нет
if [[ ! -d "$SANDBOX" ]]; then
echo "Создаю минимальную систему Debian..."
sudo debootstrap --arch="$ARCH" stable "$SANDBOX" "$DEBIAN_MIRROR"
fi

# Монтируем системные точки
sudo mount -t proc /proc "$SANDBOX/proc"
sudo mount --rbind /sys "$SANDBOX/sys"
sudo mount --rbind /dev "$SANDBOX/dev"

# Добавим базовые бинари для экспериментов
sudo cp /bin/bash "$SANDBOX/bin/"
sudo cp /usr/bin/ls "$SANDBOX/usr/bin/"

echo "Входим в песочницу!"
sudo chroot "$SANDBOX" /bin/bash

# После выхода - очистка
echo "Отмонтирую ресурсы..."
sudo umount -l "$SANDBOX/proc" "$SANDBOX/sys" "$SANDBOX/dev"


Здесь:

debootstrap ставит минимальный Debian прямо в каталог (/opt/sandbox)
mount подключает системные псевдофайловые системы (/proc, /sys, /dev)
chroot запускает bash внутри нового корня
После выхода - все отмонтируется, и можно просто удалить /opt/sandbox


BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Сравнение конфигураций между серверами

Иногда нужно понять, чем конфиги на dev и prod отличаются, но без полного копирования или внешних тулз.

Задача:

Сравнить /etc/nginx/ и /etc/systemd/ между двумя серверами, чтобы увидеть, какие файлы изменены, добавлены или удалены.


🛠 Пример скрипта:


#!/usr/bin/env bash

REMOTE="[email protected]"
DIRS=("/etc/nginx" "/etc/systemd")
TMPDIR="/tmp/config-compare"
LOG="/tmp/config-diff.log"

mkdir -p "$TMPDIR"
> "$LOG"

for dir in "${DIRS[@]}"; do
echo "Checking $dir ..." | tee -a "$LOG"

rsync -avz --dry-run --delete "$REMOTE:$dir/" "$dir/" \
| grep -E '^deleting|^>f' \
| sed "s|^|$dir/ |" \
>> "$TMPDIR/rsync.diff"
done

if [[ -s "$TMPDIR/rsync.diff" ]]; then
echo -e "\nDifferences found:\n" | tee -a "$LOG"
cat "$TMPDIR/rsync.diff" | tee -a "$LOG"
else
echo "Configurations match across all directories." | tee -a "$LOG"
fi


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

rsync --dry-run --delete - имитирует синхронизацию, но ничего не меняет, выводит список различий между каталогами.
grep -E '^>f|^deleting' - фильтрует только изменения (новые или удалённые файлы).

▪️ Расширение скрипта при необходимости:

1️⃣ Сравнение содержимого файлов:


ssh "$REMOTE" "cat /etc/nginx/nginx.conf" > /tmp/remote.conf
diff -u /etc/nginx/nginx.conf /tmp/remote.conf || echo "nginx.conf differs!"


2️⃣ Генерация markdown отчета:


echo -e "## Config diff report\n\`\`\`\n$(cat $TMPDIR/rsync.diff)\n\`\`\`" > /tmp/diff_report.md


3️⃣Уведомление в телегу при изменениях:


[[ -s $TMPDIR/rsync.diff ]] && curl -s -F "text=$(cat $TMPDIR/rsync.diff)" \
"https://api.telegram.org/bot$TOKEN/sendMessage?chat_id=$CHAT_ID"


BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Системные уведомления через D-Bus и bash

Bash умеет не только писать логи в консоль - он может отправлять системные уведомления прямо в графическую среду, используя D-Bus. Это хороший способ сообщить пользователю о результатах скрипта, ошибках или завершении задач, не залезая в UI.

1️⃣ Простой способ - notify-send. Самая быстрая интеграция:


notify-send "Бэкап завершен" "Все файлы успешно сохранены" --icon=dialog-information


Работает через D-Bus (org.freedesktop.Notifications). Можно добавить приоритет, срок жизни, категории:


notify-send \
--urgency=critical \
--expire-time=10000 \
--app-name="BackupScript" \
"Ошибка резервного копирования" \
"Недостаточно места на диске!"


2️⃣ Напрямую через dbus-send. Если notify-send недоступен (например, в минимальной среде),
можно напрямую вызвать метод D-Bus:


dbus-send --session --type=method_call \
--dest=org.freedesktop.Notifications \
/org/freedesktop/Notifications \
org.freedesktop.Notifications.Notify \
string:"BashScript" \
uint32:0 \
string:"dialog-warning" \
string:"Системное уведомление" \
string:"Задача завершена с ошибками" \
array:string:"ОК" \
dict:string:string: \
int32:-1


Выглядит громоздко, но это чистый вызов через D-Bus, минуя внешние обертки. Можно внедрить в сценарии, где нужно абсолютное управление уведомлениями.

3️⃣ Уведомления в фоновом режиме. Если скрипт работает из cron или systemd-сервиса, нужно указать сеансовую шину D-Bus пользователя. Например, так:


export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
notify-send "Backup completed" "Проверено $(date)"


Это позволяет отправлять уведомления от root в сессию конкретного пользователя.

4️⃣ Практический пример


#!/usr/bin/env bash

export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"

TASK="Резервное копирование /home"
notify-send "Начато" "$TASK..."

if tar czf /backup/home_$(date +%F).tar.gz /home 2>/dev/null; then
notify-send "Успешно" "$TASK завершено"
else
notify-send "Ошибка" "$TASK не выполнено"
fi


Каждое выполнение скрипта будет сопровождаться визуальными уведомлениями в системе.

▪️ Динамические уведомления. Можно обновлять уведомление (пример для GNOME/KDE, не все среды поддерживают):


ID=$(notify-send "Выполняется резервное копирование..." --print-id)
sleep 5
notify-send "Завершено" "Файлы успешно сохранены" --replace-id="$ID"


BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2🤨1
Вставка последнего аргумента без копипасты

Сколько раз вы выполняли команду, вроде:


cp file.txt /tmp/somedir/


а потом через секунду нужно:


cd /tmp/somedir/


и снова набираете руками путь или выделяете путь?
Есть способ не повторять последнее слово - bash это помнит.

1️⃣ Alt + . - вставка последнего аргумента

В любой момент нажмите Alt + . - и bash подставит последний аргумент предыдущей команды.


cp file.txt /tmp/somedir/
cd <Alt+.>


превратится в


cd /tmp/somedir/


Нажимайте Alt + . несколько раз, чтобы пройтись по аргументам из истории (Bash перебирает их назад).

2️⃣ Альтернатива: !$ и !. Тоже самое, но в виде подстановки из истории:


cd !$


или


cd !.


!$ - последний аргумент предыдущей команды.
!. - то же самое, но безопаснее (некоторые шеллы по-разному интерпретируют $).

3️⃣ Примеры

Быстрое удаление того, что только что создали:


mkdir new_dir
rm -r !$


Скопировали и сразу зашли:


cp -r project /opt/
cd !$


Переместили файл и открыли его в редакторе:


mv data.log /var/log/archive/
nano !$


Копируете в несколько мест подряд:


cp backup.tar.gz /mnt/usb/
cp !$ /srv/backups/


BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1😁1