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

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

Реклама: @dad_admin
Download Telegram
Это был неправильный ответ, подумай еще

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14
Анализ активности пользователей через .bash_history

Если ты хочешь узнать, кто чем занимался на сервере, не прибегая к сложным средствам аудита - начни с простого: разбор ~/.bash_history. Это быстрый способ получить отчёт об активности пользователей, особенно если логи команд не централизуются.

Что можно узнать:

📍Самые часто используемые команды
📍Подозрительные или потенциально опасные действия
📍Время последней активности (если HISTTIMEFORMAT включён)
📍Кто запускал sudo, rm, curl, scp и прочие «чувствительные» команды


🛠 Пример скрипта:


#!/bin/bash

REPORT="/tmp/history_report.txt"
KEY_CMDS="sudo|rm|curl|scp|wget|nc|nmap|python|ssh|dd"

echo "Отчёт об активности пользователей - $(date)" > "$REPORT"
echo >> "$REPORT"

for user_home in /home/*; do
user=$(basename "$user_home")
hist_file="$user_home/.bash_history"

[[ -f "$hist_file" ]] || continue

echo "Пользователь: $user" >> "$REPORT"
echo "— Топ 5 команд:" >> "$REPORT"
grep -v '^#' "$hist_file" | awk '{print $1}' | sort | uniq -c | sort -rn | head -n 5 >> "$REPORT"

echo "— Подозрительные команды:" >> "$REPORT"
grep -E "$KEY_CMDS" "$hist_file" | tail -n 5 >> "$REPORT"
echo >> "$REPORT"
done

cat "$REPORT"


▪️ Проверка root-пользователя:


grep -E "$KEY_CMDS" /root/.bash_history | tail -n 5


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

🌟 Этот простой анализ позволяет выявить:

- кто часто использует sudo, rm -rf, dd
- несанкционированную установку пакетов (apt install, curl | bash)
- запуск сетевых туннелей (ssh -R, ngrok, socat)


BashTex 📱 #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Управление процессами после разрыва сессии

Бывало такое: запустил долгую задачу, закрыл терминал - и всё пропало. А что если процесс всё ещё жив, и ты можешь снова им управлять?

Сегодня разберём два инструмента:

ts - из moreutils для запуска с timestamp
reptyr - для перехвата уже запущенного процесса и перевода его обратно в терминал

🌟 Сценарий: восстановление "осиротевшего" процесса

1️⃣ Запустили задачу без screen или tmux:


some-heavy-task.sh &


2️⃣ Вышли из терминала, но процесс живёт (можно найти через ps или top).

3️⃣ Подключаемся обратно, узнаём PID:


ps aux | grep some-heavy-task


4️⃣ Забираем процесс себе:


reptyr <PID>


Теперь процесс снова управляем - можно читать вывод, отменить Ctrl+C, передать сигналы.

⚙️ Установка


sudo apt install reptyr moreutils # Ubuntu/Debian
sudo yum install reptyr moreutils # RHEL/CentOS


🔥 ts - лог с таймштампами. Хочешь узнать, когда именно что-то произошло в логе?


long-running-command | ts '[%Y-%m-%d %H:%M:%S]'


Пример вывода:


[2025-06-10 10:03:10] Запущено обновление системы
[2025-06-10 10:03:25] Завершено без ошибок


Идеально для cron-скриптов, CI-логов и мониторинга.

❗️ Ограничения и советы

📍 reptyr не всегда работает, если у процесса есть PTY или взаимодействие с stdin.

📍 Чтобы reptyr работал на Ubuntu 20+ - нужно отключить Yama security:


echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope


(для постоянства: добавь в /etc/sysctl.d/10-ptrace.conf)

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥2
Игроман или что? 🤔

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8🔥5
Автогенерация help/usage в Bash

Одна из лучших практик при написании bash-утилит - добавлять --help, чтобы объяснять, как работает скрипт. Но зачем дублировать описание в заголовке и в коде, если можно использовать один и тот же блок? С помощью cat <<EOF и sed можно генерировать справку прямо из комментариев скрипта.

🛠 Пример структуры скрипта:


#!/bin/bash

: <<'USAGE'
my-script.sh - полезный инструмент

Использование:
./my-script.sh [опции]

Опции:
-h показать помощь
-f FILE указать файл
-v включить подробный вывод

Пример:
./my-script.sh -f config.ini -v
USAGE

# Генерация help из заголовка
show_help() {
sed -n "/^: <<'USAGE'/,/^USAGE/p" "$0" | sed '1d;$d'
}

while getopts ":hf:v" opt; do
case $opt in
h) show_help; exit 0 ;;
f) FILE=$OPTARG ;;
v) VERBOSE=1 ;;
\?) echo "Неверный флаг: -$OPTARG" >&2; show_help; exit 1 ;;
esac
done


⭐️ Как это работает?

📍 : <<'USAGE' ... USAGE - это многострочный комментарий.
📍 sed -n '/^: <<'\''USAGE'\''/,/^USAGE/p' "$0" - извлекает его.
📍 В show_help() мы красиво выводим только нужный блок.


Теперь ты всегда видишь usage в начале файла - и это единственный источник правды.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁19
Управление каталогами через стек путей

Все еще используешь 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: просмотр пути


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 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
Автоматическая генерация CHANGELOG из git log

Если ты оформляешь релизы или просто хочешь видеть историю изменений красиво, не нужно писать CHANGELOG.md вручную. Bash + git log = автоматическая генерация понятного и читаемого списка коммитов по тегу или дате.

🛠 Простой changelog между тегами


#!/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/


⭐️ Совет: Добавить в Makefile или release.sh:


changelog:
bash scripts/gen_changelog.sh


И у тебя всегда будет свежий, читаемый список изменений для клиентов или команды.

BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Автоматическое обновление и перезапуск Docker-контейнеров при выходе новых образов

Если ты используешь докер и хочешь держать свои контейнеры в актуальном состоянии без ручного 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


▪️ Для автоматизации: Добавь скрипт в cron или systemd-timer, например, каждые 6 часов:


0 */6 * * * /usr/local/bin/docker-auto-update.sh


⭐️ Советы:

📍 Используй docker inspect для восстановления аргументов запуска, если параметры сложные.
📍Для нескольких контейнеров используй массивы и цикл.


BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Bash и двоичные данные: читаем, конвертируем, анализируем

Bash - не только для текста. Иногда приходится парсить бинарные файлы, смотреть их содержимое, искать сигнатуры или работать с данными в base64. В арсенале есть несколько утилит: xxd, od, base64 - и ты удивишься, сколько они могут.

▪️ xxd - человекочитаемый hex-дамп


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 - гибкий дампер


od -An -t x1 -v myfile.bin


Это дает HEX-дамп без смещений, только байты. Удобно для парсинга в скриптах.


od -An -t d2 myfile.bin


Читаем 2-байтные значения как целые числа.

▪️ base64 - кодирование/декодирование в текст. Когда бинарь нужно «перенести» в текст:


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 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Локальное зеркало APT-репозитория с Bash и rsync

Обновление пакетов без внешнего интернета - это реально. Если ты обслуживаешь несколько серверов в ограниченной сети (или хочешь ускорить установку и обновление пакетов), стоит создать локальное зеркало 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


▪️ Автоматизация. Добавь скрипт в cron или systemd-timer для ежедневной синхронизации:


0 4 * * * /usr/local/bin/apt-mirror-sync.sh


Локальное зеркало экономит трафик, ускоряет установку и даёт контроль над пакетами в изолированных окружениях.

BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Когда спрашивают почему я выбрал Linux

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20
Автоматизация создания пользователя в Linux

Каждый раз настраивать нового юзера вручную - скучно. Особенно если нужно: создать пользователя, выдать sudo, настроить SSH-доступ, прописать алиасы и окружение

🛠 Решается скриптом (create_user.sh):


#!/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 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1
Bash-функции с возможностью изменять аргументы

Когда ты передаешь переменные в функции - по умолчанию это копии, а не ссылки. Но с declare -n (aka nameref) можно менять переменные по ссылке, включая элементы массивов и даже динамические имена переменных.

Что такое 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


❗️ Когда использовать nameref?

📍 Когда хочется возвращать несколько значений из функции
📍 Когда работаешь с динамическими именами переменных
📍 Когда пишешь библиотеки/модули на Bash


BashTex 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Фоновая очередь с приоритетами

Когда ты запускаешь десятки фоновых задач - важно не просто кидать их в фон через &, а управлять их приоритетом, нагрузкой и порядком выполнения.

💎 Используем:

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 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🗿1
Создаем интерактивность в терминале

Когда хочется добавить взаимодействие в скрипт, но без навороченного TUI, достаточно трех команд Bash: read -s, tput, stty. С их помощью можно: скрыть ввод паролей, управлять курсором, отключать echo, обрабатывать клавиши "на лету".

▪️ read -s - скрытый ввод. Используется для ввода пароля:


read -sp "Введите пароль: " password
echo -e "\nПароль получен!"


-s - скрыть, -p - prompt, -e - enable readline, -n - количество символов

▪️ tput - контроль терминала


tput civis # скрыть курсор
tput cnorm # вернуть курсор
tput setaf 2; echo "Зелёный текст"; tput sgr0


Примеры:

setaf - цвет текста (0-7)
setab - цвет фона
cup 5 10 - переместить курсор на строку 5, столбец 10
clear - очистить экран

▪️ stty - контроль поведения терминала


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 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
Аудит sudo-доступа всех пользователей


#!/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


🔎 Что делает скрипт:

📍 Сканирует всех пользователей с интерактивным shell;
📍 Выводит sudo -l для каждого;
📍 Ищет опасные команды с NOPASSWD, которые могут дать root-доступ.

▪️ Пример опасных конструкций в sudoers:


(user) NOPASSWD: /usr/bin/vim
(user) NOPASSWD: /usr/bin/find / -exec
(user) NOPASSWD: /usr/bin/python3


Такие команды позволяют поднять интерактивный shell от root без ввода пароля - критическая уязвимость, если не контролируется.

BashTex 📱 #bash #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Перенос окружения на другой сервер с возможностью отката

Забудь про ручное копирование. Используй 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


▪️ Версионирование. Каждая копия создаётся с уникальным timestamp'ом, и ты всегда можешь:

📍 Вернуться к предыдущей версии;
📍 Отслеживать изменения в алиасах и bash-окружении;
📍 Проверять дифф между окружениями:


diff -u ~/env-backup/20240601-1000/.bashrc ~/env-backup/20240520-0900/.bashrc


🌟 Рекомендация. Добавь в ~/.bashrc:


[[ -f ~/.bash_aliases ]] && source ~/.bash_aliases
[[ -f ~/env-backup/env.sh ]] && source ~/env-backup/env.sh


BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9
Профилирование скрипта: time, PS4, set -x - лог с таймингом каждой строки

🔎 Скрипт тормозит, но где? Чтобы найти бутылочное горлышко в скрипте, нужно понять, какая строка выполняется долго, а не просто смотреть на общее time.

Решение: профилирование через связку:

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"


▪️ Вывод лога trace.log:


+ 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: Если обернуть скрипт:


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 📱 #bash #utils
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥4
Одна ошибка и ты ошибся

BashTex 📱 #юмор
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17🗿2
Очистка зависших SSH-сессий

Иногда пользователи (или вы сами) забывают выйти с сервера, и сессия остается в статусе idle или stuck, занимая ресурсы, блокируя терминалы и даже мешая обновлениям. Хорошая новость: Bash + w + ps + timeout помогут автоматически завершать такие сессии.

Что считать зависшей сессией?

📍 Бездействие более 30 минут;
📍 Нет активных процессов;
📍 Неиспользуемый TTY;

🛠 Скрипт для автоудаления "спящих" SSH-сессий


#!/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


❗️ Дополнительно:

📍 Добавь в исключения TTY root'а, CI/CD, сервисных пользователей;
📍 В проде лучше сначала логировать, потом - удалять;

BashTex 📱 #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍2