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

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

Реклама: @dad_admin
Download Telegram
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Как безопасно обрабатывать файлы с пробелами в именах

Файлы с пробелами, табами и спецсимволами - классическая причина мистических багов в 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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Быстрые текстовые трансформации в 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
👍8🔥5
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
👍8
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
🔥11
Работа с сигналами: 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
👍7
Проверка времени отклика сервисов

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

▪️ Самый простой замер


time curl -s https://bashtex.com > /dev/null


Показывает общее время выполнения запроса и быстро понять, тормозит или нет.

▪️ Точнее: только сетевое время


curl -s -o /dev/null -w "time_total: %{time_total}\n" https://bashtex.com


Полезные метрики:

time_namelookup
time_connect
time_starttransfer
time_total

Пример:


curl -w "DNS:%{time_namelookup} CONNECT:%{time_connect} TTFB:%{time_starttransfer} TOTAL:%{time_total}\n" \
-o /dev/null -s https://bashtex.com


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


for url in https://a.ru https://b.ru; do
curl -o /dev/null -s -w "$url %{time_total}\n" "$url"
done


▪️ Таймаут обязателен


curl --connect-timeout 3 --max-time 5 https://bashtex.com


Без таймаута любой мониторинг бесполезен.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
PIPESTATUS: как узнать, какая команда в пайпе реально упала

В Bash есть неприятная особенность: после пайпа $? показывает статус только последней команды.

Например:

false | grep test

echo $?


Здесь grep успешно отработал и вернул 0, поэтому ошибка false потерялась.

▪️На помощь приходит PIPESTATUS

Сразу после выполнения пайпа:

false | grep test

echo "${PIPESTATUS[@]}"


Получим:

1 1


Каждое значение соответствует своей команде.

false       → 1
grep test → 1


▪️Более наглядный пример

cat /missing/file | grep ERROR | sort

echo "${PIPESTATUS[@]}"


Можно получить:

1 1 0


То есть cat завершился с ошибкой, grep ничего не получил, а sort технически выполнился успешно.

▪️Важный нюанс

PIPESTATUS очень легко потерять:

false | true

echo "${PIPESTATUS[@]}"


работает.

Но если между пайпом и проверкой выполнить другую команду:

false | true

echo "check"
echo "${PIPESTATUS[@]}"


теперь PIPESTATUS относится уже к echo "check".

Поэтому сохраняйте его сразу:

false | true

status=("${PIPESTATUS[@]}")

echo "${status[@]}"


▪️А если нужен общий статус пайпа?

Есть:

set -o pipefail


Теперь:

false | true

echo $?


вернёт ненулевой код.

Но pipefail отвечает только на вопрос «пайп завершился успешно?», а PIPESTATUS позволяет понять «какая именно команда вернула ошибку?».

▪️Почему это важно

В сложных Bash-конвейерах последняя команда может успешно завершиться даже тогда, когда предыдущая уже упала. PIPESTATUS позволяет не терять эти ошибки и точно определить проблемный этап.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👨‍💻5
/proc/PID/fd: как узнать, что на самом деле держит процесс

ps показывает процесс, lsof умеет искать открытые файлы. Но иногда быстрее посмотреть непосредственно в /proc.

У каждого процесса есть каталог:

ls -l /proc/1234/fd


Внутри находятся символические ссылки на все открытые файловые дескрипторы процесса.

▪️Что можно увидеть

Например:

0 -> /dev/null
1 -> /var/log/app.log
2 -> /var/log/app.err
5 -> /tmp/data.db


0, 1 и 2 — стандартные stdin, stdout и stderr. Остальные дескрипторы приложение открыло самостоятельно.

▪️Найти удалённые файлы

Особенно полезен такой поиск:

ls -l /proc/1234/fd | grep deleted


Можно обнаружить:

7 -> /var/log/app.log (deleted)


Файл уже отсутствует в каталоге, но процесс всё ещё держит его открытым.

▪️Посмотреть тип дескриптора

readlink /proc/1234/fd/7


Результат может быть:

socket:[48192]


или:

pipe:[72831]


или:

/run/app.sock


То есть через один каталог можно увидеть не только обычные файлы, но и сокеты, pipes и другие объекты ядра.

▪️Найти все открытые дескрипторы процесса

for fd in /proc/1234/fd/*; do
printf '%s -> %s\n' "${fd##*/}" "$(readlink "$fd")"
done


Получается компактная карта того, с какими объектами взаимодействует процесс.

▪️Почему это важно

Если сервис ведёт себя странно, полезно посмотреть не только его аргументы и память, но и то, что он реально держит открытым.

/proc/PID/fd помогает быстро найти удалённые логи, неожиданные файлы, UNIX-сокеты и каналы IPC - причём без отдельного инструмента анализа.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1
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
🔥6👍1