Автоматическая очистка старых бэкапов по количеству копий
▪️ Исходные условия
Все бэкапы лежат в одном каталоге;
Имена содержат дату или время (важно для сортировки);
Нужно оставить, например, 7 последних копий.
🛠 Простой, но надежный скрипт
▪️ Полезные улучшения
Проверка без удаления:
Фильтрация только нужных бэкапов:
Логирование:
BashTex📱 #bash #utils
Все бэкапы лежат в одном каталоге;
Имена содержат дату или время (важно для сортировки);
Нужно оставить, например, 7 последних копий.
#!/bin/bash
BACKUP_DIR="/backups"
KEEP=7
cd "$BACKUP_DIR" || exit 1
ls -1t | tail -n +$((KEEP + 1)) | while read -r old_backup; do
echo "Удаляю старый бэкап: $old_backup"
rm -rf -- "$old_backup"
done
ls -1t- сортирует файлы по времени изменения (новые сверху)tail -n +$((KEEP + 1))- выбирает всё после N первыхrm -rf --- безопасно удаляет, даже если имя начинается с -
Проверка без удаления:
ls -1t | tail -n +$((KEEP + 1))
Фильтрация только нужных бэкапов:
ls -1t backup-* | tail -n +$((KEEP + 1))
Логирование:
rm -rf -- "$old_backup" >> /var/log/backup-cleanup.log 2>&1
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Проверка доступности DNS и fallback на другой сервер
Когда DNS внезапно падает, проблемы выглядят как сбой сети или сервиса. Чтобы не гадать, можно сделать простой механизм: проверяем DNS и если не отвечает, то временно переключаемся на резервный сервер.
🛠 Базовый скрипт
▪️ Автовосстановление (по cron)
⚠️ Обратить внимание
В системах с systemd-resolved или NetworkManager resolv.conf может перезаписываться;
Для серверов лучше использовать resolvectl или override конфигурации;
Скрипт требует root.
BashTex📱 #bash
Когда DNS внезапно падает, проблемы выглядят как сбой сети или сервиса. Чтобы не гадать, можно сделать простой механизм: проверяем DNS и если не отвечает, то временно переключаемся на резервный сервер.
#!/bin/bash
TEST_DOMAIN="google.com"
PRIMARY_DNS="8.8.8.8"
FALLBACK_DNS="1.1.1.1"
RESOLV="/etc/resolv.conf"
BACKUP="/tmp/resolv.conf.bak"
if dig +time=2 +tries=1 "$TEST_DOMAIN" @"$PRIMARY_DNS" > /dev/null; then
echo "DNS доступен"
exit 0
fi
echo "DNS недоступен, переключаемся на fallback"
cp "$RESOLV" "$BACKUP"
cat > "$RESOLV" <<EOF
nameserver $FALLBACK_DNS
EOF
dig - быстрая проверка реального DNS-запроса
+time и +tries - не зависаем надолго
resolv.conf сохраняется перед изменением
if dig "$TEST_DOMAIN" @"$PRIMARY_DNS" > /dev/null && [ -f "$BACKUP" ]; then
mv "$BACKUP" "$RESOLV"
fi
В системах с systemd-resolved или NetworkManager resolv.conf может перезаписываться;
Для серверов лучше использовать resolvectl или override конфигурации;
Скрипт требует root.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Проверка существования команды и версии утилиты
Скрипты часто падают не из-за логики, а из-за отсутствующей команды или неподходящей версии утилиты. Хорошая практика для часто переезжающих скриптов - проверять наличие команды до выполнения основной логики и иметь fallback.
▪️ Базовая проверка: есть ли команда
быстрее и безопаснее
корректно работает с alias и builtins;
не пишет лишнего в stdout.
▪️ Проверка с fallback
Один интерфейс - разные реализации.
▪️ Проверка версии утилиты
▪️ Универсальная функция
Использование:
BashTex📱 #bash #utils
Скрипты часто падают не из-за логики, а из-за отсутствующей команды или неподходящей версии утилиты. Хорошая практика для часто переезжающих скриптов - проверять наличие команды до выполнения основной логики и иметь fallback.
if ! command -v curl >/dev/null 2>&1; then
echo "curl не найден"
exit 1
fi
command -v в данном случае:быстрее и безопаснее
which;корректно работает с alias и builtins;
не пишет лишнего в stdout.
if command -v curl >/dev/null; then
DL="curl -fsSL"
elif command -v wget >/dev/null; then
DL="wget -qO-"
else
echo "Нет curl или wget"
exit 1
fi
$DL https://bashtex.com
Один интерфейс - разные реализации.
REQ="7.60"
CUR=$(curl -V | awk '{print $2}')
if [ "$(printf '%s\n' "$REQ" "$CUR" | sort -V | head -n1)" != "$REQ" ]; then
echo "curl слишком старый: $CUR"
exit 1
fi
sort -V корректно сравнивает версии (7.9 < 7.10).
require_cmd() {
command -v "$1" >/dev/null || {
echo "Требуется команда: $1"
exit 1
}
}
Использование:
require_cmd awk
require_cmd tar
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Поиск файлов, измененных за последние 24 часа
Простая задача, которая регулярно спасает время: быстро найти, что именно менялось на системе за сутки - конфиги, логи, скрипты, данные.
▪️ Базовый вариант
▪️ Только конфиги или нужные расширения
Удобно после апдейтов или ручных правок.
▪️ С деталями (размер, дата, путь)
Или аккуратнее через stat:
▪️ Исключаем лишнее
Актуально для системного аудита.
▪️ За последние N часов (точнее суток)
BashTex📱 #bash #utils
Простая задача, которая регулярно спасает время: быстро найти, что именно менялось на системе за сутки - конфиги, логи, скрипты, данные.
find /path -type f -mtime -1
-mtime -1 - файлы, измененные менее суток назад. Работает по времени изменения содержимого (mtime)find /etc -type f -mtime -1 \( -name "*.conf" -o -name "*.cfg" \)
Удобно после апдейтов или ручных правок.
find /var/log -type f -mtime -1 -exec ls -lh {} +
Или аккуратнее через stat:
find . -type f -mtime -1 -exec stat --format '%y %s %n' {} +
find / -type f -mtime -1 \
! -path "/proc/*" \
! -path "/sys/*" \
! -path "/dev/*"
Актуально для системного аудита.
find /home -type f -mmin -1440
-mmin работает с минутамиBashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8🗿3👨💻2
Работа с датами и временем
Дата и время в bash нужны постоянно: бэкапы, логи, ротация, отчеты, cron и т.д. Хорошая новость -
▪️ Форматированный вывод даты:
▪️ Типовые форматы:
▪️ Вчера / завтра
С форматированием:
▪️ Смещение на N дней
Пример для бэкапов:
▪️ Часы, минуты, секунды
Комбинирование:
▪️ Начало и конец дня
Вчерашний день целиком:
▪️ Unix timestamp в человекочитаемо
Обратно:
▪️ Имена файлов и каталогов
▪️ Проверка возраста файлов (совместно с date)
BashTex📱 #bash #utils
Дата и время в bash нужны постоянно: бэкапы, логи, ротация, отчеты, cron и т.д. Хорошая новость -
date умеет почти все, если знать приемы.
date +"%Y-%m-%d %H:%M:%S"
%Y - год%m - месяц%d - день%H:%M:%S - время%s - Unix timestamp
now=$(date +"%F_%H-%M-%S")
date -d "yesterday"
date -d "tomorrow"
С форматированием:
date -d "yesterday" +"%Y-%m-%d"
date -d "+3 days"
date -d "-7 days"
Пример для бэкапов:
backup_date=$(date -d "+1 day" +"%F")
date -d "+2 hours"
date -d "-15 minutes"
date -d "+30 seconds"
Комбинирование:
date -d "+1 day +2 hours"
date -d "today 00:00"
date -d "today 23:59:59"
Вчерашний день целиком:
date -d "yesterday 00:00"
date -d "yesterday 23:59:59"
date -d @1700000000
Обратно:
date +%s
logfile="app_$(date +%F).log"
mkdir "backup_$(date +%Y%m%d)"
file_ts=$(stat -c %Y file.txt)
now_ts=$(date +%s)
(( now_ts - file_ts > 86400 )) && echo "Файл старше суток"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Безопасная работа с rm
▪️ Простой способ - ls
Если вывод выглядит корректно только потом:
▪️ Проверка через echo. Отлично работает со сложными шаблонами:
Пока есть echo - ничего не удалится.
▪️ Проверка через find
Проверили список -> заменили
▪️ Подтверждение перед удалением. Встроенный интерактивный режим
▪️ Свой безопасный wrapper
Использование:
▪️ Проверка на пустые переменные (обязательно!)
Опасно:
Безопасно:
BashTex📱 #bash #utils
rm - одна из самых опасных команд в linux ввиду отсутствия корзины. Ошибся путем, переменной или шаблоном и данные ушли навсегда. Но есть простые приемы, которые делают работу с удалением безопасной.
ls -ld /path/to/delete/*
Если вывод выглядит корректно только потом:
rm -rf /path/to/delete/*
echo rm -rf /data/tmp/*
Пока есть echo - ничего не удалится.
find /logs -type f -mtime +7 -print
Проверили список -> заменили
-print на -delete:
find /logs -type f -mtime +7 -delete
rm -ri /important/data
-i - спрашивает подтверждение-r - рекурсивно
safe_rm() {
echo "Будут удалены:"
ls -ld "$@"
read -p "Продолжить? [y/N] " ans
[[ "$ans" == "y" ]] && rm -rf "$@"
}
Использование:
safe_rm /path/to/delete
Опасно:
rm -rf "$DIR"
Безопасно:
[[ -n "$DIR" ]] && rm -rf "$DIR"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7
Чтение файлов построчно без потери спецсимволов
Чтение файла строка за строкой в bash кажется простым… пока не начинают теряться символы.
▪️ Классическая ошибка
Проблемы:
начальные/конечные пробелы обрезаются
строки с
Для конфигов, путей и логов это критично.
▪️ Правильный способ
Это канонический вариант чтения строк.
▪️ Что здесь происходит
отключает разделение по пробелам и табам;
сохраняет все пробелы в начале и конце строки.
запрещает интерпретацию
строка читается как есть.
▪️ Пример проблемы
Файл:
Без -r:
С IFS= read -r:
▪️ Чтение с обработкой строк
▪️ Альтернатива: mapfile
Но есть один минус -
BashTex📱 #bash #utils
Чтение файла строка за строкой в bash кажется простым… пока не начинают теряться символы.
while read line; do
echo "$line"
done < file.txt
Проблемы:
\ - пропадаетначальные/конечные пробелы обрезаются
строки с
\n, \t, \\ читаются некорректноДля конфигов, путей и логов это критично.
while IFS= read -r line; do
echo "$line"
done < file.txt
Это канонический вариант чтения строк.
IFS=отключает разделение по пробелам и табам;
сохраняет все пробелы в начале и конце строки.
read -rзапрещает интерпретацию
\ как escape;строка читается как есть.
Файл:
path=C:\Program Files\App\
Без -r:
path=C:Program FilesApp
С IFS= read -r:
path=C:\Program Files\App\
while IFS= read -r line; do
[[ "$line" =~ ^#|^$ ]] && continue
echo "Обработка: $line"
done < config.conf
mapfile -t lines < file.txt
Но есть один минус -
mapfile загружает весь файл в памятьBashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Поиск пользователей без пароля и с заблокированным shell
Со временем в системе накапливаются сервисные, забытые или некорректные аккаунты. Часть из них может быть: без пароля, с истекшим паролем
или с заблокированным shell. Быстрый аудит можно сделать обычным bash.
▪️ Пользователи без пароля. Пароль хранится в /
Если вывод не пустой - это повод проверить, зачем аккаунт существует.
▪️ Пользователи с заблокированным паролем
! или * в поле пароля значит, что вход запрещен
Обычно это нормально для сервисных аккаунтов.
▪️ Пользователи с отключенным shell
Типично для:
www-data
nginx
backup
Если обычный пользователь с таким shell - стоит проверить.
▪️ Проверка статуса пароля через chage
Полезно для поиска:
истекших паролей;
аккаунтов без политики смены.
▪️ Массово:
▪️ Быстрый отчет:
BashTex📱 #bash #utils
Со временем в системе накапливаются сервисные, забытые или некорректные аккаунты. Часть из них может быть: без пароля, с истекшим паролем
или с заблокированным shell. Быстрый аудит можно сделать обычным bash.
etc/shadow, но факт его отсутствия легко проверить:
sudo awk -F: '($2==""){print $1}' /etc/shadow
Если вывод не пустой - это повод проверить, зачем аккаунт существует.
sudo awk -F: '($2 ~ /^!|^\*/){print $1}' /etc/shadow
! или * в поле пароля значит, что вход запрещен
Обычно это нормально для сервисных аккаунтов.
awk -F: '($7 ~ /(nologin|false)$/){print $1, $7}' /etc/passwd
Типично для:
www-data
nginx
backup
Если обычный пользователь с таким shell - стоит проверить.
sudo chage -l username
Полезно для поиска:
истекших паролей;
аккаунтов без политики смены.
for u in $(cut -d: -f1 /etc/passwd); do
chage -l "$u" 2>/dev/null | grep -q "never" && echo "$u"
done
awk -F: '{print $1 ":" $7}' /etc/passwd
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9
Разница между "$@" и "$*", и почему это ломает скрипты
Оба варианта выглядят почти одинаково, но ведут себя принципиально по-разному, особенно если в аргументах есть пробелы.
Предположим, скрипт запущен так:
▪️ "$@" - правильный вариант
Вывод:
Каждый аргумент сохраняется как отдельная сущность.
Это то, чего вы ожидаете в 99% скриптов.
▪️ "$*" - частая ловушка
Вывод:
Все аргументы склеены в одну строку через IFS (по умолчанию пробел).
▪️ Почему это ломает скрипты
Передача аргументов дальше:
Обработка файлов:
копирование падает или ведет себя странно.
Работа с пробелами:
один аргумент = несколько файлов (по мнению bash).
BashTex📱 #bash #utils
Оба варианта выглядят почти одинаково, но ведут себя принципиально по-разному, особенно если в аргументах есть пробелы.
Предположим, скрипт запущен так:
./script.sh "file one.txt" "file two.txt"
for arg in "$@"; do
echo "[$arg]"
done
Вывод:
[file one.txt]
[file two.txt]
Каждый аргумент сохраняется как отдельная сущность.
Это то, чего вы ожидаете в 99% скриптов.
for arg in "$*"; do
echo "[$arg]"
done
Вывод:
[file one.txt file two.txt]
Все аргументы склеены в одну строку через IFS (по умолчанию пробел).
Передача аргументов дальше:
rm "$*"
rm получает один путь, которого не существует.Обработка файлов:
cp "$*" /backup
копирование падает или ведет себя странно.
Работа с пробелами:
один аргумент = несколько файлов (по мнению bash).
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Автоматический сбор логов одного сервиса в архив
Бывает такое, что нужно быстро собрать логи сервиса и отправить в тикет, например. Делать это вручную - долго и неудобно. Решается одним bash-скриптом.
▪️ Базовый вариант. Собираем логи systemd-сервиса и сразу архивируем:
Результат: один .tar.gz с логами сервиса за все время.
▪️ Ограничение по времени. Чаще нужны не все логи, а, например, последние сутки:
Можно и точнее:
▪️ Полезные флаги
Пример:
BashTex📱 #bash
Бывает такое, что нужно быстро собрать логи сервиса и отправить в тикет, например. Делать это вручную - долго и неудобно. Решается одним bash-скриптом.
SERVICE=nginx
OUT="/tmp/${SERVICE}-logs-$(date +%F_%H-%M).tar.gz"
journalctl -u "$SERVICE" --no-pager > /tmp/${SERVICE}.log
tar -czf "$OUT" -C /tmp "${SERVICE}.log"
rm /tmp/${SERVICE}.log
Результат: один .tar.gz с логами сервиса за все время.
journalctl -u nginx --since "24 hours ago" --no-pager > nginx.log
tar -czf nginx-logs.tar.gz nginx.log
Можно и точнее:
--since "2026-01-20 10:00" --until "2026-01-20 12:00"
-o short-iso - удобный формат времени-p err - только ошибки--boot - текущая загрузкаПример:
journalctl -u nginx -p err --since today -o short-iso
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Массовая проверка доступности серверов
▪️ Базовый пример. Есть файл со списком хостов:
Проверяем доступность всех сразу:
Все ping идут параллельно, вывод появляется почти мгновенно.
▪️ Ограничение параллелизма. Чтобы не зафлудить сеть:
▪️ Только упавшие хосты
Будет полезно тем, у кого нет мониторинга, но есть 2 и более сервера.
BashTex📱 #bash #utils
servers.txtПроверяем доступность всех сразу:
while read -r host; do
(
ping -c1 -W1 "$host" &>/dev/null \
&& echo "[OK] $host" \
|| echo "[FAIL] $host"
) &
done < servers.txt
wait
Все ping идут параллельно, вывод появляется почти мгновенно.
MAX=10
i=0
while read -r host; do
(
ping -c1 -W1 "$host" &>/dev/null \
&& echo "[OK] $host" \
|| echo "[FAIL] $host"
) &
((i++))
((i % MAX == 0)) && wait
done < servers.txt
wait
ping -c1 -W1 "$host" &>/dev/null || echo "$host DOWN"
Будет полезно тем, у кого нет мониторинга, но есть 2 и более сервера.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍3
Please open Telegram to view this post
VIEW IN TELEGRAM
😁12
Автоматическая ротация кастомных логов без logrotate
Не все логи живут в /var/log. Самописные сервисы часто пишут сюда:
Реализуем для них контролируемую ротацию на bash.
💚 Задача
архивировать логи старше N дней;
удалять архивы старше M дней;
не ломать активный файл;
не удалять то, что еще пишется.
1️⃣ Поиск логов старше N дней
⚠️
2️⃣ Архивирование с датой. Добавим gzip и текущую дату:
Здесь важно:
Никаких
3️⃣ Защита от удаления активного лога. Если сервис продолжает писать в файл, удалять его напрямую нельзя. Проверка через lsof:
Альтернатива: ротировать только логи, которые не менялись X часов:
4️⃣ Удаление старых архивов. Храним архивы 30 дней:
Лучше сначала проверить:
Только потом добавлять
5️⃣ Безопасный вариант с flock (чтобы не запустить дважды)
Теперь крон не создаст гонку.
▪️ Пример запуска через cron
BashTex📱 #bash #utils
Не все логи живут в /var/log. Самописные сервисы часто пишут сюда:
/opt/app/logs/
/srv/project/log/
/data/custom/*.log
Реализуем для них контролируемую ротацию на bash.
архивировать логи старше N дней;
удалять архивы старше M дней;
не ломать активный файл;
не удалять то, что еще пишется.
LOG_DIR="/opt/app/logs"
DAYS=7
find "$LOG_DIR" -type f -name "*.log" -mtime +$DAYS
-mtime +7 - старше 7 дней.mtime - это время последнего изменения.
ARCHIVE_DIR="/opt/app/archive"
mkdir -p "$ARCHIVE_DIR"
find "$LOG_DIR" -type f -name "*.log" -mtime +7 -print0 |
while IFS= read -r -d '' file; do
base=$(basename "$file")
gzip -c "$file" > "$ARCHIVE_DIR/${base}_$(date +%F).gz" && rm -f "$file"
done
Здесь важно:
-print0 + read -d '' - безопасно для пробеловgzip -c - сначала создаем архив&& rm - удаляем только если архив созданНикаких
rm до успешного gzip.
if lsof "$file" >/dev/null 2>&1; then
echo "Файл используется, пропускаем: $file"
continue
fi
Альтернатива: ротировать только логи, которые не менялись X часов:
-mmin +1440
find "$ARCHIVE_DIR" -type f -name "*.gz" -mtime +30 -delete
Лучше сначала проверить:
find "$ARCHIVE_DIR" -type f -mtime +30 -print
Только потом добавлять
-delete.
(
flock -n 200 || exit 1
# код ротации здесь
) 200>/var/lock/custom-log-rotate.lock
Теперь крон не создаст гонку.
0 3 * * * /usr/local/bin/custom_rotate.sh
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Проверка, какие команды доступны через sudo
Перед тем как что-то ломать или усиливать безопасность, полезно понять: что именно пользователь может запускать через sudo.
▪️ Базовая проверка
Показывает:
от какого пользователя можно выполнять команды
какие команды разрешены
есть ли NOPASSWD
Минус: в выводе много мусора.
▪️ Убираем лишнее. Только команды:
Или короче:
▪️ Быстро найти опасные права
Команды с NOPASSWD
Полный доступ (ALL)
Запуск shell’ов
▪️ Проверка другого пользователя (root)
BashTex📱 #bash
Перед тем как что-то ломать или усиливать безопасность, полезно понять: что именно пользователь может запускать через sudo.
sudo -l
Показывает:
от какого пользователя можно выполнять команды
какие команды разрешены
есть ли NOPASSWD
Минус: в выводе много мусора.
sudo -l | sed -n '/may run the following commands/,/^$/p'
Или короче:
sudo -l | grep -E '^\s*\('
Команды с NOPASSWD
sudo -l | grep NOPASSWD
Полный доступ (ALL)
sudo -l | grep '(ALL)'
Запуск shell’ов
sudo -l | grep -E 'bash|sh|zsh'
sudo -l -U username
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17
Ограничение времени выполнения команды
Иногда команда зависает навсегда: сетевой запрос, бэкап, скрипт.
▪️ Базовое использование
Если команда не завершилась за 5 секунд, то она будет остановлена.
Поддерживаемые единицы: 5s 2m 1h
▪️ В скриптах и cron. Пример с curl:
В cron это особенно важно т.к зависшая задача может копиться часами.
▪️ Проверка результата
Код 124 означает, что команда была прервана по таймауту.
▪️ Жесткое завершение
По умолчанию timeout шлёт SIGTERM.
Если процесс игнорирует его:
10s - мягкое завершение
+2s - принудительный SIGKILL
BashTex📱 #bash #utils
Иногда команда зависает навсегда: сетевой запрос, бэкап, скрипт.
timeout - это простой способ не дать ей убить автоматизацию.
timeout 5s command
Если команда не завершилась за 5 секунд, то она будет остановлена.
Поддерживаемые единицы: 5s 2m 1h
timeout 10s curl https://bashtex.com
В cron это особенно важно т.к зависшая задача может копиться часами.
timeout 5s long_task
case $? in
0) echo "OK" ;;
124) echo "Timeout" ;;
*) echo "Ошибка" ;;
esac
Код 124 означает, что команда была прервана по таймауту.
По умолчанию timeout шлёт SIGTERM.
Если процесс игнорирует его:
timeout -k 2s 10s command
10s - мягкое завершение
+2s - принудительный SIGKILL
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Проверка: существует ли файл, каталог или ссылка
В bash не нужно городить ls | grep. Для проверок есть встроенные тесты, более быстрые и надежные.
▪️ Обычный файл -
Истина, если: файл есть и это не каталог
▪️ Каталог -
Полезно перед: копированием, cd или очисткой директорий
▪️ Символическая ссылка -
Работает даже если ссылка битая.
▪️ Просто что-то существует -
Файл, каталог, ссылка - все подряд.
▪️ Шпаргалка
BashTex📱 #bash #utils
В bash не нужно городить ls | grep. Для проверок есть встроенные тесты, более быстрые и надежные.
-f
[ -f file.txt ] && echo "Файл существует"
Истина, если: файл есть и это не каталог
-d
[ -d /etc/nginx ] && echo "Каталог существует"
Полезно перед: копированием, cd или очисткой директорий
-L
[ -L /usr/bin/python ] && echo "Это symlink"
Работает даже если ссылка битая.
-e
[ -e path ] || echo "Ничего нет"
Файл, каталог, ссылка - все подряд.
-fобычный файл-dкаталог-Lsymlink-eсуществует
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Захват вывода команды в переменную
Есть два способа сохранить вывод команды в переменную. Формально оба работают, но один из них устарел.
▪️ Правильный способ
Плюсы:
легко читать
можно вкладывать команды
меньше сюрпризов с экранированием
▪️ Устаревший способ
Минусы:
плохо читается
сложно экранировать
вложенность превращается в ад
▪️ Почему backticks ломают скрипты
`
ошибки трудно отлаживать
в больших скриптах быстро становится нечитаемо
▪️ Общая ловушка: переносы строк. Оба способа схлопывают переводы строк в пробелы:
Если важны строки:
BashTex📱 #bash #utils
Есть два способа сохранить вывод команды в переменную. Формально оба работают, но один из них устарел.
files=$(ls /etc)
Плюсы:
легко читать
можно вкладывать команды
меньше сюрпризов с экранированием
count=$(wc -l < file.txt)
files=`ls /etc
Минусы:
плохо читается
сложно экранировать
вложенность превращается в ад
# выглядит ужасно и ломается
result=`echo \`date\``
`
конфликтует с кавычкамиошибки трудно отлаживать
в больших скриптах быстро становится нечитаемо
list=$(cat file)
Если важны строки:
mapfile -t list < file
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7