ru
Feedback
BashTex | Linux

BashTex | Linux

Открыть в Telegram

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

Больше
2 522
Подписчики
Нет данных24 часа
+77 дней
-1030 день
Архив постов
🌚 BashTex 📱 #юмор
🌚 BashTex 📱 #юмор

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

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

Состояние скрипта между запусками Многие 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

А вот накатил бы Linux и работать не надо было бы BashTex 📱 #юмор
А вот накатил бы Linux и работать не надо было бы BashTex 📱 #юмор

Быстрые текстовые трансформации в 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

Архитектура большого 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

Автоматическая ротация дампов БД по дням недели Не всегда нужно хранить десятки одинаковых дампов. Для многих задач хватает схемы: 7 файлов по дням недели, где каждый новый дамп перезаписывает соответствующий день. Идея простая: в понедельник - backup-mon.sql во вторник - backup-tue.sql через неделю цикл повторяется 🛠 Пример для PostgreSQL

#!/usr/bin/env bash

BACKUP_DIR="/var/backups/db"
DB_NAME="mydb"
DB_USER="postgres"

day=$(date +%a | tr '[:upper:]' '[:lower:]')   # mon, tue, wed...
file="$BACKUP_DIR/backup-$day.sql"

mkdir -p "$BACKUP_DIR"

pg_dump -U "$DB_USER" "$DB_NAME" > "$file"
echo "Backup saved to $file"
🛠 Пример для MySQL

#!/usr/bin/env bash

BACKUP_DIR="/var/backups/db"
DB_NAME="mydb"
DB_USER="root"

day=$(date +%a | tr '[:upper:]' '[:lower:]')
file="$BACKUP_DIR/backup-$day.sql"

mkdir -p "$BACKUP_DIR"

mysqldump -u "$DB_USER" "$DB_NAME" > "$file"
echo "Backup saved to $file"
▪️ Сжатие для экономии места

mysqldump -u "$DB_USER" "$DB_NAME" | gzip > "$BACKUP_DIR/backup-$day.sql.gz"
▪️ Cron-запуск

0 2 * * * /usr/local/bin/db-backup.sh
Каждую ночь в 02:00 дамп будет обновлять файл нужного дня. BashTex 📱 #backup

Ого, платный Arch BashTex 📱 #юмор
Ого, платный Arch BashTex 📱 #юмор

Как безопасно обрабатывать файлы с пробелами в именах Файлы с пробелами, табами и спецсимволами - классическая причина мистических багов в bash. Скрипт вроде работает… пока не встретит файл типа: my file.txt или backup (old).tar.gzАнти-паттерн

for f in $(ls); do
  echo "$f"
done
Проблема: bash режет вывод по пробелам и переводам строк. Файл my file.txt превратится в два разных слова. ➕ Правильный способ №1 - glob + кавычки

for f in *; do
  echo "$f"
done
Почему это безопаснее: * раскрывается самим shell; каждый элемент цикла - это отдельное имя файла; кавычки сохраняют пробелы. Если нужен определённый тип:

for f in *.log; do
  [[ -e "$f" ]] || continue
  echo "$f"
done
[[ -e "$f" ]] защищает, если совпадений нет. ➕ Правильный способ №2 - find -print0. Для рекурсивного обхода:

find . -type f -print0 | while IFS= read -r -d '' f; do
  echo "$f"
done
Почему это хорошо: -print0 разделяет файлы нулевым байтом; это безопасно даже для пробелов, табов и спецсимволов; read -d '' читает до NUL, а не до пробела. ▪️ Безопасная передача в xargs

find . -type f -print0 | xargs -0 rm -f
Пара: -print0 и xargs -0 должны идти вместе. BashTex 📱 #bash #utils

Brace expansion для массовых операций Brace expansion - это встроенная фича, которая позволяет генерировать списки прямо в командной строке. Работает быстро, читаемо и без лишних for. ▪️ Диапазоны чисел

echo {1..5}

1 2 3 4 5
С шагом:

echo {1..10..2}

1 3 5 7 9
▪️ Диапазоны букв

echo {a..e}

a b c d e
▪️ Массовое создание файлов

touch file_{1..5}.txt
Создаст:

file_1.txt
file_2.txt
...
▪️ Создание каталогов

mkdir -p project/{src,bin,config,logs}
Результат:

project/src
project/bin
project/config
project/logs
▪️ Комбинирование

echo {dev,prod}_{1..3}

dev_1 dev_2 dev_3 prod_1 prod_2 prod_3
▪️ Практика: быстрые шаблоны. Создать структуру окружений

mkdir -p env/{dev,stage,prod}/{logs,tmp,data}
Создать пачку логов

touch log_{2024..2026}_{01..12}.log
Удаление группы файлов

rm file_{1..10}.txt
⚠️ Важный момент. Brace expansion происходит до выполнения команды. Это не цикл и не glob. Например:

echo file_{1..3}.txt
сначала превращается в:

echo file_1.txt file_2.txt file_3.txt
BashTex 📱 #bash #utils

Автоматическая очистка старых systemd-журналов systemd-journal удобен, но есть проблема - логи могут занять гигабайты диска, особенно на загруженных серверах. ▪️ Сколько сейчас занимают журналы

journalctl --disk-usage

Archived and active journals take up 2.3G on disk
▪️ Очистка по размеру. Оставить, например, не больше 500 МБ:

journalctl --vacuum-size=500M
Удалятся самые старые записи, пока объем не станет ~ 500 МБ. ▪️ Очистка по времени. Оставить только последние 7 дней:

journalctl --vacuum-time=7d
Поддерживаются: d - дни h - часы m - минуты
▪️ Комбинированный подход. Часто используют оба ограничения:

journalctl --vacuum-time=7d
journalctl --vacuum-size=1G
Это дает контроль и по времени, и по размеру. ▪️ Добавление в cron

0 3 * * * /usr/bin/journalctl --vacuum-time=7d --vacuum-size=1G
▪️ Постоянная настройка через journald. Чтобы не чистить вручную:

/etc/systemd/journald.conf
Пример:

SystemMaxUse=1G
SystemKeepFree=500M
MaxRetentionSec=7day
После изменения:

systemctl restart systemd-journald
BashTex 📱 #bash

Как работать с большими файлами без загрузки в память Частая ошибка: пытаться обработать большой файл, загружая его целиком в память. Например:

content=$(cat huge.log)
Если файл весит несколько гигабайт - скрипт может съесть всю RAM или просто упасть. Правильный подход - обрабатывать файл потоково. ▪️ Чтение файла построчно. Самый безопасный способ:

while IFS= read -r line; do
    echo "$line"
done < huge.log
файл читается строка за строкой; память почти не используется; можно обрабатывать очень большие файлы. ▪️ Использование grep / awk. Unix-утилиты работают потоково, поэтому идеально подходят для больших файлов. Например:

grep ERROR huge.log
или:

awk '/ERROR/ {print $0}' huge.log
Они читают файл частями, не загружая его полностью. ▪️ Анализ логов. Быстрый пример анализа:

grep ERROR huge.log | awk '{print $5}' | sort | uniq -c
Это обработает гигабайтные логи за секунды. ▪️ tail для живых логов. Если файл постоянно растет:

tail -F huge.log
Можно фильтровать сразу:

tail -F huge.log | grep ERROR
Это удобно для мониторинга сервисов. ▪️ Чтение файла частями. Иногда нужно обрабатывать батчами:

split -l 100000 huge.log part_
Файл разобьется на куски:

part_aa
part_ab
part_ac
Теперь их можно обрабатывать параллельно. BashTex 📱 #bash #utils

Использование /dev/null правильно /dev/null - это специальное устройство в linux, которое принимает любые данные и просто их выбрасывает. Часто используется, когда нужно убрать лишний вывод команд. ▪️ Отключаем stdout. Если команда выводит много информации:

ls /tmp > /dev/null
Теперь stdout (fd 1) будет игнорироваться. ▪️ Отключаем только ошибки. Если нужно скрыть stderr (fd 2):

ls /no/such/file 2> /dev/null
Ошибки исчезнут, но нормальный вывод останется. ▪️ Полное подавление вывода. Иногда нужно убрать все:

command > /dev/null 2>&1
Что происходит: stdout в /dev/null и stderr туда же ▪️ Пример:

curl -s https://bashtex.com > /dev/null 2>&1
Команда выполняется тихо. ▪️ Проверка команды без мусора. Полезный паттерн:

command -v docker > /dev/null 2>&1
Проверяем наличие команды:

if command -v docker > /dev/null 2>&1; then
    echo "Docker установлен"
fi
🤩 Частая ошибка. Некоторые пишут:

command 2>&1 > /dev/null
Это не то же самое. Правильный порядок:

command > /dev/null 2>&1
Потому что редиректы выполняются слева направо. ▪️ Практические кейсы. Проверка файла

test -f file.txt > /dev/null 2>&1
Проверка сервиса

systemctl is-active nginx > /dev/null
Проверка сети

ping -c1 google.com > /dev/null 2>&1
BashTex 📱 #bash #utils

Нет времени объяснять, накатывай Linux BashTex 📱 #юмор
Нет времени объяснять, накатывай Linux BashTex 📱 #юмор

Проверка, какие сервисы стартуют дольше всего Если сервер долго загружается, проблема часто не в системе в целом, а в одном-двух медленных сервисах. В systemd есть встроенный инструмент для такой диагностики - systemd-analyze. ▪️ Смотрим самые медленные сервисы. Самая полезная команда:

systemd-analyze blame
Пример вывода:

8.532s docker.service
4.921s networkd-wait-online.service
3.102s postgresql.service
1.876s nginx.service
Список уже отсортирован по времени запуска. Что это значит: docker.service запускался 8.5 секунд networkd-wait-online.service ждал сеть почти 5 секунд Именно такие сервисы чаще всего замедляют загрузку. ▪️ Смотрим цепочку зависимостей. Иногда сервис запускается быстро, но ждет другой сервис. Проверить можно так:

systemd-analyze critical-chain
Пример:

graphical.target
└─docker.service
  └─network-online.target
    └─systemd-networkd-wait-online.service
Это показывает кто кого блокирует при загрузке. ▪️ Общая статистика загрузки. Полезная команда:

systemd-analyze
Пример:

Startup finished in 3.112s (kernel)
                + 9.842s (userspace)
Здесь видно: время загрузки ядра время загрузки systemd сервисов ▪️Частые причины медленной загрузки. Чаще всего тормозят: networkd-wait-online.service docker.service snapd.service базы данных storage-сервисы Иногда сервис ждет ресурс, который ему не нужен. BashTex 📱 #linux #utils

В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн Но где их находить? Как узнавать о них ран
В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн Но где их находить? Как узнавать о них раньше, чем когда все начнут выкладывать фотографии оттуда? Переходите на канал IT-Мероприятия России. В нём каждый день анонсируются мероприятия со всех городов России 📆 в канале размещаются как онлайн, так и оффлайн мероприятия; 👩‍💻 можно найти ивенты по любому стеку: программирование, frontend-backend разработка, кибербезопасность, дата-аналитика, osint, devops и другие; 🎙 разнообразные форматы мероприятий: митапы с коллегами по цеху, конференции и вебинары с известными опытными специалистами, форумы и олимпиады от важных представителей индустрии и многое другое А чтобы не искать по разным форумам и чатам новости о предстоящих ивентах: 🚀 IT-мероприятия Россииподписывайся и будь в курсе всех предстоящих мероприятий!

Современный мониторинг ресурсов Если стандартный top кажется неудобным, а htop - уже привычным, стоит попробовать btop. Это современный мониторинг ресурсов с удобным интерфейсом и большим количеством полезных функций. ▪️ Что показывает btop. В одном окне можно увидеть: загрузку CPU по ядрам использование RAM и swap дисковую активность сетевой трафик список процессов с сортировкой Интерфейс обновляется в реальном времени и выглядит значительно понятнее, чем классические инструменты. ▪️ Установка

sudo apt install btop # Ubuntu / Debian
sudo dnf install btop # RHEL / CentOS / Fedora
sudo pacman -S btop # Arch
▪️ Запуск:

btop
🤩 Что делает его удобным Интерактивный список процессов Можно: сортировать по CPU / RAM убивать процессы фильтровать список ▪️ Клавиши: F9 - kill process F6 - сортировка F - поиск процесса ▪️ Мониторинг сети. btop показывает: входящий / исходящий трафик скорость сети активность интерфейсов Это удобно, когда нужно быстро понять куда уходит трафик. ▪️ Наглядная нагрузка CPU. В отличие от top, здесь видно: загрузку каждого ядра историю нагрузки spikes CPU Очень полезно при диагностике перегрузки сервера. ▪️ Полезные настройки Открыть настройки: ESC Можно изменить: тему интерфейса частоту обновления отображаемые графики сетевые интерфейсы Конфиг хранится в:

~/.config/btop/btop.conf
BashTex 📱 #linux #monitoring

Контроль превышения лимитов ulimit у сервисов Сервис падает без причины, но в логах странные ошибки:
Too many open files Resource temporarily unavailable fork: retry cannot allocate memory
Очень часто это не баг. Это лимиты ulimit. ▪️ Какие лимиты критичны 1️⃣ nofile - открытые файлы. Сколько файловых дескрипторов может открыть процесс. Проверка:

ulimit -n
Или для конкретного процесса:

cat /proc/<PID>/limits | grep "Max open files"
Если видишь 1024, то для прод-сервиса это почти всегда мало. 2️⃣ nproc - количество процессов. Ограничение на число процессов пользователя. Проверка:

ulimit -u

Или:


cat /proc/<PID>/limits | grep "Max processes"

Если приложение активно форкает воркеры - лимит может убить его.

🤩
 
Почему это сложно заметить


сервис стартует нормально
падает только под нагрузкой
в логах нет прямого указания на лимит
systemd может перезапускать бесконечно

▪️
 
Проверка лимитов у systemd-сервиса



systemctl show myservice | grep -E 'LimitNOFILE|LimitNPROC'

Если пусто, то используются дефолтные значения системы.

▪️
 Как исправить
. Создать override:


systemctl edit myservice

Добавить:


[Service]
LimitNOFILE=65535
LimitNPROC=4096

Перезагрузить:


systemctl daemon-reload
systemctl restart myservice

▪️
 Быстрая диагностика падений
. Если сервис падает под нагрузкой:

Проверить 
/proc/<PID>/limits

Посмотреть количество открытых файлов:


ls /proc/<PID>/fd | wc -l

Проверить количество процессов пользователя:


ps -u username | wc -l
BashTex 📱 #bash #check

🖥️ Выбираешь сервер под ИИ? Сначала загляни сюда 23 апреля в 11:00 (МСК) — бесплатный вебинар от CNS: «Как выбрать сервер дл
🖥️ Выбираешь сервер под ИИ? Сначала загляни сюда 23 апреля в 11:00 (МСК) — бесплатный вебинар от CNS: «Как выбрать сервер для ИИ в 2026 году: GPU, TCO и подводные камни» Если ты сейчас разбираешься, что брать под LLM, инференс или RAG — этот час сэкономит тебе кучу времени, нервов и, возможно, бюджета. Что разберём: 🔹 NVIDIA Hopper vs Blackwell — в чём реальная разница под задачи 2026 года, и не переплачиваешь ли ты за архитектуру 🔹 TCO без иллюзий — как считать полную стоимость владения, где прячутся скрытые расходы 🔹 Типичные ошибки при закупке GPU-серверов — скрытые ловушки и как грамотно сопоставить характеристики железа с реальными задачами нейросетей 🔹 Q&A-сессия — спрашивай, отвечаем честно Кому это полезно: — IT-директорам — Архитекторам и администраторам инфраструктуры — Всем, кто строит или планирует on-prem под ML/LLM/RAG 🗓 23 апреля, 11:00–12:00 МСК 📌 Регистрация: webinar.cns-corp.ru #реклама О рекламодателе