Управление каталогами через стек путей
Все еще используешь cd туда-сюда, чтобы прыгать по директориям? Попробуй
🌟 Как это работает
▪️ Пример использования
Стек хранит историю твоих переходов, как назад в браузере.
▪️ dirs: просмотр пути
Это означает:
dirs +0 → текущий путь
dirs +1 → предыдущий
popd +1 → убрать второй элемент
❓ Где полезно:
⭐️ Совет: Добавить алиасы для удобства:
BashTex📱 #bash #utils
Все еще используешь cd туда-сюда, чтобы прыгать по директориям? Попробуй
pushd и popd - это как cd, но умнее: команды работают со стеком путей, а значит ты можешь легко возвращаться обратно.pushd /some/path- перейти в каталог и добавить его в стек.popd- вернуться назад по стеку и удалить текущий путь из него.dirs- показать текущий стек директорий.
pushd /etc/nginx
ls -l
pushd /var/log
tail -n 10 syslog
popd # Возврат в /etc/nginx
popd # Возврат туда, где были до первого pushd
Стек хранит историю твоих переходов, как назад в браузере.
dirs -v
# 0 ~/project/scripts
# 1 ~/project
# 2 ~
Это означает:
dirs +0 → текущий путь
dirs +1 → предыдущий
popd +1 → убрать второй элемент
1. В сложных скриптах, где ты переходишь между 3-4 директориями
2. При автоматизации сборки (build → temp → deploy → назад)
3. Когда нужно "вернуться" точно туда, откуда пришёл
alias bd='popd'
alias pd='pushd'
alias d='dirs -v'
pushd/popd - это просто удобная альтернатива cd с историей. Попробуй - и не можешь не возвращаться к cd ../../../..BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
Автоматическая генерация CHANGELOG из git log
Если ты оформляешь релизы или просто хочешь видеть историю изменений красиво, не нужно писать CHANGELOG.md вручную. Bash + git log = автоматическая генерация понятного и читаемого списка коммитов по тегу или дате.
🛠 Простой changelog между тегами
▪️ Пример вывода:
▪️ По дате: за последнюю неделю
▪️ Возможные расширения:
⭐️ Совет: Добавить в Makefile или
И у тебя всегда будет свежий, читаемый список изменений для клиентов или команды.
BashTex📱 #bash
Если ты оформляешь релизы или просто хочешь видеть историю изменений красиво, не нужно писать CHANGELOG.md вручную. Bash + git log = автоматическая генерация понятного и читаемого списка коммитов по тегу или дате.
#!/bin/bash
PREV_TAG=$(git describe --abbrev=0 --tags HEAD^)
CURRENT_TAG=$(git describe --tags)
echo "## Changelog: $PREV_TAG → $CURRENT_TAG" > CHANGELOG.md
git log "$PREV_TAG..$CURRENT_TAG" --pretty="* %s (%an)" >> CHANGELOG.md
## Changelog: v1.2.0 → v1.3.0
* Добавлен скрипт автообновления (admin)
* Фикс логирования ошибок в cron (dev)
* Обновлена документация (docs)
git log --since="7 days ago" --pretty="* %h %s (%an)" > changelog_this_week.md
📍 Группировка по типу коммита (feat, fix, chore)📍 Сортировка по автору или дате📍 Добавление ссылок на GitHub ([#123](https://github.com/...))📍 Генерация changelog на каждый git tag с сохранением в releases/
release.sh:
changelog:
bash scripts/gen_changelog.sh
И у тебя всегда будет свежий, читаемый список изменений для клиентов или команды.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Автоматическое обновление и перезапуск Docker-контейнеров при выходе новых образов
Если ты используешь докер и хочешь держать свои контейнеры в актуальном состоянии без ручного docker pull + restart - этот пост для тебя. С помощью bash можно отслеживать обновления образа и автоматически перезапускать контейнер, если он устарел.
🌟 Принцип:
🛠 Пример скрипта:
▪️ Для автоматизации: Добавь скрипт в cron или systemd-timer, например, каждые 6 часов:
⭐️ Советы:
BashTex📱 #bash
Если ты используешь докер и хочешь держать свои контейнеры в актуальном состоянии без ручного docker pull + restart - этот пост для тебя. С помощью bash можно отслеживать обновления образа и автоматически перезапускать контейнер, если он устарел.
📍 Проверяем хэш локального и удалённого образа📍 Если разные — обновляем образ📍 Перезапускаем контейнер с теми же параметрами📍 Логируем событие
#!/bin/bash
IMAGE="nginx:latest"
CONTAINER="my-nginx"
LOG="/var/log/docker_autoupdate.log"
echo "[$(date)] Проверка образа $IMAGE" >> "$LOG"
# Получаем текущий локальный digest
LOCAL_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE" 2>/dev/null || echo "none")
# Обновляем образ
docker pull "$IMAGE" > /dev/null 2>&1
# Получаем новый digest
NEW_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE" 2>/dev/null || echo "none")
# Сравниваем
if [[ "$LOCAL_DIGEST" != "$NEW_DIGEST" ]]; then
echo "[$(date)] Образ обновлён. Перезапуск контейнера $CONTAINER..." >> "$LOG"
docker stop "$CONTAINER"
docker rm "$CONTAINER"
# Запуск с нужными параметрами — укажи свои!
docker run -d --name "$CONTAINER" -p 80:80 "$IMAGE"
echo "[$(date)] Контейнер перезапущен с новым образом." >> "$LOG"
else
echo "[$(date)] Образ актуален. Перезапуск не требуется." >> "$LOG"
fi
0 */6 * * * /usr/local/bin/docker-auto-update.sh
📍 Используй docker inspect для восстановления аргументов запуска, если параметры сложные.📍 Для нескольких контейнеров используй массивы и цикл.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Bash и двоичные данные: читаем, конвертируем, анализируем
Bash - не только для текста. Иногда приходится парсить бинарные файлы, смотреть их содержимое, искать сигнатуры или работать с данными в base64. В арсенале есть несколько утилит:
▪️ xxd - человекочитаемый hex-дамп
Вывод:
Ты сразу видишь:
1. Смещение (слева)
2. HEX-представление
3. ASCII-декод справа (если есть)
Обратно в бинарник:
▪️ od - гибкий дампер
Это дает HEX-дамп без смещений, только байты. Удобно для парсинга в скриптах.
Читаем 2-байтные значения как целые числа.
▪️ base64 - кодирование/декодирование в текст. Когда бинарь нужно «перенести» в текст:
Обратно:
Будет полезно:
- для пересылки двоичных файлов через API
- вставки бинарных данных в JSON/YAML
- генерации payload'ов
▪️ Проверка сигнатур файлов
Для ELF-файлов ожидается:
Можно использовать для определения типа файла без file.
⭐️ Бонус: сравнение бинарников
Выводит байты, которые отличаются, с их смещением.
BashTex📱 #bash #utils
Bash - не только для текста. Иногда приходится парсить бинарные файлы, смотреть их содержимое, искать сигнатуры или работать с данными в base64. В арсенале есть несколько утилит:
xxd, od, base64 - и ты удивишься, сколько они могут.
xxd /bin/ls | head
Вывод:
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 3e00 0100 0000 b080 4000 0000 0000 ..>.......@.....
Ты сразу видишь:
1. Смещение (слева)
2. HEX-представление
3. ASCII-декод справа (если есть)
Обратно в бинарник:
xxd -r dump.hex > recovered.bin
od -An -t x1 -v myfile.bin
Это дает HEX-дамп без смещений, только байты. Удобно для парсинга в скриптах.
od -An -t d2 myfile.bin
Читаем 2-байтные значения как целые числа.
base64 /bin/bash > bash.b64
Обратно:
base64 -d bash.b64 > bash_restored
Будет полезно:
- для пересылки двоичных файлов через API
- вставки бинарных данных в JSON/YAML
- генерации payload'ов
head -c 4 somefile | xxd
Для ELF-файлов ожидается:
7f 45 4c 46 → .ELF
Можно использовать для определения типа файла без file.
cmp -l file1.bin file2.bin
Выводит байты, которые отличаются, с их смещением.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Локальное зеркало APT-репозитория с Bash и rsync
Обновление пакетов без внешнего интернета - это реально. Если ты обслуживаешь несколько серверов в ограниченной сети (или хочешь ускорить установку и обновление пакетов), стоит создать локальное зеркало APT-репозитория. Это особенно полезно для оффлайн-установок, CI/CD-сборок или ситуаций с нестабильным интернетом.
❓ Что нужно?
🛠 Пример скрипта:
Это минимальный зеркальный снимок. При необходимости можно расширить под debian-security, updates и другие релизы.
▪️ Настройка локального клиента. Чтобы использовать зеркало, на других серверах пропиши в
или через nginx:
▪️ Автоматизация. Добавь скрипт в cron или systemd-timer для ежедневной синхронизации:
Локальное зеркало экономит трафик, ускоряет установку и даёт контроль над пакетами в изолированных окружениях.
BashTex📱 #bash #utils
Обновление пакетов без внешнего интернета - это реально. Если ты обслуживаешь несколько серверов в ограниченной сети (или хочешь ускорить установку и обновление пакетов), стоит создать локальное зеркало APT-репозитория. Это особенно полезно для оффлайн-установок, CI/CD-сборок или ситуаций с нестабильным интернетом.
📍 Утилита rsync📍 Немного места на диске (от 50 ГБ и выше)📍 Простой скрипт для синхронизации
#!/bin/bash
# Базовые параметры
MIRROR="rsync://mirror.yandex.ru/ubuntu"
DEST="/srv/apt-mirror"
DIST="focal"
ARCH="amd64"
SECTIONS="main,restricted,universe,multiverse"
mkdir -p "$DEST"
rsync -av --delete \
--include "dists/" \
--include "dists/$DIST/" \
--include "dists/$DIST/*" \
--include "pool/" \
--include "pool/*" \
--exclude "*" \
"$MIRROR/" "$DEST"
Это минимальный зеркальный снимок. При необходимости можно расширить под debian-security, updates и другие релизы.
/etc/apt/sources.list:
deb [trusted=yes] file:///srv/apt-mirror focal main restricted universe multiverse
или через nginx:
deb https://mirror.local/ focal main restricted universe multiverse
0 4 * * * /usr/local/bin/apt-mirror-sync.sh
Локальное зеркало экономит трафик, ускоряет установку и даёт контроль над пакетами в изолированных окружениях.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20
Автоматизация создания пользователя в Linux
Каждый раз настраивать нового юзера вручную - скучно. Особенно если нужно: создать пользователя, выдать sudo, настроить SSH-доступ, прописать алиасы и окружение
🛠 Решается скриптом (create_user.sh):
▪️ Пример использования:
или
Скрипт подходит для CI/CD, dev-серверов, временных пользователей или быстрого поднятия окружения в cloud-инстансах.
BashTex📱 #bash
Каждый раз настраивать нового юзера вручную - скучно. Особенно если нужно: создать пользователя, выдать sudo, настроить SSH-доступ, прописать алиасы и окружение
#!/bin/bash
USERNAME="$1"
PUBKEY_URL="$2" # URL к публичному ключу или путь к файлу
if [[ -z "$USERNAME" || -z "$PUBKEY_URL" ]]; then
echo "Usage: $0 <username> <pubkey_url_or_file>"
exit 1
fi
# 1. Создание пользователя
useradd -m -s /bin/bash "$USERNAME"
# 2. Добавление в sudoers
usermod -aG sudo "$USERNAME"
# 3. Настройка SSH
HOME_DIR="/home/$USERNAME"
mkdir -p "$HOME_DIR/.ssh"
chmod 700 "$HOME_DIR/.ssh"
# Подгружаем ключ
if [[ "$PUBKEY_URL" =~ ^http ]]; then
curl -s "$PUBKEY_URL" -o "$HOME_DIR/.ssh/authorized_keys"
else
cp "$PUBKEY_URL" "$HOME_DIR/.ssh/authorized_keys"
fi
chmod 600 "$HOME_DIR/.ssh/authorized_keys"
chown -R "$USERNAME:$USERNAME" "$HOME_DIR/.ssh"
# 4. Aliases и welcome message
cat <<EOF >> "$HOME_DIR/.bashrc"
# --- Custom Setup ---
alias ll='ls -alF'
alias gs='git status'
echo "Добро пожаловать, $USERNAME!"
EOF
chown "$USERNAME:$USERNAME" "$HOME_DIR/.bashrc"
echo "[+] Пользователь $USERNAME создан и готов к работе!"
./create_user.sh dev1 https://example.com/dev1.pub
или
./create_user.sh admin1 ~/.ssh/id_rsa.pub
Скрипт подходит для CI/CD, dev-серверов, временных пользователей или быстрого поднятия окружения в cloud-инстансах.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1
Bash-функции с возможностью изменять аргументы
Когда ты передаешь переменные в функции - по умолчанию это копии, а не ссылки. Но с declare -n (aka nameref) можно менять переменные по ссылке, включая элементы массивов и даже динамические имена переменных.
❓ Что такое nameref?
▪️ Пример: модификация значения по ссылке
▪️ Пример: изменение массива внутри функции
Вывод:
▪️ Комбинирование с итерацией и позиционными аргументами
❗️ Когда использовать nameref?
BashTex📱 #bash #utils
Когда ты передаешь переменные в функции - по умолчанию это копии, а не ссылки. Но с declare -n (aka nameref) можно менять переменные по ссылке, включая элементы массивов и даже динамические имена переменных.
declare -n ref=имя - создает ссылку на переменную, позволяя функции менять её напрямую.
modify() {
declare -n ref=$1
ref="Изменено внутри функции"
}
value="Оригинал"
modify value
echo "$value" # Изменено внутри функции
update_array() {
declare -n arr=$1
arr+=("новый элемент")
}
my_array=("один" "два")
update_array my_array
printf "%s\n" "${my_array[@]}"
Вывод:
один
два
новый элемент
double_values() {
declare -n numbers=$1
for i in "${!numbers[@]}"; do
numbers[$i]=$((numbers[$i] * 2))
done
}
arr=(10 20 30)
double_values arr
echo "${arr[@]}" # 20 40 60
📍 Когда хочется возвращать несколько значений из функции📍 Когда работаешь с динамическими именами переменных📍 Когда пишешь библиотеки/модули на Bash
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Фоновая очередь с приоритетами
Когда ты запускаешь десятки фоновых задач - важно не просто кидать их в фон через &, а управлять их приоритетом, нагрузкой и порядком выполнения.
💎 Используем:
🛠 Пример: динамическая очередь с приоритетами
❓ Что это даёт?
▪️ Расширение: Добавь ограничение количества параллельных задач:
🔥 Такой подход позволяет:
BashTex📱 #bash
Когда ты запускаешь десятки фоновых задач - важно не просто кидать их в фон через &, а управлять их приоритетом, нагрузкой и порядком выполнения.
nice - задаем приоритет (-20 самый высокий, 19 - самый низкий)
wait - ждем завершения задач
& - фоновый запуск
массив - очередь
#!/bin/bash
declare -a QUEUE=(
"sleep 5" # низкий приоритет
"sleep 2" # высокий приоритет
"sleep 4"
)
declare -a PRIORITY=(
10 # nice +10 → ниже приоритет
-5 # nice -5 → выше приоритет
0
)
for i in "${!QUEUE[@]}"; do
echo "[*] Запуск: ${QUEUE[$i]} с приоритетом ${PRIORITY[$i]}"
nice -n "${PRIORITY[$i]}" bash -c "${QUEUE[$i]}" &
done
wait
echo "[+] Все задачи завершены"
📍 Задачи с низким приоритетом будут уступать CPU📍 Высокоприоритетные задачи получат преимущество при выполнении📍 wait гарантирует, что мы дождёмся всех процессов
MAX_PARALLEL=3
PIDS=()
for i in "${!QUEUE[@]}"; do
nice -n "${PRIORITY[$i]}" bash -c "${QUEUE[$i]}" &
PIDS+=($!)
if (( ${#PIDS[@]} >= MAX_PARALLEL )); then
wait -n # ждём завершения хотя бы одной задачи
# удалим завершившиеся из списка
for pid in "${PIDS[@]}"; do
if ! kill -0 "$pid" 2>/dev/null; then
PIDS=("${PIDS[@]/$pid}")
fi
done
fi
done
wait
📍 Делать умные очереди задач📍 Балансировать нагрузку📍 Экономить ресурсы📍 Контролировать порядок и параллелизм
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🗿1
Создаем интерактивность в терминале
Когда хочется добавить взаимодействие в скрипт, но без навороченного TUI, достаточно трех команд Bash:
▪️ read -s - скрытый ввод. Используется для ввода пароля:
-s - скрыть, -p - prompt, -e - enable readline, -n - количество символов
▪️ tput - контроль терминала
Примеры:
▪️ stty - контроль поведения терминала
Можно использовать и для отключения Ctrl+C, перехвата ввода, таймаутов:
▪️ Сценарий: простой ввод пароля с маской
BashTex📱 #bash #utils
Когда хочется добавить взаимодействие в скрипт, но без навороченного TUI, достаточно трех команд Bash:
read -s, tput, stty. С их помощью можно: скрыть ввод паролей, управлять курсором, отключать echo, обрабатывать клавиши "на лету".
read -sp "Введите пароль: " password
echo -e "\nПароль получен!"
-s - скрыть, -p - prompt, -e - enable readline, -n - количество символов
tput civis # скрыть курсор
tput cnorm # вернуть курсор
tput setaf 2; echo "Зелёный текст"; tput sgr0
Примеры:
setaf - цвет текста (0-7)setab - цвет фонаcup 5 10 - переместить курсор на строку 5, столбец 10clear - очистить экран
stty -echo # отключить вывод на экран
read username
stty echo # вернуть обратно
Можно использовать и для отключения Ctrl+C, перехвата ввода, таймаутов:
stty intr '' # временно отключить ^C
read_password() {
prompt="Введите пароль: "
password=""
while IFS= read -rsn1 char; do
[[ $char == $'\0' || $char == $'\n' ]] && break
password+="$char"
echo -n '*'
done
echo
}
read_password
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
Аудит sudo-доступа всех пользователей
🔎 Что делает скрипт:
📍 Сканирует всех пользователей с интерактивным shell;
📍 Выводит sudo -l для каждого;
📍 Ищет опасные команды с NOPASSWD, которые могут дать root-доступ.
▪️ Пример опасных конструкций в sudoers:
Такие команды позволяют поднять интерактивный shell от root без ввода пароля - критическая уязвимость, если не контролируется.
BashTex📱 #bash #security
#!/bin/bash
echo "[*] Проверка sudo-доступа всех пользователей..."
echo
# Получим список всех shell-пользователей
getent passwd | awk -F: '$7 ~ /bash|sh/ {print $1}' | while read user; do
echo "==> Пользователь: $user"
# Проверим, может ли пользователь использовать sudo
if sudo -lU "$user" &>/dev/null; then
sudo -lU "$user" 2>/dev/null
echo "[!] Потенциальные лазейки:"
sudo -lU "$user" 2>/dev/null | grep NOPASSWD | grep -Ei 'vim|less|more|nano|perl|python|bash|sh|man|awk|find|xargs|tar|scp|rsync|cp'
echo
else
echo "Нет доступа к sudo или пользователь не существует."
echo
fi
done
(user) NOPASSWD: /usr/bin/vim
(user) NOPASSWD: /usr/bin/find / -exec
(user) NOPASSWD: /usr/bin/python3
Такие команды позволяют поднять интерактивный shell от root без ввода пароля - критическая уязвимость, если не контролируется.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Перенос окружения на другой сервер с возможностью отката
Забудь про ручное копирование. Используй
▪️ Структура. Создадим папку
▪️ Синхронизация на другой сервер
На новом сервере:
▪️ Версионирование. Каждая копия создаётся с уникальным timestamp'ом, и ты всегда можешь:
📍 Вернуться к предыдущей версии;
📍 Отслеживать изменения в алиасах и bash-окружении;
📍 Проверять дифф между окружениями:
🌟 Рекомендация. Добавь в ~/.bashrc:
BashTex📱 #bash
Забудь про ручное копирование. Используй
rsync + версионирование, чтобы миграция алиасов, .bashrc, .config, env-переменных прошла чисто и прозрачно.~/env-backup/ со всеми элементами:
#!/bin/bash
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
BACKUP_DIR=~/env-backup/$TIMESTAMP
mkdir -p "$BACKUP_DIR"
# Экспорт переменных среды
export -p > "$BACKUP_DIR/env.sh"
# Сохраняем bash окружение
cp ~/.bashrc ~/.bash_aliases ~/.profile "$BACKUP_DIR" 2>/dev/null
# Копируем .config (если нужно)
rsync -a --exclude="*/Cache/" ~/.config "$BACKUP_DIR/config" 2>/dev/null
echo "Окружение сохранено в: $BACKUP_DIR"
rsync -avz ~/env-backup/ user@new-host:~/env-backup/
На новом сервере:
cd ~/env-backup/YYYYMMDD-HHMMSS/
cp .bashrc .bash_aliases .profile ~/
rsync -a config/ ~/.config/
# Подгружаем переменные среды
source env.sh
diff -u ~/env-backup/20240601-1000/.bashrc ~/env-backup/20240520-0900/.bashrc
[[ -f ~/.bash_aliases ]] && source ~/.bash_aliases
[[ -f ~/env-backup/env.sh ]] && source ~/env-backup/env.sh
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9
Профилирование скрипта: time, PS4, set -x - лог с таймингом каждой строки
🔎 Скрипт тормозит, но где? Чтобы найти бутылочное горлышко в скрипте, нужно понять, какая строка выполняется долго, а не просто смотреть на общее time.
✅ Решение: профилирование через связку:
time - сколько длился весь скрипт
set -x - трассировка всех команд
PS4 + date - лог с таймингом каждой строки
▪️ Пример: логирование с таймингом
▪️ Вывод лога trace.log:
Теперь видно, какая команда занимает больше всего времени. Не нужно гадать.
▪️ Добавим time: Если обернуть скрипт:
В конце получим:
🛠 Скрипт: поиск "медленных" команд в логе
▪️ Пример вывода:
Теперь ты в автомате видишь: какие строки тормозят, а не листаешь лог на глаз.
BashTex📱 #bash #utils
time - сколько длился весь скрипт
set -x - трассировка всех команд
PS4 + date - лог с таймингом каждой строки
#!/bin/bash
LOGFILE=trace.log
# Префикс трассировки: время и строка
export PS4='+ $(date "+%H:%M:%S.%3N") [${BASH_SOURCE##*/}:${LINENO}] '
# Включаем трассировку и направляем в лог
exec 3>&1 4>&2
exec > >(tee "$LOGFILE") 2>&1
set -x
# Тестовые команды
sleep 1
echo "Шаг 1"
sleep 2
echo "Шаг 2"
+ 12:34:56.001 [script.sh:12] sleep 1
+ 12:34:57.003 [script.sh:13] echo 'Шаг 1'
Шаг 1
+ 12:34:57.004 [script.sh:14] sleep 2
+ 12:34:59.006 [script.sh:15] echo 'Шаг 2'
Шаг 2
Теперь видно, какая команда занимает больше всего времени. Не нужно гадать.
time ./script.sh
В конце получим:
real 0m3.006s
user 0m0.002s
sys 0m0.004s
#!/bin/bash
LOG=trace.log
THRESHOLD=1.0 # секунды
awk '
/^\+ / {
ts=$2 # + 12:34:56.001
split(ts, a, ":")
split(a[3], b, ".")
sec = a[1]*3600 + a[2]*60 + b[1] + b[2]/1000
cmd = substr($0, index($0, $4))
if (last_sec > 0) {
delta = sec - last_sec
if (delta >= threshold) {
printf "%6.3fs | %s\n", delta, last_cmd
}
}
last_sec = sec
last_cmd = cmd
}
' threshold="$THRESHOLD" "$LOG"
1.002s | sleep 1
2.002s | sleep 2
Теперь ты в автомате видишь: какие строки тормозят, а не листаешь лог на глаз.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥4
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17🗿2
Очистка зависших SSH-сессий
Иногда пользователи (или вы сами) забывают выйти с сервера, и сессия остается в статусе idle или stuck, занимая ресурсы, блокируя терминалы и даже мешая обновлениям. Хорошая новость: Bash + w + ps + timeout помогут автоматически завершать такие сессии.
❓ Что считать зависшей сессией?
📍 Бездействие более 30 минут;
📍 Нет активных процессов;
📍 Неиспользуемый TTY;
🛠 Скрипт для автоудаления "спящих" SSH-сессий
🌟 Как это работает
❗️ Дополнительно:
📍 Добавь в исключения TTY root'а, CI/CD, сервисных пользователей;
📍 В проде лучше сначала логировать, потом - удалять;
BashTex📱 #bash
Иногда пользователи (или вы сами) забывают выйти с сервера, и сессия остается в статусе idle или stuck, занимая ресурсы, блокируя терминалы и даже мешая обновлениям. Хорошая новость: Bash + w + ps + timeout помогут автоматически завершать такие сессии.
#!/bin/bash
# Время бездействия в минутах
IDLE_LIMIT=30
echo "[*] Поиск SSH-сессий, бездействующих более $IDLE_LIMIT минут..."
w -h | awk -v limit="$IDLE_LIMIT" '
{
idle=$5
if (idle ~ /:/) {
split(idle, t, ":")
minutes = t[1]*60 + t[2]
} else if (idle ~ /old/) {
minutes = 999
} else {
minutes = idle + 0
}
if (minutes >= limit) {
print $2 # TTY
}
}
' | while read tty; do
echo "[!] Завершение процессов на $tty"
pkill -KILL -t "$tty"
done
w -h- список всех интерактивных сессийawkпарсит IDLE-времяpkill -tзавершает процессы, связанные с TTY
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17
Bash и математика
Это почти несовместимо, но стоит подключить утилиту
▪️ Пример: базовые вычисления
По умолчанию дробные числа - без знаков после запятой. Поэтому:
▪️ Переменные и выражения
Или сохранить результат:
Флаг -l включает математическую библиотеку с поддержкой sqrt(), s(), c(), l(), e() и т.д.
▪️ Условия и логика
▪️ Пример: вычисление средней загрузки из логов CPU
🌟 Когда использовать bc:
📍 скрипты мониторинга;
📍 фин. расчёты в bash;
📍 работа с датчиками (температура, напряжение);
📍 вычисление геометрических величин, преобразование координат
BashTex📱 #bash #utils
Это почти несовместимо, но стоит подключить утилиту
bc - и ты получаешь калькулятор в консоли, поддерживающий: дробные числа, логические выражения, условные операторы, возведение в степень и функции.
echo "3.14 * 2.5" | bc
# → 7.85
По умолчанию дробные числа - без знаков после запятой. Поэтому:
echo "scale=4; 10 / 3" | bc
# → 3.3333
a=5.7
b=3.2
echo "scale=2; $a + $b" | bc
# → 8.9
Или сохранить результат:
result=$(echo "scale=3; ($a^2 + $b^2)^0.5" | bc -l)
Флаг -l включает математическую библиотеку с поддержкой sqrt(), s(), c(), l(), e() и т.д.
x=2.5
y=4.1
if [[ $(echo "$x < $y" | bc) -eq 1 ]]; then
echo "$x меньше $y"
fi
total=0
count=0
for val in 1.2 0.8 2.5 1.9; do
total=$(echo "$total + $val" | bc)
count=$((count + 1))
done
avg=$(echo "scale=2; $total / $count" | bc)
echo "Средняя нагрузка: $avg"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18
Сканирование домашнего каталога на наличие SSH-ключей и приватных файлов
SSH-ключи и приватные файлы часто забывают почистить после миграций, тестов и копирований. Но забытый id_rsa в чужом $HOME - это потенциальная дыра в безопасности.
Сегодня про то, как быстро просканировать все домашние каталоги на сервере на наличие:
приватных ключей (id_rsa, *.pem, *.key)
конфигураций с доступами (.ssh/config, known_hosts)
подозрительных backup-файлов (*.bak, *.old, *~)
🛠 Скрипт: поиск чувствительных файлов
⭐️ Расширенная версия: с владельцем и правами
▪️ Это поможет заметить, если:
📍 приватный ключ лежит с правами 644 - плохо
📍 файл принадлежит не тому пользователю
📍 ключи забыли в общем ~/Downloads/ или ~/Desktop/
BashTex📱 #bash #security
SSH-ключи и приватные файлы часто забывают почистить после миграций, тестов и копирований. Но забытый id_rsa в чужом $HOME - это потенциальная дыра в безопасности.
Сегодня про то, как быстро просканировать все домашние каталоги на сервере на наличие:
приватных ключей (id_rsa, *.pem, *.key)
конфигураций с доступами (.ssh/config, known_hosts)
подозрительных backup-файлов (*.bak, *.old, *~)
#!/bin/bash
echo "[*] Поиск приватных SSH-ключей и чувствительных файлов в /home/*"
find /home /root \
-type f \
\( -name "id_rsa" -o -name "*.pem" -o -name "*.key" -o -name "*.bak" -o -name "*.old" -o -name "*~" \) \
-exec ls -lh {} \; 2>/dev/null
find /home /root \
-type f \
\( -name "id_rsa" -o -name "*.key" -o -name "*.pem" -o -name "*.gpg" \) \
-printf "%M %u %p\n" 2>/dev/null | sort
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👨💻2🔥1
Выявление SUID-бинарей и контроль их изменений
🌟 SUID-файлы в Linux - это потенциальная зона риска. Если злоумышленник сможет изменить или подменить такой бинарник, он может получить права root. Поэтому важно не только найти такие файлы, но и отслеживать их изменения.
SUID (Set User ID) - бит прав, при котором программа выполняется с правами владельца файла, а не вызывающего пользователя.
Типичный пример:
SUID-бит (s вместо x) на позиции владельца.
1️⃣ Поиск всех SUID-файлов в системе
Добавим форматированный вывод с размером и датой:
2️⃣ Контроль изменений через контрольные суммы. Создадим базовый снимок:
А теперь проверим изменения:
Все, что отличается от baseline, будет отображено.
▪️ Добавить cron-задачу:
И сам suid_check.sh:
BashTex📱 #bash #security
SUID (Set User ID) - бит прав, при котором программа выполняется с правами владельца файла, а не вызывающего пользователя.
Типичный пример:
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 54256 /usr/bin/passwd
SUID-бит (s вместо x) на позиции владельца.
find / -perm -4000 -type f 2>/dev/null
Добавим форматированный вывод с размером и датой:
find / -perm -4000 -type f -exec ls -lh {} \; 2>/dev/null
find / -perm -4000 -type f -exec sha256sum {} \; 2>/dev/null > /var/log/suid_baseline.sha
А теперь проверим изменения:
sha256sum -c /var/log/suid_baseline.sha 2>/dev/null | grep -v ': OK'
Все, что отличается от baseline, будет отображено.
@daily root /usr/local/bin/suid_check.sh >> /var/log/suid_monitor.log
И сам suid_check.sh:
#!/bin/bash
BASELINE="/var/log/suid_baseline.sha"
TMP="/tmp/suid_check.$$"
find / -perm -4000 -type f -exec sha256sum {} \; 2>/dev/null > "$TMP"
diff -u "$BASELINE" "$TMP" && cp "$TMP" "$BASELINE"
rm "$TMP"
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Запуск команд от имени другого пользователя через su/sudo без пароля
Иногда нужно запустить команду от другого пользователя - без постоянного ввода пароля. Например:
от имени сервисного пользователя без логина;
в скриптах автоматизации;
при делегировании задач.
Используем sudo с NOPASSWD и su с передачей команды.
1️⃣ Способ: sudo без пароля. Для этого отредактируем sudoers через:
Добавим строку:
Теперь можно запускать:
Или сразу выполнять произвольную команду:
2️⃣ Способ: su без пароля (через sudo-права). Если sudo уже доступен, можно делать:
Это полезно, если нужна изоляция окружения (su - сбрасывает переменные).
▪️ Пример в скрипте:
Обязательно ограничь sudo на конкретную команду в sudoers, чтобы избежать эскалации.
🌟 Безопасность:
📍 Не давай NOPASSWD на ALL!
📍 Всегда указывай полный путь к команде
📍 Используй visudo, чтобы не сломать конфигурацию
BashTex📱 #bash #utils
Иногда нужно запустить команду от другого пользователя - без постоянного ввода пароля. Например:
от имени сервисного пользователя без логина;
в скриптах автоматизации;
при делегировании задач.
Используем sudo с NOPASSWD и su с передачей команды.
sudo visudo
Добавим строку:
myuser ALL=(targetuser) NOPASSWD: /usr/bin/systemctl restart my-service
Теперь можно запускать:
sudo -u targetuser /usr/bin/systemctl restart my-service
Или сразу выполнять произвольную команду:
sudo -u deployuser /home/deployuser/scripts/deploy.sh
sudo su - otheruser -c 'echo $HOME'
Это полезно, если нужна изоляция окружения (su - сбрасывает переменные).
#!/bin/bash
USER=deploy
CMD="/opt/app/update.sh"
sudo -u "$USER" bash -c "$CMD"
Обязательно ограничь sudo на конкретную команду в sudoers, чтобы избежать эскалации.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Эмуляция очереди и стека в Bash: играем с массивами как в CS101
В bash можно не только писать условия и циклы, но и реализовать базовые структуры данных. Сегодня - очередь (FIFO) и стек (LIFO) - с помощью обычных массивов.
▪️ Стек (LIFO). Последним пришел - первым ушел.
После этого в стеке остается только "первый".
▪️ Очередь (FIFO). Первым пришел - первым ушел.
Мы просто “срезаем” массив начиная с элемента 1.
▪️ Пример: обработка задач в очереди
▪️ Условно реальный стек
С bash версии 4+ можно использовать [-1] для получения последнего элемента.
🌟 Минусы:
📍 Нет указателей, только пересоздание массива;
📍 Производительность не сравнима с языками типа Python, но работает.
BashTex📱 #bash #utils
В bash можно не только писать условия и циклы, но и реализовать базовые структуры данных. Сегодня - очередь (FIFO) и стек (LIFO) - с помощью обычных массивов.
stack=()
# push
stack+=("первый")
stack+=("второй")
# pop
last_index=$(( ${#stack[@]} - 1 ))
echo "POP: ${stack[$last_index]}"
unset 'stack[$last_index]'
После этого в стеке остается только "первый".
queue=()
# enqueue
queue+=("alpha")
queue+=("beta")
# dequeue
echo "DEQUEUE: ${queue[0]}"
queue=("${queue[@]:1}")
Мы просто “срезаем” массив начиная с элемента 1.
queue=("job1" "job2" "job3")
while [[ ${#queue[@]} -gt 0 ]]; do
task="${queue[0]}"
echo "Processing $task"
queue=("${queue[@]:1}")
done
push() { stack+=("$1"); }
pop() { echo "${stack[-1]}"; unset 'stack[-1]'; }
peek() { echo "${stack[-1]}"; }
С bash версии 4+ можно использовать [-1] для получения последнего элемента.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8