Brace expansion для массовых операций
Brace expansion - это встроенная фича, которая позволяет генерировать списки прямо в командной строке. Работает быстро, читаемо и без лишних for.
▪️ Диапазоны чисел
С шагом:
▪️ Диапазоны букв
▪️ Массовое создание файлов
Создаст:
▪️ Создание каталогов
Результат:
▪️ Комбинирование
▪️ Практика: быстрые шаблоны. Создать структуру окружений
Создать пачку логов
Удаление группы файлов
⚠️ Важный момент. Brace expansion происходит до выполнения команды. Это не цикл и не glob. Например:
сначала превращается в:
BashTex📱 #bash #utils
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
echo file_{1..3}.txt
сначала превращается в:
echo file_1.txt file_2.txt file_3.txt
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Как безопасно обрабатывать файлы с пробелами в именах
Файлы с пробелами, табами и спецсимволами - классическая причина мистических багов в bash. Скрипт вроде работает… пока не встретит файл типа:
➖ Анти-паттерн
Проблема: bash режет вывод по пробелам и переводам строк. Файл
➕ Правильный способ №1 - glob + кавычки
Почему это безопаснее: * раскрывается самим shell; каждый элемент цикла - это отдельное имя файла; кавычки сохраняют пробелы.
Если нужен определённый тип:
➕ Правильный способ №2 - find -print0. Для рекурсивного обхода:
Почему это хорошо:
это безопасно даже для пробелов, табов и спецсимволов;
▪️ Безопасная передача в xargs
Пара:
BashTex📱 #bash #utils
Файлы с пробелами, табами и спецсимволами - классическая причина мистических багов в bash. Скрипт вроде работает… пока не встретит файл типа:
my file.txt или backup (old).tar.gz
for f in $(ls); do
echo "$f"
done
Проблема: bash режет вывод по пробелам и переводам строк. Файл
my file.txt превратится в два разных слова.
for f in *; do
echo "$f"
done
Почему это безопаснее: * раскрывается самим shell; каждый элемент цикла - это отдельное имя файла; кавычки сохраняют пробелы.
Если нужен определённый тип:
for f in *.log; do
[[ -e "$f" ]] || continue
echo "$f"
done
[[ -e "$f" ]] защищает, если совпадений нет.
find . -type f -print0 | while IFS= read -r -d '' f; do
echo "$f"
done
Почему это хорошо:
-print0 разделяет файлы нулевым байтом;это безопасно даже для пробелов, табов и спецсимволов;
read -d '' читает до NUL, а не до пробела.
find . -type f -print0 | xargs -0 rm -f
Пара:
-print0 и xargs -0 должны идти вместе.BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Быстрые текстовые трансформации в shell
Когда нужно быстро подправить текст в пайплайне, не обязательно тянуть awk или Python. Три старые утилиты часто закрывают задачу в одну строку:
cut - вырезать нужные поля
paste - склеить строки/колонки
tr - заменить или удалить символы
1️⃣ cut - достать нужный столбец. Например, из
Несколько полей:
2️⃣ tr - заменить символы. Поменять запятые на пробелы:
Удалить символы:
Сделать lowercase - uppercase:
3️⃣ paste - склеить строки в одну. Есть файл:
Сделать CSV-строку:
Результат:
Склеить два файла построчно:
▪️ Комбинируем. Из
Или список пакетов в uppercase:
BashTex📱 #bash #utils
Когда нужно быстро подправить текст в пайплайне, не обязательно тянуть awk или Python. Три старые утилиты часто закрывают задачу в одну строку:
cut - вырезать нужные поля
paste - склеить строки/колонки
tr - заменить или удалить символы
/etc/passwd взять только логины:
cut -d: -f1 /etc/passwd
-d: - разделитель-f1 - первое полеНесколько полей:
cut -d: -f1,7 /etc/passwd
echo "a,b,c" | tr ',' ' '
Удалить символы:
echo "a-b-c" | tr -d '-'
Сделать lowercase - uppercase:
echo "bash rocks" | tr '[:lower:]' '[:upper:]'
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥5
find + -exec vs xargs: где удобнее, где безопаснее
Когда нужно выполнить команду для большого количества файлов, чаще всего используют два подхода:
▪️ find -exec - простой и безопасный. Пример: удалить .log файлы старше 7 дней
Плюсы: безопасно работает с пробелами, не ломается на спецсимволах и не требует пайпа
Но есть нюанс: команда запускается для каждого файла.
▪️ Ускоренный вариант -exec. Можно запускать команду пакетами:
Теперь rm получит много файлов за раз. По скорости это почти как xargs.
▪️ xargs - быстрее для больших списков. Пример:
xargs собирает много аргументов и запускает команду одним вызовом. Можно ограничить размер батча:
⚠️ Главная проблема xargs. Файлы с пробелами ломают команду:
Поэтому правильный вариант:
Пара:
делает обработку 100% безопасной.
BashTex📱 #bash #utils
Когда нужно выполнить команду для большого количества файлов, чаще всего используют два подхода:
find ... -exec или find ... | xargs. Они решают одну задачу, но ведут себя по-разному.
find /var/log -type f -name "*.log" -mtime +7 -exec rm {} \;
{} - подставляет найденный файл.\; - завершает команду.Плюсы: безопасно работает с пробелами, не ломается на спецсимволах и не требует пайпа
Но есть нюанс: команда запускается для каждого файла.
find /var/log -type f -name "*.log" -exec rm {} +
Теперь rm получит много файлов за раз. По скорости это почти как xargs.
find /var/log -type f -name "*.log" | xargs rm
xargs собирает много аргументов и запускает команду одним вызовом. Можно ограничить размер батча:
find . -name "*.tmp" | xargs -n 10 rm
file one.txt
file two.txt
Поэтому правильный вариант:
find . -type f -print0 | xargs -0 rm
Пара:
-print0
xargs -0
делает обработку 100% безопасной.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
tee + process substitution: один поток и несколько получателей
Иногда нужно одновременно: увидеть вывод команды в терминале, записать его в файл и передать на обработку другой программе Если делать это по очереди - потеряется поток данных. Здесь помогает связка tee + process substitution.
▪️ Что делает tee. tee дублирует поток:
вывод остается в терминале и одновременно пишется в
▪️ Несколько получателей. tee может писать сразу в несколько файлов:
Но иногда нужно не просто файл, а другую команду.
▪️ Process substitution. Bash позволяет подставить вывод команды как файл:
Это называется process substitution.
▪️ Комбинируем
Одна копия идет в терминал, а другая в grep. Если найден ERROR, запись попадет в errors.log.
▪️ Более реальный пример. Допустим, идет сбор логов:
Теперь: полный поток остается в терминале, ошибки автоматически сохраняются
▪️ Можно делать несколько обработчиков
Один поток и сразу несколько фильтров.
BashTex📱 #bash #utils
Иногда нужно одновременно: увидеть вывод команды в терминале, записать его в файл и передать на обработку другой программе Если делать это по очереди - потеряется поток данных. Здесь помогает связка tee + process substitution.
command | tee file.log
вывод остается в терминале и одновременно пишется в
file.log
command | tee out1.log out2.log
Но иногда нужно не просто файл, а другую команду.
>(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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11
Работа с сигналами: SIGTERM, SIGINT, SIGHUP
Любой процесс в linux можно остановить сигналом. Если скрипт их не обрабатывает - он просто умирает, иногда оставляя: временные файлы, lock-файлы или незавершённые операции
▪️ Основные сигналы
SIGINT - (2) -
Остановка пользователем
SIGTERM (15) - вежливое завершение -
Дает процессу шанс корректно завершиться.
SIGHUP (1) - перечитай конфиг
часто используется для reload
▪️ Обработка сигналов через trap
Теперь скрипт не просто падает, а выполняет cleanup.
▪️ Пример cleanup
▪️ Полный пример
Теперь:
скрипт не оставляет мусор
Не все сигналы можно перехватить. Нельзя поймать: SIGKILL (9)
Если прилетит
BashTex📱 #scripts #utils
Любой процесс в linux можно остановить сигналом. Если скрипт их не обрабатывает - он просто умирает, иногда оставляя: временные файлы, lock-файлы или незавершённые операции
SIGINT - (2) -
Ctrl+CОстановка пользователем
SIGTERM (15) - вежливое завершение -
systemctl stop / killДает процессу шанс корректно завершиться.
SIGHUP (1) - перечитай конфиг
часто используется для reload
trap 'echo "Получен SIGINT"; cleanup; exit 1' INT
trap 'echo "Получен SIGTERM"; cleanup; exit 0' TERM
Теперь скрипт не просто падает, а выполняет 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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Проверка времени отклика сервисов
Когда сервис работает, но пользователи жалуются на медлительность, нужно мерить не аптайм, а отклик. Это легко сделать обычным curl.
▪️ Самый простой замер
Показывает общее время выполнения запроса и быстро понять, тормозит или нет.
▪️ Точнее: только сетевое время
Полезные метрики:
Пример:
▪️ Проверка нескольких сервисов
▪️ Таймаут обязателен
Без таймаута любой мониторинг бесполезен.
BashTex📱 #bash #utils
Когда сервис работает, но пользователи жалуются на медлительность, нужно мерить не аптайм, а отклик. Это легко сделать обычным curl.
time curl -s https://bashtex.com > /dev/null
Показывает общее время выполнения запроса и быстро понять, тормозит или нет.
curl -s -o /dev/null -w "time_total: %{time_total}\n" https://bashtex.com
Полезные метрики:
time_namelookuptime_connecttime_starttransfertime_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
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
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1
tee + process substitution: один поток и несколько получателей
Иногда нужно одновременно: увидеть вывод команды в терминале, записать его в файл и передать на обработку другой программе Если делать это по очереди - потеряется поток данных. Здесь помогает связка tee + process substitution.
▪️ Что делает tee. tee дублирует поток:
command | tee file.log
вывод остается в терминале и одновременно пишется в
▪️ Несколько получателей. tee может писать сразу в несколько файлов:
command | tee out1.log out2.log
Но иногда нужно не просто файл, а другую команду.
▪️ Process substitution. Bash позволяет подставить вывод команды как файл:
>(command)
Это называется process substitution.
▪️ Комбинируем
command | tee >(grep ERROR > errors.log)
Одна копия идет в терминал, а другая в 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
Иногда нужно одновременно: увидеть вывод команды в терминале, записать его в файл и передать на обработку другой программе Если делать это по очереди - потеряется поток данных. Здесь помогает связка tee + process substitution.
command | tee file.log
вывод остается в терминале и одновременно пишется в
file.logcommand | tee out1.log out2.log
Но иногда нужно не просто файл, а другую команду.
>(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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍1