ch
Feedback
BashTex | Linux

BashTex | Linux

前往频道在 Telegram

Авторский канал для тех, кто хочет глубже погрузиться в мир Linux. Подойдет для разработчиков, системных администраторов и DevOps Реклама: @dad_admin

显示更多
2 530
订阅者
-124 小时
+167
-930

数据加载中...

相似频道
无数据
有任何问题?请刷新页面或联系我们的客服
进出提及
---
---
---
---
---
---
吸引订阅者
六月 '26
六月 '26
+18
在4个频道中
五月 '26
+8
在0个频道中
Get PRO
四月 '26
+14
在0个频道中
Get PRO
三月 '26
+22
在0个频道中
Get PRO
二月 '26
+18
在0个频道中
Get PRO
一月 '26
+85
在5个频道中
Get PRO
十二月 '25
+122
在19个频道中
Get PRO
十一月 '25
+93
在2个频道中
Get PRO
十月 '25
+107
在7个频道中
Get PRO
九月 '25
+197
在20个频道中
Get PRO
八月 '25
+16
在1个频道中
Get PRO
七月 '25
+130
在13个频道中
Get PRO
六月 '25
+57
在4个频道中
Get PRO
五月 '25
+70
在1个频道中
Get PRO
四月 '25
+728
在23个频道中
Get PRO
三月 '25
+129
在6个频道中
Get PRO
二月 '25
+235
在9个频道中
Get PRO
一月 '25
+497
在19个频道中
Get PRO
十二月 '24
+134
在8个频道中
Get PRO
十一月 '24
+819
在17个频道中
日期
订阅者增长
提及
频道
04 六月0
03 六月+1
02 六月+5
01 六月+12
频道帖子
Когда переменные пропадают Одна из частых ловушек в bash - переменная изменилась… но снаружи осталась прежней. Причина почти всегда одна - subshell. ▪️ Что такое subshell. Subshell - это дочерний процесс bash. Он получает копию переменных, но изменения не возвращаются назад. Создается, например, здесь:

( command )
или в пайпах:

command | while read ...
▪️ Классическая проблема

count=0

echo -e "a\nb\nc" | while read -r line; do
  ((count++))
done

echo "$count"
Результат: 0 Почему? Цикл while выполняется в subshell. ▪️ Правильный вариант

count=0

while read -r line; do
  ((count++))
done < <(echo -e "a\nb\nc")

echo "$count"
Результат: 3 Теперь цикл работает в текущем shell. ▪️ Ещё пример

x=1

( x=5 )

echo "$x"
Результат: 1 Изменение потерялось. ▪️ Когда это полезно. Subshell - это не баг, а инструмент. Например:

( cd /tmp && ls )
внутри меняем каталог, а снаружи остаемся там же BashTex 📱 #scripts

2
Подготовка к DevOps/SRE интервью с «Troubleshooting Docker и Kubernetes: поиск и устранение проблем» В программе только важны
Подготовка к DevOps/SRE интервью с «Troubleshooting Docker и Kubernetes: поиск и устранение проблем» В программе только важные аспекты: — troubleshooting Docker и образов — диагностика сетевых проблем — настройка readiness/liveness probes — отладка pod’ов, деплоев и ingress — анализ логов контейнеров и кластера — разбор ошибок CrashLoopBackOff, OOMKilled, ImagePullBackOff и других Собеседования на DevOps/SRE сейчас всё чаще строятся вокруг реальных инцидентов. Данный курс фокусируется именно на таких сценариях и помогает в подготовке к практическим вопросам 48 часов доступен со скидкой 25% ↗️ Пройти курс на Stepik
288
3
Вы бы знали, чего это стоило.. BashTex 📱 #юмор
Вы бы знали, чего это стоило.. BashTex 📱 #юмор
340
4
Работа с сигналами: 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
338
5
🔈 Новый VPS/VDS-сервис от упоротых инфраструктурщиков Давно дружим с CORTEL, это ребята про enterprise решения для крупняка.
🔈 Новый VPS/VDS-сервис от упоротых инфраструктурщиков Давно дружим с CORTEL, это ребята про enterprise решения для крупняка. Сейчас они запустили отдельный бренд для аренды VPS/VDS — Serverum. Это сервис, где можно выбрать VPS, оплатить и сразу начать пользоваться. Подойдёт для dev/stage-сред, тестовых стендов, ботов, pet-проектов, небольших сервисов и других задач, где нужен сервер без лишней возни. Внутри: — собственная проприетарная платформа — отечественные решения — защищённая инфраструктура — низкие цены — живая поддержка от инженерной команды Сейчас ребята запускают первых пользователей и собирают честную обратную связь от тех, кто реально работает с инфраструктурой. Можно зайти, потыкать, взять VPS под задачу и написать фидбек. 👉 Serverum.ru
348
6
Контроль роста логов 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
376
7
Как правильно обрабатывать 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
470
8
Группировка команд {} против () - в чем реальная разница В 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
449
9
Проверка доступности файловых систем (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
484
10
И да, ему все еще не нужен ИИ BashTex 📱 #юмор
И да, ему все еще не нужен ИИ BashTex 📱 #юмор
506
11
Работа с 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
430
12
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
572
13
Где остаются следы 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
593
14
Проверка, какие сервисы работают без 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
583
15
Ты ждал знак? Держи! BashTex 📱 #юмор
Ты ждал знак? Держи! BashTex 📱 #юмор
605
16
Отслеживание появления новых файлов и их автоархивация Иногда нужно автоматически реагировать на новые файлы: сервис складывает логи, система генерирует отчеты или приложение пишет дампы Вместо 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
598
17
Проверка доступности внутренних портов между серверами Иногда сервис работает, но приложение всё равно не может подключиться. Одна из частых причин - порт недоступен между серверами: 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
731
18
🌚 BashTex 📱 #юмор
🌚 BashTex 📱 #юмор
724
19
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
785
20
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
641