

- Главная
- Каталог
- Интернет технологии
- BashTex | Linux
BashTex | Linux
Авторский канал про мир Linux и Bash. Основная аудитория: системные администраторы, DevOps, Python-разработчики и другие.
Статистика канала
Полная статистикаchevron_right
TMPDIR="/tmp/myscript"
mkdir -p "$TMPDIR"
# ...
rm -rf "$TMPDIR"{}
Это рискованно, потому что:
- Возможна гонка при mkdir в /tmp
- Если скрипт завершится с ошибкой - rm -rf не выполнится
- Несколько процессов перетрут файлы друг друга
TMPDIR=$(mktemp -d -t myscript.XXXXXX)
trap 'rm -rf "$TMPDIR"' EXIT{}
mktemp -d- создает уникальную директориюtrap ... EXIT- гарантирует удаление даже при ошибках Безопасно, изолированно и без коллизий
#!/usr/bin/env bash
set -euo pipefail
TMPDIR=$(mktemp -d -t build.XXXXXX)
trap 'echo "Cleaning $TMPDIR"; rm -rf "$TMPDIR"' EXIT
echo "Workdir: $TMPDIR"
cp -r src/* "$TMPDIR/"
pushd "$TMPDIR" >/dev/null
make all
popd >/dev/null{}
При любом исходе (Ctrl+C, ошибка, SIGTERM) директория будет удалена автоматически.
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
LOG="$TMPDIR/run.log"
OUT="$TMPDIR/result.txt"
echo "Starting..." > "$LOG"
echo "42" > "$OUT"{}
Все временные артефакты изолированы в одной папке. После завершения скрипта следов нет.
mktemp создает директорию с правами 700.
Можно задать вручную:
TMPDIR=$(mktemp -d -p /var/tmp myscript.XXXXXX)
chmod 700 "$TMPDIR"{}
Полезно, если скрипт работает под рутом и обрабатывает конфиденциальные данные.
BashTex
for f in *.log; do
gzip "$f" &
done
wait{}
Все файлы сжимаются одновременно - но это нагружает CPU. Хотелось бы ограничить количество потоков, для этого добавим контроль.
MAXJOBS=4
for f in *.log; do
gzip "$f" &
(( $(jobs -r | wc -l) >= MAXJOBS )) && wait -n
done
wait{}
jobs -r- считает активные фоновые процессыwait -n- дожидается завершения одного из них В итоге максимум 4 задачи одновременно
ls *.log | xargs -n1 -P4 bash -c 'gzip "$0"' {}
-n1 - по одному аргументу на процесс -P4 - максимум 4 параллельных процесса bash -c 'gzip "$0"' - шаблон выполнения
process_file() {
local f="$1"
echo "[START] $f"
sleep $((RANDOM % 5)) # эмуляция нагрузки
echo "[DONE] $f"
}
export -f process_file
ls *.log | xargs -n1 -P3 bash -c 'process_file "$0"' {}
Вывод:
[START] file1.log
[START] file2.log
[START] file3.log
[DONE] file2.log
[DONE] file1.log
[START] file4.log
[DONE] file3.log
[DONE] file4.log{}
Все просто, читаемо и работает без внешних зависимостей.
BashTex /proc, без доступа к shell-сессии.
/proc/<PID>/environ{}
Это бинарный файл, где переменные разделены нулевыми байтами (\0).
PID=1234
tr '\0' '\n' < /proc/$PID/environ{}
Выведет все окружение процесса:
USER=www-data
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
PWD=/var/www
HOME=/var/www
LANG=en_US.UTF-8{}
PID=1234
eval "$(tr '\0' '\n' < /proc/$PID/environ | sed 's/^/export /')"{}
Теперь ты в том же окружении, что и процесс $PID.
Будет полезно, если: хочешь повторить окружение демона (nginx, systemd, custom app); нужно пересоздать контекст для отладки; запускаешь скрипт от того же пользователя, что и процесс.
grep -z '^PATH=' /proc/$PID/environ | tr -d '\0' | cut -d= -f2-{}
А если нужно универсальнее, то функция:
get_env_var() {
local pid=$1 var=$2
grep -z "^${var}=" /proc/$pid/environ | tr -d '\0' | cut -d= -f2-
}
get_env_var 1234 PATH{}
PID=$(systemctl show -p MainPID myservice | cut -d= -f2)
tr '\0' '\n' < /proc/$PID/environ{}
Пример: повторить сессию nginx worker’а
PID=$(pgrep -n nginx)
eval "$(tr '\0' '\n' < /proc/$PID/environ | sed 's/^/export /')"
env | grep -E 'PATH|LANG|PWD'{}
Теперь любая команда (например, curl, python, php) будет запускаться с теми же переменными, что и процесс веб-сервера.
alias # все алиасы
declare -f # все функции
declare -p # все переменные (включая окружение){}
Можно собрать это в файл:
{
echo "# Snapshot from $(date)"
echo "# Aliases"
alias
echo
echo "# Functions"
declare -f
echo
echo "# Variables"
declare -p
} > ~/.bash_snapshot{}
Теперь у вас дамп окружения. Содержит все, что вы настроили вручную или подгрузили через .bashrc, .bash_aliases, и т.д.
source ~/.bash_snapshot{}
Все ваши функции, алиасы и переменные возвращаются как были.
snapshot() {
local file="${1:-~/.bash_snapshot_$(date +%F_%H-%M-%S)}"
{
alias
declare -f
declare -p | grep -v '^declare -[a-z]* BASH'
} > "$file"
echo "Saved snapshot to $file"
}
restore() {
local file="${1:-~/.bash_snapshot_latest}"
[[ -f $file ]] && source "$file" && echo "Restored from $file"
}{}
Использование:
snapshot ~/envs/dev.env
restore ~/envs/dev.env{}
diff <(grep -v '^#' dev.env) <(grep -v '^#' prod.env){}
покажет, что отличается между dev и prod.
BashTex
cp file.txt /tmp/somedir/{}
а потом через секунду нужно:
cd /tmp/somedir/{}
и снова набираете руками путь или выделяете путь?
Есть способ не повторять последнее слово - bash это помнит.
⠀
Alt + . - и bash подставит последний аргумент предыдущей команды.
cp file.txt /tmp/somedir/
cd <Alt+.>{}
превратится в
cd /tmp/somedir/{}
Нажимайте Alt + . несколько раз, чтобы пройтись по аргументам из истории (Bash перебирает их назад).
cd !${}
или
cd !.{}
!$ - последний аргумент предыдущей команды.
!. - то же самое, но безопаснее (некоторые шеллы по-разному интерпретируют $).
mkdir new_dir
rm -r !${}
Скопировали и сразу зашли:
cp -r project /opt/
cd !${}
Переместили файл и открыли его в редакторе:
mv data.log /var/log/archive/
nano !${}
Копируете в несколько мест подряд:
cp backup.tar.gz /mnt/usb/
cp !$ /srv/backups/{}
BashTex
notify-send "Бэкап завершен" "Все файлы успешно сохранены" --icon=dialog-information{}
Работает через D-Bus (org.freedesktop.Notifications). Можно добавить приоритет, срок жизни, категории:
notify-send \
--urgency=critical \
--expire-time=10000 \
--app-name="BackupScript" \
"Ошибка резервного копирования" \
"Недостаточно места на диске!"{}
dbus-send --session --type=method_call \
--dest=org.freedesktop.Notifications \
/org/freedesktop/Notifications \
org.freedesktop.Notifications.Notify \
string:"BashScript" \
uint32:0 \
string:"dialog-warning" \
string:"Системное уведомление" \
string:"Задача завершена с ошибками" \
array:string:"ОК" \
dict:string:string: \
int32:-1{}
Выглядит громоздко, но это чистый вызов через D-Bus, минуя внешние обертки. Можно внедрить в сценарии, где нужно абсолютное управление уведомлениями.
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
notify-send "Backup completed" "Проверено $(date)"{}
Это позволяет отправлять уведомления от root в сессию конкретного пользователя.
#!/usr/bin/env bash
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
TASK="Резервное копирование /home"
notify-send "Начато" "$TASK..."
if tar czf /backup/home_$(date +%F).tar.gz /home 2>/dev/null; then
notify-send "Успешно" "$TASK завершено"
else
notify-send "Ошибка" "$TASK не выполнено"
fi{}
Каждое выполнение скрипта будет сопровождаться визуальными уведомлениями в системе.
ID=$(notify-send "Выполняется резервное копирование..." --print-id)
sleep 5
notify-send "Завершено" "Файлы успешно сохранены" --replace-id="$ID"{}
BashTex Задача: Сравнить/etc/nginx/и/etc/systemd/между двумя серверами, чтобы увидеть, какие файлы изменены, добавлены или удалены.
#!/usr/bin/env bash
REMOTE="user@prod.example.com"
DIRS=("/etc/nginx" "/etc/systemd")
TMPDIR="/tmp/config-compare"
LOG="/tmp/config-diff.log"
mkdir -p "$TMPDIR"
> "$LOG"
for dir in "${DIRS[@]}"; do
echo "Checking $dir ..." | tee -a "$LOG"
rsync -avz --dry-run --delete "$REMOTE:$dir/" "$dir/" \
| grep -E '^deleting|^>f' \
| sed "s|^|$dir/ |" \
>> "$TMPDIR/rsync.diff"
done
if [[ -s "$TMPDIR/rsync.diff" ]]; then
echo -e "\nDifferences found:\n" | tee -a "$LOG"
cat "$TMPDIR/rsync.diff" | tee -a "$LOG"
else
echo "Configurations match across all directories." | tee -a "$LOG"
fi{}
rsync --dry-run --delete - имитирует синхронизацию, но ничего не меняет, выводит список различий между каталогами.
grep -E '^>f|^deleting' - фильтрует только изменения (новые или удалённые файлы).
ssh "$REMOTE" "cat /etc/nginx/nginx.conf" > /tmp/remote.conf
diff -u /etc/nginx/nginx.conf /tmp/remote.conf || echo "nginx.conf differs!"{}
echo -e "## Config diff report\n\`\`\`\n$(cat $TMPDIR/rsync.diff)\n\`\`\`" > /tmp/diff_report.md{}
[[ -s $TMPDIR/rsync.diff ]] && curl -s -F "text=$(cat $TMPDIR/rsync.diff)" \
"https://api.telegram.org/bot$TOKEN/sendMessage?chat_id=$CHAT_ID"{}
BashTex chroot и немного bash.
chroot - это механизм, который меняет корень файловой системы для процесса. Все, что он видит, находится внутри изолированного каталога, и даже rm -rf / не затронет настоящую систему (если, конечно, настроено правильно🤓 ).
#!/usr/bin/env bash
SANDBOX="/opt/sandbox"
DEBIAN_MIRROR="http://deb.debian.org/debian"
ARCH=$(dpkg --print-architecture)
# Проверка зависимостей
for cmd in debootstrap chroot mount umount; do
command -v $cmd >/dev/null || { echo "$cmd not found"; exit 1; }
done
# Создание окружения, если нет
if [[ ! -d "$SANDBOX" ]]; then
echo "Создаю минимальную систему Debian..."
sudo debootstrap --arch="$ARCH" stable "$SANDBOX" "$DEBIAN_MIRROR"
fi
# Монтируем системные точки
sudo mount -t proc /proc "$SANDBOX/proc"
sudo mount --rbind /sys "$SANDBOX/sys"
sudo mount --rbind /dev "$SANDBOX/dev"
# Добавим базовые бинари для экспериментов
sudo cp /bin/bash "$SANDBOX/bin/"
sudo cp /usr/bin/ls "$SANDBOX/usr/bin/"
echo "Входим в песочницу!"
sudo chroot "$SANDBOX" /bin/bash
# После выхода - очистка
echo "Отмонтирую ресурсы..."
sudo umount -l "$SANDBOX/proc" "$SANDBOX/sys" "$SANDBOX/dev"{}
Здесь:BashTexdebootstrapставит минимальный Debian прямо в каталог (/opt/sandbox)mountподключает системные псевдофайловые системы (/proc,/sys,/dev)chrootзапускает bash внутри нового корня После выхода - все отмонтируется, и можно просто удалить/opt/sandbox
Отзывы канала
всего 5 отзывов
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
BashTex | Linux — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 2.5K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 18.5, количество отзывов – 5, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 1258.74 ₽, а за 15 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий