fa
Feedback
BashTex | Linux

BashTex | Linux

رفتن به کانال در Telegram

Авторский канал для тех, кто хочет глубже погрузиться в мир Linux. Подойдет для разработчиков, системных администраторов и DevOps Реклама: @dad_admin

نمایش بیشتر
2 529
مشترکین
اطلاعاتی وجود ندارد24 ساعت
اطلاعاتی وجود ندارد7 روز
-130 روز
آرشیو پست ها
Контроль превышения лимитов ulimit у сервисов Сервис падает без причины, но в логах странные ошибки:
Too many open files Resource temporarily unavailable fork: retry cannot allocate memory
Очень часто это не баг. Это лимиты ulimit. ▪️ Какие лимиты критичны 1️⃣ nofile - открытые файлы. Сколько файловых дескрипторов может открыть процесс. Проверка:

ulimit -n
Или для конкретного процесса:

cat /proc/<PID>/limits | grep "Max open files"
Если видишь 1024, то для прод-сервиса это почти всегда мало. 2️⃣ nproc - количество процессов. Ограничение на число процессов пользователя. Проверка:

ulimit -u

Или:


cat /proc/<PID>/limits | grep "Max processes"

Если приложение активно форкает воркеры - лимит может убить его.

🤩
 
Почему это сложно заметить


сервис стартует нормально
падает только под нагрузкой
в логах нет прямого указания на лимит
systemd может перезапускать бесконечно

▪️
 
Проверка лимитов у systemd-сервиса



systemctl show myservice | grep -E 'LimitNOFILE|LimitNPROC'

Если пусто, то используются дефолтные значения системы.

▪️
 Как исправить
. Создать override:


systemctl edit myservice

Добавить:


[Service]
LimitNOFILE=65535
LimitNPROC=4096

Перезагрузить:


systemctl daemon-reload
systemctl restart myservice

▪️
 Быстрая диагностика падений
. Если сервис падает под нагрузкой:

Проверить 
/proc/<PID>/limits

Посмотреть количество открытых файлов:


ls /proc/<PID>/fd | wc -l

Проверить количество процессов пользователя:


ps -u username | wc -l
BashTex 📱 #bash #check

🖥️ Выбираешь сервер под ИИ? Сначала загляни сюда 23 апреля в 11:00 (МСК) — бесплатный вебинар от CNS: «Как выбрать сервер дл
🖥️ Выбираешь сервер под ИИ? Сначала загляни сюда 23 апреля в 11:00 (МСК) — бесплатный вебинар от CNS: «Как выбрать сервер для ИИ в 2026 году: GPU, TCO и подводные камни» Если ты сейчас разбираешься, что брать под LLM, инференс или RAG — этот час сэкономит тебе кучу времени, нервов и, возможно, бюджета. Что разберём: 🔹 NVIDIA Hopper vs Blackwell — в чём реальная разница под задачи 2026 года, и не переплачиваешь ли ты за архитектуру 🔹 TCO без иллюзий — как считать полную стоимость владения, где прячутся скрытые расходы 🔹 Типичные ошибки при закупке GPU-серверов — скрытые ловушки и как грамотно сопоставить характеристики железа с реальными задачами нейросетей 🔹 Q&A-сессия — спрашивай, отвечаем честно Кому это полезно: — IT-директорам — Архитекторам и администраторам инфраструктуры — Всем, кто строит или планирует on-prem под ML/LLM/RAG 🗓 23 апреля, 11:00–12:00 МСК 📌 Регистрация: webinar.cns-corp.ru #реклама О рекламодателе

Работа с дескрипторами файлов В linux все - это файл. И каждый процесс работает с файловыми дескрипторами: 0 - stdin 1 - stdout 2 - stderr 3+ - любые дополнительные Понимание этого - ключ к нормальной автоматизации. ▪️ Базовые перенаправления

command >out.log        # stdout
command 2>err.log       # stderr
command >all.log 2>&1   # объединить
2>&1 значит: направь stderr туда же, куда сейчас смотрит stdout. ⚠️ Порядок важен: command 2>&1 >file - НЕ то же самое. ▪️ Dup (дублирование дескрипторов). Можно создать свой поток:

exec 3>debug.log
echo "debug" >&3
Теперь 3 пишет в debug.log. Это удобно, если нужно: отделить debug-лог от основного вывода не засорять stdout вести параллельный лог ▪️ Временное перенаправление

{
  echo "только в файл"
} >file.txt
Или:

exec >all_output.log 2>&1
Теперь весь скрипт пишет в лог. ▪️ Закрытие дескриптора. Иногда нужно закрыть поток:

exec 3>&-
Это освобождает дескриптор. Полезно при работе с сокетами, FIFO и временными логами. ▪️ Практический кейс. Раздельный лог и чистый stdout:

exec 3>debug.log
BASH_XTRACEFD=3
set -x
Трассировка уйдет в файл, а stdout останется чистым для пайплайна. BashTex 📱 #bash #utils

Спалили BashTex 📱 #юмор
Спалили BashTex 📱 #юмор

Почему cron не сработал Каждый админ хотя бы раз слышал: Cron не отработал. Но, спойлер: в 90% случаев cron работает. Не работает: окружение, путь или логика скрипта. 1️⃣ Неправильный PATH. Cron запускается с минимальным окружением. То, что работает в shell:

myscript.sh
В cron может не найти: command not found Проверка:

echo $PATH
Решение:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Или использовать абсолютные пути:

/usr/bin/rsync
/usr/bin/docker
2️⃣ Не тот пользователь. Есть:

crontab -e
И есть:

sudo crontab -e
Это два разных crontab. Проверка:

crontab -l
sudo crontab -l
Иногда задача просто стоит не там. 3️⃣ Нет прав на файл. Скрипт есть. Но:

chmod +x script.sh
забыли. Или владелец не тот. 4️⃣ Неправильный shebang. Если в начале:

#!/bin/bash
А на системе bash лежит в:

/usr/bin/bash
Cron молча свалится. Проверка:

which bash
Лучший вариант:

#!/usr/bin/env bash
5️⃣ Нет логирования и кажется, не сработал Если вывод не перенаправлен, ты его не увидишь. Правильно:

0 3 * * * /path/script.sh >> /var/log/script.log 2>&1
Без этого ты гадаешь. 6️⃣ Разница окружения. Cron не знает: твоих alias твоих переменных твоего virtualenv твоего nvm Если работает вручную, но не в cron - почти всегда проблема в ENV. Debug-метод:

env > /tmp/cron_env.txt
7️⃣ Скрипт падает внутри. Cron сработал. Но внутри:

rm -rf "$DIR"
где $DIR пустой. Без:

set -euo pipefail
ошибка могла остаться незамеченной. 8️⃣ Cron вообще не запущен. Редко, но бывает. Проверка:

systemctl status cron
# или
systemctl status crond
BashTex 📱 #cron

Спалили BashTex 📱 #юмор
Спалили BashTex 📱 #юмор

Sync tricks: инкременты, hard links и бэкапы Все знают про rsync, но не все используют его на 100%. Сегодня разберем три мощных приема: инкрементальные бэкапы, hard links для экономии места и атомарная схема снапшотов 1️⃣ Инкрементальный sync. База:

rsync -a --delete /data/ /backup/current/
Что происходит: -a - сохраняет права, владельца, время --delete - удаляет лишнее в приемнике Это зеркало. Но это не история. Каждый запуск перезаписывает прошлый бэкап. 2️⃣ Настоящие снапшоты через hard links. Допустим, структура такая:

/backup/
 ├── 2026-03-29/
 ├── 2026-03-30/
 └── 2026-03-31/
Команда:

TODAY=$(date +%F)
YESTERDAY=$(date -d "yesterday" +%F)

rsync -a --delete \
  --link-dest=/backup/$YESTERDAY \
  /data/ /backup/$TODAY/
Что происходит: изменённые файлы - копируются неизмененные - создаются как hard link места занимает почти как один бэкап Что тут необычного? Hard link - это не копия файла. Это второе имя для того же inode. Проверка:

ls -li file1 file2
Одинаковый inode - это один и тот же файл. Удаляешь снапшот 29-го числа и файл не удалится, если он есть в 30-м. Здесь же и начинается экономия места. Если данные почти не меняются: 30 снапшотов могут занимать +5–10% к объему, вместо ×30 бэкапов. Это почти как ZFS snapshots, но работает на обычном ext4. 3️⃣ Атомарная схема без битых бэкапов. Никогда не пиши прямо в конечную папку. Правильно:

rsync -a --delete \
  --link-dest=/backup/$YESTERDAY \
  /data/ /backup/.tmp-$TODAY/ &&
mv /backup/.tmp-$TODAY /backup/$TODAY
Теперь: если rsync упал - снапшот не появится всегда либо полный, либо отсутствует 4️⃣ Ротация снапшотов. Храним 14 дней:

find /backup -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;
(Осторожно с путями.) 🛠 Мини-скрипт

#!/usr/bin/env bash
set -euo pipefail

SRC="/data"
DST="/backup"
TODAY=$(date +%F)
YESTERDAY=$(ls -1 $DST | sort | tail -n 1)

rsync -a --delete \
  ${YESTERDAY:+--link-dest=$DST/$YESTERDAY} \
  "$SRC/" "$DST/.tmp-$TODAY/"

mv "$DST/.tmp-$TODAY" "$DST/$TODAY"
Первый запуск - обычная копия. Все следующие - инкременты. BashTex 📱 #bash #backup

Не все так просто, кожаный BashTex 📱 #юмор
Не все так просто, кожаный BashTex 📱 #юмор

Автоматический failover при недоступности mount-точки Неприятная ситуация когда mount вроде есть, но по факту хранилище уже умерло. NFS отвалился. iSCSI завис. Ceph не отвечает. Сервис продолжает писать… в никуда. Решение - автоматическая логика: Проверка -> попытка remount -> переключение на fallback. ▪️ Логика failover Проверяем, что mount существует; Проверяем доступность записи; Если ошибка, то пробуем remount; Если не помогло - переключаемся на fallback. 🛠 Пример скрипта

#!/usr/bin/env bash

MOUNT_POINT="/data"
FALLBACK="/data_local"
TEST_FILE="$MOUNT_POINT/.healthcheck"

log() {
  echo "$(date '+%F %T') | $1"
}

check_mount() {
  mountpoint -q "$MOUNT_POINT" || return 1
  timeout 3 touch "$TEST_FILE" 2>/dev/null || return 1
  rm -f "$TEST_FILE"
}

remount() {
  log "Попытка remount..."
  mount -o remount "$MOUNT_POINT"
}

switch_to_fallback() {
  log "Переключение на fallback $FALLBACK"
  umount -l "$MOUNT_POINT"
  mount --bind "$FALLBACK" "$MOUNT_POINT"
}

main() {
  if check_mount; then
    log "Mount работает нормально"
    exit 0
  fi

  log "Mount недоступен"

  remount && sleep 2

  if check_mount; then
    log "Remount помог"
    exit 0
  fi

  switch_to_fallback
}

main
▪️ Что здесь важно 1. timeout - если NFS завис, без timeout скрипт повиснет навсегда. 2. mountpoint -q - Проверяет именно mount, а не просто директорию. 3. umount -l - lazy umount - полезно, если есть залипшие процессы. ▪️ Как запускать правильно Лучше всего: systemd timer или healthcheck внутри сервиса или отдельный watchdog unit ⚠️ Нюансы Если сервис пишет активно, то нужно ставить его на паузу перед failover; fallback должен быть заранее подготовлен; важно логировать переключения; нужен механизм возврата обратно. BashTex 📱 #bash #utils

Профилирование bash-скрипта Большинство bash-скриптов медленные не потому что bash плохой, а потому что внутри: лишние grep | awk | sed, десятки subshell, сетевые вызовы без таймаутов и циклы по 100k строк И пока не измерил - не оптимизируешь. 1️⃣ Базовый уровень - time. Самое простое:

time ./script.sh
Вывод:

real    0m3.421s
user    0m0.212s
sys     0m0.084s
Что важно: real - общее время (включая ожидание сети, IO) user - CPU в user space sys - системные вызовы
Если real > user + sys - это значит, что скрипт ждет (сеть, диск, sleep). Если user большой - это значит много вычислений. 2️⃣ Профилирование построчно через DEBUG trap. Настоящая магия начинается здесь.

#!/usr/bin/env bash

PS4='+ $(date "+%s.%N") '
exec 3>&2
BASH_XTRACEFD=3
set -x
Но это просто трассировка. Чтобы измерять время между строками:

#!/usr/bin/env bash

last_time=$(date +%s%N)

trap '
  now=$(date +%s%N)
  diff=$(( (now - last_time) / 1000000 ))
  echo "${diff} ms → $BASH_COMMAND"
  last_time=$now
' DEBUG
Теперь перед каждой командой будет вывод:

2 ms → var=$(cat file)
153 ms → curl https://api
1 ms → echo done
И сразу видно: где реальная задержка, какой вызов тормозит и сколько стоит subshell ⚠️ Важно trap DEBUG вызывается перед каждой командой, включая: внутренние, подстановки и циклы. На больших скриптах лог будет огромный. ▪️ Мини-профилировщик функции. Если нужно измерить только конкретный блок:

measure() {
  local start=$(date +%s%N)
  "$@"
  local end=$(date +%s%N)
  echo "Функция заняла $(( (end - start)/1000000 )) ms"
}
Использование:

measure heavy_function
BashTex 📱 #bash #utils

Почему sleep - это костыль? Очень часто используют такую конструкцию:

curl https://api.bashtex.com || sleep 5 && curl https://api.bashtex.com
Или ещё хуже: в цикле с фиксированной паузой. Это неуправляемый retry, который: создает лишнюю нагрузку, не учитывает тип ошибки, не масштабируется и может устроить небольшой DDoS при массовом падении сервиса. Правильный подход - retry с exponential backoff. ▪️ Почему sleep 5 - это плохая стратегия. Представим: API лежит 2 минуты. 100 серверов начинают делать: запрос -> sleep 5 -> запрос -> sleep 5 → … Ты получаешь синхронную атаку на уже мертвый сервис. Exponential backoff делает паузы все длиннее: 1s -> 2s -> 4s -> 8s -> 16s -> ... Это: снижает нагрузку, дает сервису восстановиться, уменьшает каскадные падения 🛠 Базовая retry-обертка

retry() {
  local max_attempts=$1
  shift

  local attempt=1
  local delay=1

  while true; do
    "$@" && return 0

    if (( attempt >= max_attempts )); then
      echo "Команда не удалась после $attempt попыток"
      return 1
    fi

    echo "Попытка $attempt неудачна. Повтор через $delay сек."
    sleep "$delay"

    attempt=$(( attempt + 1 ))
    delay=$(( delay * 2 ))
  done
}
▪️ Использование:

retry 5 curl -fsS https://api.bashtex.com
▪️ Что здесь происходит "$@" - передаем любую команду; выходной код управляет retry; задержка удваивается; максимум попыток ограничен. ▪️ Когда retry вреден при логических ошибках (401, 403); если операция не идемпотентна; если сервис возвращает fatal error. Retry должен применяться к временным ошибкам, а не ко всем подряд. BashTex 📱 #bash #utils

Генерация временных файлов Практически каждый, кому необходимы были временные файлы писал так:

TMP="/tmp/script.$RANDOM"
И вроде все ок, но на деле это один из самых старых и самых недооцененных багов в bash. ▪️ Почему /tmp/file.$RANDOM - это плохая идея 1️⃣ Коллизии. $RANDOM - это число от 0 до 32767. При параллельном запуске скриптов совпадения реальны. 2️⃣ Race condition. Ты:

echo "data" > /tmp/file.$RANDOM
А злоумышленник заранее создал симлинк с таким именем и твой скрипт перезапишет чужой файл. Это классическая symlink attack. 3️⃣ Неправильные права. Файл создается с текущим umask. Это может быть не то, что ты ожидал. ▪️ Правильный способ - mktemp

TMP=$(mktemp)
Результат:

/tmp/tmp.ABCd93kL
Что делает mktemp: генерирует криптографически безопасное имя создаёт файл атомарно выставляет права 600 исключает race condition
▪️ Создание временной директории

TMP_DIR=$(mktemp -d)
▪️ Правильная очистка. Всегда следует добавлять cleanup:

TMP=$(mktemp)

cleanup() {
  rm -f "$TMP"
}
trap cleanup EXIT
Теперь файл удалится даже при ошибке или Ctrl+C. ▪️ Когда нужно имя с префиксом

mktemp /tmp/myscript.XXXXXX
Или:

mktemp -d /tmp/myscript.XXXXXX
XXXXXX обязательно - это шаблон. BashTex 📱 #bash #utils

Отладка bash-скриптов В bash есть встроенная трассировка, и она может быть эффективнее любого printf-дебага. 1️⃣ Включаем трассировку

set -x
Теперь каждая команда будет выводиться перед выполнением:

+ var=10
+ echo 10
Отключить:

set +x
Полезно включать только на проблемном участке. 2️⃣ Отладка всего скрипта. Можно запустить сразу так:

bash -x script.sh
Или добавить в начало:

#!/bin/bash
set -x
3️⃣ Сделать трассировку читаемой. По умолчанию вывод начинается с +. Это скучно. Можно добавить больше контекста:

export PS4='+ $(date "+%H:%M:%S") ${BASH_SOURCE}:${LINENO}: '
Теперь вывод будет выглядеть так:

+ 14:32:10 script.sh:12: var=10
Здесь видно: время, файл и номер строки Для сложных скриптов - это крайне полезно. 4️⃣ Отдельный лог отладки. Чтобы не засорять stdout:

exec 3>/tmp/debug.log
BASH_XTRACEFD=3
set -x
Теперь трассировка уйдет в /tmp/debug.log, а основной вывод останется чистым. Это особенно важно для автоматизации и CI. 5️⃣ Отладка переменных. Полезные режимы:

set -u   # ошибка при использовании unset переменной
set -e   # выход при ошибке
set -o pipefail  # ловим ошибки в пайпах
Продвинутый вариант:

set -euxo pipefail
BashTex 📱 #bash #utils

Сравнение конфигураций сервиса между серверами Классическая ситуация: на одном сервере все работает. На другом - нет. При этом версии одинаковые, ОС одинаковая, но потом спустя время выясняется: конфиг отличается на одну строку.
😁Задача Сравнить конфигурации одного сервиса между серверами: nginx.conf sshd_config app.conf Быстро. Чисто. Без копипасты глазами.
1️⃣ Самый простой способ - diff через SSH

ssh server1 "cat /etc/nginx/nginx.conf" > s1.conf
ssh server2 "cat /etc/nginx/nginx.conf" > s2.conf

diff -u s1.conf s2.conf
Но это неудобно и мусорно. Лучше сразу:

diff -u \
  <(ssh server1 "cat /etc/nginx/nginx.conf") \
  <(ssh server2 "cat /etc/nginx/nginx.conf")
Чисто. Без временных файлов. 2️⃣ Игнорировать комментарии и пустые строки. Очень часто различия только в комментариях.

diff -u \
  <(ssh s1 "grep -vE '^\s*#|^\s*$' /etc/ssh/sshd_config") \
  <(ssh s2 "grep -vE '^\s*#|^\s*$' /etc/ssh/sshd_config")
Теперь сравнивается только реальная логика. 3️⃣ Если это nginx - сравнивать весь effective config. У nginx часто include-файлы. Правильнее:

ssh s1 "nginx -T" > s1.nginx
ssh s2 "nginx -T" > s2.nginx

diff -u s1.nginx s2.nginx
Так мы сравниваем итоговую конфигурацию. 4️⃣ Проверка sshd. У ssh есть удобная команда:

sshd -T
Она выводит итоговую конфигурацию с учетом defaults. Сравниваем так же через process substitution. 5️⃣ Если серверов много. Массовая проверка:

for host in s1 s2 s3; do
  ssh "$host" "sshd -T" | sort > "$host.conf"
done

diff -u s1.conf s2.conf
Сортировка помогает убрать разницу порядка строк. BashTex 📱 #bash #utils

Свернуть с этой дорожки уже не получится BashTex 📱 #юмор
Свернуть с этой дорожки уже не получится BashTex 📱 #юмор

Управление выводом В консоли все выглядит одинаково. Но для системы это два разных потока: stdout - нормальный вывод (FD 1) stderr - ошибки (FD 2) И если их не различать - автоматизация начинает ломаться. ▪️ Что такое stdout и stderr. Пример:

echo "OK"
echo "ERROR" >&2
Первое уйдет в stdout, второе в stderr. Проверим:

./script.sh >out.log 2>err.log
Теперь: out.log - нормальный результат err.log - ошибки ⚠️ Почему это важно 1️⃣ CI/CD пайплайны. В системах вроде GitHub Actions или GitLab CI: stdout - это лог выполнения stderr - это ошибка шага Если приложение пишет все в stdout, то и пайплайн может считать шаг успешным. 2️⃣ Парсинг вывода в скриптах. Типичная ошибка:

result=$(some_command)
Если some_command пишет ошибку в stdout - переменная будет содержать текст ошибки. Автоматизация съест ее как валидные данные. 3️⃣ Логирование в systemd. В systemd: stdout - это StandardOutput stderr - это StandardError Если сервис пишет ошибки в stdout, мониторинг может их не выделить. 🤩 Типичный анти-паттерн

if curl bashtex.com; then
  echo "OK"
fi
Если curl вернет HTTP 500, сообщение об ошибке может уйти в stdout. 🤩 Правильно:

if curl -fsS bashtex.com; then
  echo "OK"
else
  echo "FAIL" >&2
fi
▪️ Управление потоками. Раздельная запись

command >out.log 2>err.log
Объединить

command >all.log 2>&1
Игнорировать ошибки

command 2>/dev/null
Поменять местами

command 3>&1 1>&2 2>&3
BashTex 📱 #bash #utils

Чеклист для ситуации, когда сервер под нагрузкой Представим ситуацию, сервер начинает тормозить, мониторинг краснеет, а пользователи уже бегут к телефону или генерируют инциденты. На этот случай и написан чеклист, что проверять в первую очередь. 1️⃣ CPU: кто жрет процессор

uptime
Смотрим: Load Average сравниваем с количеством CPU (nproc)
Если load > количества ядер - это означает, что проблема есть. Детализация:

top
Смотрим: %CPU us / sy / wa процессы в топе
Если высокий wa, то проблема в IO. 2️⃣ IO: не уперлись ли в диск

iostat -xz 1 3
Смотрим: %util await svctm
Если %util ≈ 100% - диск забит. Быстрое упрощение:

iotop
Кто активно пишет/читает. 3️⃣ Память: нет ли OOM

free -h
Проверяем: свободная память swap
И сразу:

dmesg | grep -i oom
Если есть OOM Killer, то причина найдена. 4️⃣ Сеть: не уперлись ли в соединения

ss -s
Смотрим: ESTAB TIME-WAIT orphaned sockets
И:

iftop
Кто льет трафик. 5️⃣ Процессы: нет ли runaway

ps aux --sort=-%cpu | head
ps aux --sort=-%mem | head
Смотрим: неожиданные процессы бесконечные воркеры
6️⃣ Быстрый общий снимок

top -b -n1 | head -20
Будет полезно для фиксации состояния. BashTex 📱 #bash #utils

Почему сервис не стартует? 1️⃣ Быстрая проверка статуса

systemctl status myservice -n 20 --no-pager
Смотрим: Loaded Active ExecStart последние строки логов
2️⃣ Смотрим реальные ошибки из journal

journalctl -u myservice -xe --no-pager
Частые сообщения: Permission denied No such file or directory Address already in use Failed to bind Unit entered failed state
3️⃣ Проверяем unit-файл

systemctl cat myservice
Ошибки часто здесь: неправильный путь в ExecStart забыли daemon-reload лишний User= отсутствующая рабочая директория
Проверка синтаксиса:

systemd-analyze verify /etc/systemd/system/myservice.service
4️⃣ Типовые причины, которые встречаются чаще всего 🤩 Неверный путь к бинарнику: ExecStart=/usr/bin/app Файл не существует и сервис не стартует. 🤩 Порт уже занят

ss -lntp | grep 8080
🤩 Неправильные права

ls -l /path/to/app
Нужно проверить владельца и execute-бит. 🤩 Ошибка в конфиге приложения. Попробуй запустить вручную:

sudo -u serviceuser /usr/bin/app
🛠 Небольшой скрипт диагностики

#!/bin/bash
SERVICE="$1"

echo "=== STATUS ==="
systemctl status "$SERVICE" -n 10 --no-pager

echo
echo "=== LAST ERRORS ==="
journalctl -u "$SERVICE" -n 20 --no-pager

echo
echo "=== UNIT FILE ==="
systemctl cat "$SERVICE"

echo
echo "=== PORT CHECK ==="
ss -lntp | grep "$(systemctl show "$SERVICE" -p ExecStart --value | awk '{print $1}')" 2>/dev/null
Запуск:

./diag.sh nginx
BashTex 📱 #bash #utils

Опрос о DevOps-практиках от MWS Cloud Platform и DevOpsConf 2026 Вместе с MWS Cloud Platform изучаем DevOps-практики. Какие и
Опрос о DevOps-практиках от MWS Cloud Platform и DevOpsConf 2026 Вместе с MWS Cloud Platform изучаем DevOps-практики. Какие инструменты используют команды, какие есть боли в безопасности и IDP, что происходит с внедрением AI в реальные процессы? Заполните опрос и получите: ✅ Доступ к результатам опроса (презентация 3 апреля на DevOpsConf и в сообществе MWS Cloud Platform ✅ Возможность выиграть билеты на HighLoad++, TeamLead Conf, FrontendConf или другие конференции Онтико (оплачиваем проживание, если вы из региона) ✅ Подарки от MWS Cloud Platform авторам самых интересных комментариев к разделам 👉 Пройти опрос о DevOps-практиках Время прохождения: около 7 минут. Итоги розыгрыша билетов подведем 7 апреля в сообществе MWS Cloud Platform. #реклама О рекламодателе

Само обнаружение BashTex 📱 #юмор
Само обнаружение BashTex 📱 #юмор