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

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

Реклама: @dad_admin
Download Telegram
Архитектура большого bash-скрипта

Пока скрипт на 30 строк - все терпимо. На 300 строк начинается хаос. На 1000 - уже никто не понимает, где init, где логика, где cleanup. Чтобы bash не превратился в лапшу, ему нужна архитектура.

📂 Нормальная структура проекта


project/
├── main.sh
├── lib/
│ ├── log.sh
│ ├── config.sh
│ ├── checks.sh
│ └── deploy.sh
├── conf/
│ └── app.conf
└── tmp/


Где:

main.sh - точка входа
lib/ - функции по темам
conf/ - конфиги
tmp/ - временные файлы

▪️ Деление на модули

Не надо держать все в одном файле.
Лучше так:


source "$(dirname "$0")/lib/log.sh"
source "$(dirname "$0")/lib/checks.sh"


Примеры модулей:

log.sh - логгер
config.sh - загрузка переменных
checks.sh - проверки окружения
actions.sh - основная логика

▪️ Naming: единый стиль

Худший вариант:


doStuff()
x()
RunAll()


Лучше:


log_info()
check_dependencies()
deploy_app()
cleanup_tmp()


Для приватных функций можно префикс:


_internal_parse_config()


▪️ Поток исполнения. В начале файла:


main() {
load_config
check_dependencies
run_tasks
}

main "$@"


Это делает скрипт читаемым как программу, а не как свалку команд.

BashTex 📱 #bash #scripts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
Быстрые текстовые трансформации в shell

Когда нужно быстро подправить текст в пайплайне, не обязательно тянуть awk или Python. Три старые утилиты часто закрывают задачу в одну строку:

cut - вырезать нужные поля
paste - склеить строки/колонки
tr - заменить или удалить символы

1️⃣ cut - достать нужный столбец. Например, из /etc/passwd взять только логины:


cut -d: -f1 /etc/passwd


-d: - разделитель
-f1 - первое поле

Несколько полей:


cut -d: -f1,7 /etc/passwd


2️⃣ tr - заменить символы. Поменять запятые на пробелы:


echo "a,b,c" | tr ',' ' '


Удалить символы:


echo "a-b-c" | tr -d '-'


Сделать lowercase - uppercase:


echo "bash rocks" | tr '[:lower:]' '[:upper:]'


3️⃣ paste - склеить строки в одну. Есть файл:


one
two
three


Сделать CSV-строку:


paste -sd, file.txt


Результат:


one,two,three


Склеить два файла построчно:


paste users.txt shells.txt


▪️ Комбинируем. Из /etc/passwd достанем логины и склеим в одну строку:


cut -d: -f1 /etc/passwd | paste -sd,


Или список пакетов в uppercase:


cut -d' ' -f1 packages.txt | tr '[:lower:]' '[:upper:]'


BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥5
А вот накатил бы Linux и работать не надо было бы

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁11👍2
Состояние скрипта между запусками

Многие Bash-скрипты пишутся так, будто они живут один запуск. Но в реальности скрипт могут: остановить, перезапустить, запустить второй раз параллельно или оборвать посреди обработки. Чтобы не делать все заново и не ломать данные, нужны три вещи:

lock - не дать запуститься дважды
state - помнить текущее состояние
checkpoint - знать, с какого места продолжать

1️⃣ Lock: защита от параллельного запуска


LOCK=/tmp/myjob.lock

exec 9>"$LOCK"
flock -n 9 || {
echo "Скрипт уже запущен"
exit 1
}


flock не даст второму экземпляру стартовать одновременно.

2️⃣ State: храним статус в файле. Например:


STATE=/var/tmp/myjob.state
echo "stage=download" > "$STATE"


Или читаем:


source "$STATE"
echo "$stage"


Так можно помнить: текущий этап, последний обработанный файл и время последнего успешного шага

3️⃣ Checkpoint: продолжаем с нужного места. Допустим, обрабатываем список строк:


CHECKPOINT=/var/tmp/myjob.offset
last_done=$(cat "$CHECKPOINT" 2>/dev/null || echo 0)

n=0
while IFS= read -r line; do
((n++))
(( n <= last_done )) && continue

echo "Обрабатываю: $line"

echo "$n" > "$CHECKPOINT"
done < input.txt


Если скрипт упадет на 500-й строке, следующий запуск продолжит с 501-й.

🛠 Итоговая практика


STATE_DIR=/var/tmp/myjob
mkdir -p "$STATE_DIR"

LOCK="$STATE_DIR/lock"
CHECKPOINT="$STATE_DIR/checkpoint"

exec 9>"$LOCK"
flock -n 9 || exit 1

trap 'rm -f "$LOCK"' EXIT


BashTex 📱 #bash #scripts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
case против if: где ветвление читается лучше

▪️ Когда лучше if. Если проверяешь: файл существует или нет, код возврата команды, число больше/меньше или несколько логических условий


if [[ -f config.conf ]]; then
echo "Конфиг найден"
elif [[ -d config.conf ]]; then
echo "Это каталог"
else
echo "Ничего нет"
fi


Здесь if читается естественно.

▪️ Когда лучше case. Если у тебя есть один входной параметр и несколько режимов:


cmd="$1"

case "$cmd" in
start)
echo "Запуск"
;;
stop)
echo "Остановка"
;;
restart)
echo "Перезапуск"
;;
*)
echo "Неизвестная команда"
exit 1
;;
esac


Для CLI это почти всегда лучше, чем цепочка:


if [[ "$cmd" == start ]]; then
...
elif [[ "$cmd" == stop ]]; then
...


▪️ case особенно хорош для шаблонов


case "$file" in
*.log) echo "Лог" ;;
*.conf) echo "Конфиг" ;;
*.sh) echo "Скрипт" ;;
esac


if так не умеет читатьcя так же чисто.

BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍2
find + -exec vs xargs: где удобнее, где безопаснее

Когда нужно выполнить команду для большого количества файлов, чаще всего используют два подхода: find ... -exec или find ... | xargs. Они решают одну задачу, но ведут себя по-разному.

▪️ find -exec - простой и безопасный. Пример: удалить .log файлы старше 7 дней


find /var/log -type f -name "*.log" -mtime +7 -exec rm {} \;


{} - подставляет найденный файл.
\; - завершает команду.

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

▪️ Ускоренный вариант -exec. Можно запускать команду пакетами:


find /var/log -type f -name "*.log" -exec rm {} +


Теперь rm получит много файлов за раз. По скорости это почти как xargs.

▪️ xargs - быстрее для больших списков. Пример:


find /var/log -type f -name "*.log" | xargs rm


xargs собирает много аргументов и запускает команду одним вызовом. Можно ограничить размер батча:


find . -name "*.tmp" | xargs -n 10 rm


⚠️ Главная проблема xargs. Файлы с пробелами ломают команду:


file one.txt
file two.txt


Поэтому правильный вариант:


find . -type f -print0 | xargs -0 rm


Пара:


-print0
xargs -0


делает обработку 100% безопасной.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14👍1
Проверка доступности внутренних портов между серверами

Иногда сервис работает, но приложение всё равно не может подключиться. Одна из частых причин - порт недоступен между серверами: firewall, security group, routing или сервис слушает только localhost

Проверить это можно прямо из shell.

▪️ Самый простой способ - nc (netcat)


nc -zv db-server 5432


-z - проверить порт без передачи данных
-v - показать результат

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


Connection to db-server 5432 port [tcp/postgresql] succeeded!


Или:


Connection refused


▪️ Проверка нескольких портов


for port in 80 443 8080; do
nc -z host "$port" && echo "open: $port"
done


▪️ Чистый bash без утилит - /dev/tcp. Мало кто знает, но bash умеет открывать TCP-соединения:


echo > /dev/tcp/db-server/5432


Если порт открыт - команда завершится без ошибки.

Можно сделать проверку:


if timeout 2 bash -c "</dev/tcp/db-server/5432"; then
echo "Порт открыт"
else
echo "Порт закрыт"
fi


▪️ Проверка списка серверов. Простой скрипт:


servers="app1 app2 app3"
port=6379

for host in $servers; do
if nc -z "$host" "$port" 2>/dev/null; then
echo "$host OK"
else
echo "$host FAIL"
fi
done


BashTex 📱 #bash #network
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Отслеживание появления новых файлов и их автоархивация

Иногда нужно автоматически реагировать на новые файлы: сервис складывает логи, система генерирует отчеты или приложение пишет дампы Вместо cron-сканирования каталога можно использовать inotify - это механизм ядра linux для отслеживания изменений файловой системы.

▪️ Слушаем каталог. Инструмент - inotifywait (пакет inotify-tools). Простейший пример:


inotifywait -m /data/incoming -e create


-m - режим постоянного мониторинга
-e create - событие создания файла

🛠 Скрипт автоархивации


#!/usr/bin/env bash

WATCH_DIR="/data/incoming"
ARCHIVE_DIR="/data/archive"

mkdir -p "$ARCHIVE_DIR"

inotifywait -m -e create --format '%f' "$WATCH_DIR" | while read -r file; do
echo "Новый файл: $file"

tar -czf "$ARCHIVE_DIR/${file}.tar.gz" -C "$WATCH_DIR" "$file"

echo "Архив создан: ${file}.tar.gz"
done


1. inotifywait ловит появление файла
2. имя файла передаётся в цикл
3. создается архив tar.gz

▪️ Практический кейс Приложение пишет дампы:


dump_001.sql
dump_002.sql
dump_003.sql


Скрипт автоматически делает:


dump_001.sql.tar.gz
dump_002.sql.tar.gz
dump_003.sql.tar.gz


Без cron и без опроса каталога.

⚠️ Важный нюанс. Иногда файл появляется до завершения записи. Лучше ловить событие close_write:


inotifywait -m -e close_write --format '%f' "$WATCH_DIR"


Это означает: файл закрыт после записи.

▪️ Бонус: автоудаление исходника


tar -czf "$ARCHIVE_DIR/${file}.tar.gz" -C "$WATCH_DIR" "$file" && rm "$WATCH_DIR/$file"


Каталог остается чистым.

BashTex 📱 #bash #scripts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Ты ждал знак? Держи!

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
🫡8
Проверка, какие сервисы работают без restart-policy и почему это риск

В systemd у каждого сервиса есть параметр: Restart=

Он определяет, будет ли сервис автоматически перезапущен, если процесс упал. Если политика не задана (Restart=no), сервис может просто умереть и никто его не поднимет. На продакшене это часто означает: API внезапно недоступен, очередь сообщений остановилась или воркер перестал обрабатывать задачи. И система жива, но функционально мертва.

▪️ Быстрая проверка одного сервиса


systemctl show nginx -p Restart


Пример:


Restart=always


или


Restart=no


▪️ Проверка всех сервисов. Можно быстро найти юниты без restart-policy:


systemctl list-units --type=service --no-legend | awk '{print $1}' |
while read -r svc; do
policy=$(systemctl show "$svc" -p Restart --value)
[[ "$policy" == "no" ]] && echo "$svc"
done


Скрипт выведет сервисы, которые не перезапускаются автоматически.

▪️ Хорошие варианты restart-policy. Чаще всего используют:


Restart=on-failure


или


Restart=always


Разница:

on-failure - перезапуск при ошибке
always - перезапуск всегда

▪️ Пример настройки. В unit-файле:


[Service]
Restart=on-failure
RestartSec=5


RestartSec добавляет паузу перед перезапуском. После изменения:


systemctl daemon-reload
systemctl restart myservice


BashTex 📱 #systemd
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Где остаются следы SSH-подключений

Когда вы подключаетесь к серверу по SSH, система оставляет несколько артефактов. Это полезно знать не только с точки зрения безопасности, но и для диагностики и аудита.

Разберем основные места, где фиксируются подключения.

1️⃣ /var/log/auth.log - основной лог SSH. Каждое подключение к SSH фиксируется здесь. Быстро посмотреть успешные входы:


grep 'Accepted' /var/log/auth.log


Если система использует journald, записи можно посмотреть так:


journalctl -u ssh -r


-r покажет события в обратном порядке (сначала последние).

2️⃣ /var/log/wtmp - история логинов. Это бинарный лог, где хранится информация о: входах пользователей, IP-адресах, перезагрузках и выключениях системы. Смотреть его можно командой:


last


Полезный вариант с расширенной информацией:


last -Faiwx


3️⃣ /var/log/lastlog - последний вход каждого пользователя. Файл хранит последнюю дату входа для каждого системного пользователя. Посмотреть:


lastlog


Можно быстро увидеть: кто вообще заходил, когда был последний логин и с какого IP.

4️⃣ /var/run/utmp - текущие активные сессии. Пока пользователь подключен, информация о сессии хранится здесь. Посмотреть активные подключения:


who
#или
w



5️⃣ /var/log/btmp - неудачные попытки входа. Если кто-то ошибся с логином или паролем, запись попадет сюда. Посмотреть:


lastb


Полезно для поиска: ошибок авторизации или сканирования SSH.

6️⃣ ~/.bash_history - история команд. Все команды пользователя обычно сохраняются в файл:


~/.bash_history


Если не хотите записывать историю в файл (например, во время диагностики), можно временно отключить:


export HISTFILE=/dev/null


В текущей сессии history будет работать, но после выхода команды не запишутся на диск.

⚠️ Важный момент. Если сервер отправляет логи во внешнее хранилище, то след о подключении появляется сразу в момент логина.

Поэтому в инфраструктурах часто используют: центральный syslog-сервер, systemd-journal-remote и централизованный сбор логов. Это позволяет видеть историю подключений даже если локальные логи были очищены.

BashTex 📱 #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
tee + process substitution: один поток и несколько получателей

Иногда нужно одновременно: увидеть вывод команды в терминале, записать его в файл и передать на обработку другой программе Если делать это по очереди - потеряется поток данных. Здесь помогает связка tee + process substitution.

▪️ Что делает tee. tee дублирует поток:


command | tee file.log


вывод остается в терминале и одновременно пишется в file.log

▪️ Несколько получателей. tee может писать сразу в несколько файлов:


command | tee out1.log out2.log


Но иногда нужно не просто файл, а другую команду.

▪️ Process substitution. Bash позволяет подставить вывод команды как файл:


>(command)


Это называется process substitution.

▪️ Комбинируем


command | tee >(grep ERROR > errors.log)


command генерирует поток
tee дублирует его

Одна копия идет в терминал, а другая в grep. Если найден ERROR, запись попадет в errors.log.

▪️ Более реальный пример. Допустим, идет сбор логов:


journalctl -f | tee >(grep ERROR >> errors.log)


Теперь: полный поток остается в терминале, ошибки автоматически сохраняются

▪️ Можно делать несколько обработчиков


journalctl -f | tee \
>(grep ERROR >> errors.log) \
>(grep WARN >> warn.log)


Один поток и сразу несколько фильтров.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
Работа с exit codes: как правильно строить логику ошибок

В Bash каждая команда возвращает код завершения: 1 - успех, ≠0 - ошибка. И вся логика скрипта строится именно на этом.

▪️ Базовый принцип


command
echo $?


Но руками $? почти не используют, есть удобнее способы.

▪️ && - выполняй, если успешно


mkdir dir && cd dir


cd выполнится только если mkdir прошел успешно.

▪️ || - выполняй при ошибке


command || echo "Ошибка"


Полезно для fallback-логики.

▪️ Комбинируем


command && echo "OK" || echo "FAIL"


Но тут есть нюанс:

Если echo "OK" упадет (редко, но возможно), сработает || и ты получишь ложный FAIL.

Поэтому для критичной логики лучше:


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


▪️ set -e - автоматический выход при ошибке


set -e


Теперь скрипт завершится при любой ошибке. Но есть подводные камни:


set -e

grep "foo" file.txt
echo "done"


Если grep ничего не найдёт - exit code = 1 и скрипт завершится. Иногда это нормальное поведение, а не ошибка.

▪️ Правильное использование set -e. Обычно пишут так:


set -euo pipefail


Но при этом явно обрабатывают исключения:


grep "foo" file.txt || true


Или:


if grep -q "foo" file.txt; then
echo "Found"
fi


▪️ pipefail - важно для пайпов


set -o pipefail


Без него:


false | true
echo $? # → 0


С pipefail:


false | true
echo $? # → ошибка



▪️ Общие правила:

&& - для цепочек успеха
|| - для fallback
if - для сложной логики
set -e - осторожно
pipefail - почти всегда включать

BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
И да, ему все еще не нужен ИИ

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13
Проверка доступности файловых систем (read/write test)

▪️ Базовая проверка записи


touch /mnt/data/.test && rm /mnt/data/.test


Если команда зависает или падает - есть проблемы с файловой системой.

▪️Проверка с таймаутом


timeout 3 bash -c 'touch /mnt/data/.test && rm /mnt/data/.test'


Теперь: если FS зависла - команда завершится по таймауту, скрипт не повиснет

▪️ Измерение latency. Можно измерить время операции:


start=$(date +%s%N)

touch /mnt/data/.test && rm /mnt/data/.test

end=$(date +%s%N)
echo $(( (end - start)/1000000 )) ms


Если операция занимает:

<10 ms - нормально
100–500 ms - уже подозрительно
секунды - проблема


🛠 Готовый скрипт


#!/usr/bin/env bash

MOUNT="/mnt/data"
TIMEOUT=3

start=$(date +%s%N)

if timeout "$TIMEOUT" bash -c "touch $MOUNT/.test && rm $MOUNT/.test"; then
end=$(date +%s%N)
latency=$(( (end - start)/1000000 ))
echo "OK ($latency ms)"
else
echo "FAIL: FS недоступна или зависла"
fi


▪️ Проверка нескольких точек


for m in /data /backup /nfs; do
echo -n "$m: "
timeout 3 bash -c "touch $m/.test && rm $m/.test" \
&& echo "OK" || echo "FAIL"
done


BashTex 📱 #scripts #filesystem
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Группировка команд {} против () - в чем реальная разница

В Bash есть два способа сгруппировать команды:
{ cmd1; cmd2; } и ( cmd1; cmd2 )

Снаружи выглядят почти одинаково. На практике - это разное поведение.

▪️ Главное отличие

Конструкция, где выполняется

{} - в текущем shell
() - в subshell (дочернем процессе)

▪️ Пример с переменными


count=0

{ count=5; }
echo "$count"


Результат: 5. Теперь с ():


count=0

( count=5 )
echo "$count"


Результат: 0. Переменная изменилась в subshell и пропала.

▪️ Практика: перенаправления. {} удобно для группового редиректа:


{
echo "line1"
echo "line2"
} > file.txt


Обе команды попадут в один файл.

▪️ Изоляция через (). Subshell полезен, когда нужно временно изменить окружение:


( cd /tmp && ls )


После выполнения ты останешься в текущем каталоге.

▪️ Типичный кейс


cd /tmp
do_something
cd -


Можно заменить:


( cd /tmp && do_something )


Без риска забыть вернуться обратно.

BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Как правильно обрабатывать stdin в скриптах

Хороший CLI-скрипт должен уметь принимать данные: из файла, из pipe (|) и из stdin. И делать это предсказуемо.

▪️ Проверка: есть ли stdin


if [ -t 0 ]; then
echo "stdin пуст (ввод с терминала)"
else
echo "данные пришли через pipe"
fi


-t 0 - stdin подключен к терминалу
иначе - есть входной поток

▪️ Базовый шаблон


#!/usr/bin/env bash

if [ -t 0 ]; then
echo "Usage: command < file | pipe"
exit 1
fi

while IFS= read -r line; do
echo ">> $line"
done


Теперь скрипт работает так:


cat file.txt | script.sh


▪️ Универсальный вариант (stdin + файл)


input="${1:-/dev/stdin}"

while IFS= read -r line; do
echo "$line"
done < "$input"
Теперь можно:
script.sh file.txt
cat file.txt | script.sh


🤩 Частая ошибка


for line in $(cat file.txt); do
echo "$line"
done


Она ломает: пробелы, табы и пустые строки

🤩 Правильно


while IFS= read -r line; do
echo "$line"
done < file.txt


BashTex 📱 #scripts #stdin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Контроль роста логов systemd по сервисам

Когда /var/log начинает раздуваться, виноват почти всегда один-два шумных сервиса. Но в journald нет привычных файлов - значит нужно считать по-другому. Значит будем брать сервис, считать объем его логов и сравниваем во времени.

1️⃣ Сколько логов пишет сервис. Пример для nginx:


journalctl -u nginx --since "1 hour ago" | wc -c


Получаем объем логов за час (в байтах).

2️⃣ Быстрый топ шумных сервисов


systemctl list-units --type=service --no-legend | awk '{print $1}' |
while read -r svc; do
size=$(journalctl -u "$svc" --since "1 hour ago" 2>/dev/null | wc -c)
echo "$size $svc"
done | sort -nr | head


Результат:


12345678 docker.service
9876543 nginx.service
1234567 ssh.service


Сразу видно, кто генерирует больше всего логов.

3️⃣ Контроль роста. Сохраняем текущее состояние:


journalctl -u nginx --since "1 hour ago" | wc -c > /tmp/nginx.size


Через время:


old=$(cat /tmp/nginx.size)
new=$(journalctl -u nginx --since "1 hour ago" | wc -c)

echo "Рост: $((new - old)) байт"


4️⃣ Скрипт


#!/usr/bin/env bash

SINCE="10 min ago"
THRESHOLD=1000000 # 1 MB

systemctl list-units --type=service --no-legend | awk '{print $1}' |
while read -r svc; do
size=$(journalctl -u "$svc" --since "$SINCE" 2>/dev/null | wc -c)

if (( size > THRESHOLD )); then
echo "ALERT: $svc → $size bytes за $SINCE"
fi
done


BashTex 📱 #systemd #logs
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🔈 Новый VPS/VDS-сервис от упоротых инфраструктурщиков

Давно дружим с CORTEL, это ребята про enterprise решения для крупняка. Сейчас они запустили отдельный бренд для аренды VPS/VDS — Serverum.

Это сервис, где можно выбрать VPS, оплатить и сразу начать пользоваться. Подойдёт для dev/stage-сред, тестовых стендов, ботов, pet-проектов, небольших сервисов и других задач, где нужен сервер без лишней возни.

Внутри:
— собственная проприетарная платформа
— отечественные решения
— защищённая инфраструктура
— низкие цены
— живая поддержка от инженерной команды

Сейчас ребята запускают первых пользователей и собирают честную обратную связь от тех, кто реально работает с инфраструктурой.
Можно зайти, потыкать, взять VPS под задачу и написать фидбек.

👉 Serverum.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
Работа с сигналами: SIGTERM, SIGINT, SIGHUP

Любой процесс в linux можно остановить сигналом. Если скрипт их не обрабатывает - он просто умирает, иногда оставляя: временные файлы, lock-файлы или незавершённые операции

▪️ Основные сигналы

SIGINT - (2) - Ctrl+C
Остановка пользователем

SIGTERM (15) - вежливое завершение - systemctl stop / kill
Дает процессу шанс корректно завершиться.

SIGHUP (1) - перечитай конфиг
часто используется для reload

▪️ Обработка сигналов через trap


trap 'echo "Получен SIGINT"; cleanup; exit 1' INT
trap 'echo "Получен SIGTERM"; cleanup; exit 0' TERM


Теперь скрипт не просто падает, а выполняет cleanup.

▪️ Пример cleanup


cleanup() {
echo "Чистка..."
rm -f /tmp/my.lock
}


▪️ Полный пример


#!/usr/bin/env bash

LOCK=/tmp/job.lock
touch "$LOCK"

cleanup() {
echo "Удаляю lock"
rm -f "$LOCK"
}

trap cleanup EXIT
trap 'echo "SIGINT"; exit 1' INT
trap 'echo "SIGTERM"; exit 0' TERM

while true; do
echo "Работаю..."
sleep 2
done


Теперь:

Ctrl+C - корректное завершение
kill - cleanup выполняется
скрипт не оставляет мусор

Не все сигналы можно перехватить. Нельзя поймать: SIGKILL (9)
Если прилетит kill -9 - все, без cleanup.

BashTex 📱 #scripts #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4