NetworkAdmin.ru
4.71K subscribers
251 photos
36 videos
2 files
683 links
Авторский блог про сетевое и системное администрирование.

Сайт: networkadmin.ru
Реклама: @dad_admin
Биржа: https://telega.in/c/networkadminru
Download Telegram
🌀 Retry-логика в bash: как аккуратно повторять нестабильные операции

В админских скриптах не все ошибки означают, что все окончательно сломалось. Иногда команда падает из-за временной проблемы:

• сеть моргнула;
• API вернул timeout;
• DNS не ответил с первого раза;
• файл еще не появился;
• сервис еще не успел подняться;
• удаленный хост временно недоступен.

В таких случаях полезна retry-логика - аккуратный повтор операции несколько раз перед тем, как считать задачу проваленной.

🤩 Плохой вариант:


curl -fsS https://api.networkadmin.ru/deploy


Если запрос один раз упал - весь скрипт завершился.

🤩 Лучше сделать повтор:


for i in {1..5}; do
if curl -fsS https://api.networkadmin.ru/deploy; then
echo "success"
break
fi

echo "attempt $i failed, retrying..."
sleep 5
done


Но у такого варианта есть проблема: после всех неудачных попыток скрипт может продолжить работу, если явно не обработать итог.

🤩 Более аккуратный вариант - вынести retry в функцию:


retry() {
local max_attempts="$1"
local delay="$2"
shift 2

local attempt=1

until "$@"; do
if (( attempt >= max_attempts )); then
echo "command failed after $attempt attempts: $*" >&2
return 1
fi

echo "attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"
((attempt++))
done
}


Теперь можно использовать так:


retry 5 3 curl -fsS https://api.networkadmin.ru/health


Или дождаться доступности сервиса:


retry 10 2 nc -z 127.0.0.1 5432


5 или 10 - количество попыток
3 или 2 - пауза между попытками
дальше идет команда, которую нужно повторять

▪️ Для операций с сетью часто полезен backoff - увеличение паузы после каждой ошибки:


retry_backoff() {
local max_attempts="$1"
local delay="$2"
shift 2

local attempt=1

until "$@"; do
if (( attempt >= max_attempts )); then
echo "command failed after $attempt attempts: $*" >&2
return 1
fi

echo "attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"

delay=$((delay * 2))
((attempt++))
done
}


Пример:


retry_backoff 5 2 curl -fsS https://api.networkadmin.ru/status


Паузы будут примерно такими: 2s -> 4s -> 8s -> 16s

Это лучше, чем агрессивно долбить нестабильный сервис каждые 100 мс.

#bash #automation

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
📎 rsync: полезные ключи для бэкапов и аккуратной синхронизации

rsync - одна из тех утилит, которые годами живут в админских скриптах и не теряют актуальности. Ее любят за простую идею: сравнить источник и приемник, а потом скопировать только то, что реально изменилось. Особенно хорошо rsync показывает себя на каталогах с большим количеством файлов. Если нужно синхронизировать два хранилища с сотнями тысяч или миллионами объектов, обычное копирование быстро превращается в боль. У rsync есть минусы. Главный - он не становится магически многопоточным. Но для задач, где нужно копировать файлы как есть, без упаковки, дедупликации и сложных backup-форматов, это все еще очень удобный инструмент. Ниже несколько ключей, которые полезно помнить.

▪️ --backup и --backup-dir. Обычно при синхронизации мы хотим привести приемник к состоянию источника. Например:


rsync -av --delete source/ dest/


Но для бэкапов часто важно не просто удалить старые или измененные файлы, а сохранить их отдельно. Для этого есть связка:


--backup
--backup-dir=/path/to/old-files


Пример:


rsync -av --delete --backup \
--backup-dir="/mnt/data/backup/bases_increment/$(date +%F)/" \
back_user@10.20.5.22:/var/lib/pgpro/backup/ \
/mnt/data/backup/bases/ \
>> "/var/log/rsync/1Csrv-$(date +%F).log"


• новые файлы попадут в основной каталог бэкапа;
• файлы, которые должны быть удалены или заменены, будут перемещены в backup-dir;
• изменения за конкретный день окажутся в отдельной папке;
• глубину хранения можно потом регулировать через find.

Это удобно, если нужно видеть, что именно изменилось между запусками. Например, если на сайте кто-то заменил несколько файлов, при очередном бэкапе старые версии можно будет найти в отдельном каталоге.

▪️ --progress. Ключ показывает прогресс копирования файлов:


rsync -av --progress source/ dest/


В логе будет видно размер, скорость и время передачи. Это удобно для крупных файлов: дампов баз, архивов, образов. Но если файлов очень много и они мелкие, --progress может сильно засорить вывод. В таких случаях лучше использовать более спокойный режим:


rsync -av --info=progress2 source/ dest/


или вообще убрать прогресс из cron-задачи.

▪️ --ignore-existing. Этот ключ полезен, когда нужно восстановить только отсутствующие файлы и не трогать то, что уже есть в целевой директории.
Например, кто-то удалил часть файлов в /var/www, а мы хотим вернуть недостающее из бэкапа:


rsync -av --ignore-existing \
back_user@10.30.7.5:/mnt/backup/www/ \
/var/www/


• отсутствующие файлы будут скопированы;
• существующие файлы не будут перезаписаны;
• даже если в бэкапе версия новее, rsync ее не тронет.

Это хороший вариант для аккуратного "докинуть недостающее".

▪️ --update. Копирует файл только если версия в источнике новее, чем в приемнике.


rsync -av --update \
back_user@10.30.7.5:/mnt/backup/www/ \
/var/www/


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

▪️ --dry-run. Один из самых важных ключей, особенно если в команде есть --delete.


rsync -av --delete --dry-run source/ dest/


или короче:


rsync -avn --delete source/ dest/


--dry-run показывает, что rsync сделал бы, но ничего реально не меняет. Это спасает от классической ошибки: перепутали источник и приемник - и удалили не там. Перед первой настройкой бэкапа или синхронизации лучше всегда запускать тестовый прогон.

▪️ Отдельно стоит помнить про слеш в конце пути.


rsync -av /data/source/ /backup/source/


копирует содержимое каталога source. А так:


rsync -av /data/source /backup/


копирует сам каталог source внутрь /backup. На первый взгляд мелочь, но из-за этого часто получают не ту структуру директорий.

#linux #rsync

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
📺 Скриншот рабочего стола пользователя через PowerShell и PsExec

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

• пользователь не может нормально описать ошибку;
• окно с сообщением быстро исчезает;
• приложение зависло в нестандартном состоянии;
• нужно увидеть текущий экран без полноценного подключения по RDP/AnyDesk;
• удаленный просмотр экрана в компании не используется или ограничен.

В таких случаях можно сделать простой механизм: по заявке и с согласия пользователя получить скриншот его текущего рабочего стола и сохранить PNG-файл в сетевую папку. Один из вариантов - PowerShell-скрипт, который делает снимок экрана в интерактивной сессии пользователя, и удаленный запуск через PsExec. Пример запуска:


.\PsExec.exe -s -i 1 \\pk-ww01 powershell.exe `
-ExecutionPolicy Bypass `
-WindowStyle Hidden `
-File "\\fs01\scripts\PS-Capture-Local-Screen.ps1"


\\pk-ww01 - удаленная рабочая станция
-s - запуск от имени Local System
-i 1 - запуск в интерактивной сессии пользователя
powershell.exe - выполнение PowerShell-скрипта
\\fs01\scripts\... - путь к скрипту на файловом сервере

Сам скрипт делает снимок рабочего стола и сохраняет файл, например, в общую сетевую папку: \\fs01\support\screenshots\. И дальше сотрудник техподдержки может открыть PNG-файл и посмотреть, что было на экране в момент обращения.

#powershell #psexec

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
👁 Conntrack в Linux: как stateful firewall может стать узким местом

Когда на linux работает NAT или stateful firewall, почти всегда где-то рядом есть conntrack. Conntrack - это механизм ядра, который отслеживает сетевые соединения. Он нужен, чтобы firewall понимал не только отдельный пакет, но и его состояние:

• это новое соединение;
• это ответ на уже разрешенное соединение;
• это часть существующей сессии;
• это странный или неожиданный пакет.

Именно поэтому в iptables/nftables часто встречается логика:


-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT


или в nftables:


ct state established,related accept


Смысл простой: если соединение уже разрешено, ответы по нему пропускаем автоматически. Без conntrack не было бы привычного NAT, нормального stateful firewall и многих схем с masquerade. Но у conntrack есть цена. Каждое отслеживаемое соединение попадает в таблицу conntrack. Если соединений много, таблица растет. Если таблица переполнена, начинаются неприятности.

▪️ Типичные симптомы:

• новые подключения отваливаются;
• NAT начинает работать нестабильно;
• часть клиентов не может открыть сайт;
• DNS-запросы теряются;
• в логах появляются сообщения про переполнение conntrack;
• снаружи кажется, что "сеть иногда моргает".

▪️ Проверить текущий лимит:


sysctl net.netfilter.nf_conntrack_max


Посмотреть текущее количество записей:


cat /proc/sys/net/netfilter/nf_conntrack_count


Если значение nf_conntrack_count регулярно подходит к nf_conntrack_max, система близка к проблемам.

Еще можно посмотреть события в kernel log:


dmesg | grep -i conntrack


Типичная ошибка: nf_conntrack: table full, dropping packet. Это уже прямой сигнал: таблица заполнена, новые пакеты начинают отбрасываться.

▪️ Посмотреть записи conntrack можно так:


conntrack -L


Но на нагруженных серверах с этим осторожно: вывод может быть огромным. Для общей статистики лучше:


conntrack -S


Где conntrack часто становится узким местом:

• NAT-шлюзы
• Kubernetes-ноды
• Docker-хосты
• DNS-рекурсоры
• reverse proxy под большой нагрузкой
• серверы с большим количеством коротких соединений

▪️ Самый очевидный способ лечения - это увеличить лимит:


sysctl -w net.netfilter.nf_conntrack_max=262144


Для постоянной настройки:


echo "net.netfilter.nf_conntrack_max=262144" > /etc/sysctl.d/99-conntrack.conf
sysctl --system


Но просто поднять лимит не всегда решение. Нужно понимать, почему таблица растет: слишком много коротких соединений, DDoS или сканирование, долгие таймауты или что-то другое. Иногда помогает настройка timeout’ов. Например, для TCP established:


sysctl net.netfilter.nf_conntrack_tcp_timeout_established


Для UDP:


sysctl net.netfilter.nf_conntrack_udp_timeout
sysctl net.netfilter.nf_conntrack_udp_timeout_stream


Но менять таймауты нужно аккуратно. Слишком короткие значения могут ломать нормальные долгоживущие соединения.

#linux #network #conntrack

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
💿 Storage Spaces: когда можно использовать вместо аппаратного RAID

В windows server есть встроенный механизм объединения дисков - Storage Spaces. По сути, это программное хранилище, которое позволяет собрать несколько физических дисков в пул, а поверх него создать виртуальный диск с нужным типом отказоустойчивости. То есть вместо классического аппаратного RAID-контроллера можно использовать возможности самой windows.

Базовая схема: Physical disks -> Storage Pool -> Virtual Disk -> Volume
В пул добавляются физические диски, а дальше из этого пула создается виртуальный диск.

▪️ Основные варианты отказоустойчивости:

• Simple. Без отказоустойчивости. Аналог striping. Быстро, но при потере диска теряются данные.
• Mirror. Зеркалирование данных. Похоже на RAID1 или RAID10.
• Parity. Данные + контроль четности. Похоже на RAID5/RAID6 по идее, но не всегда по производительности.

▪️ Где Storage Spaces может быть полезен:

• файловый сервер;
• backup-хранилище;
• сервер с большим количеством локальных дисков;
• недорогая замена аппаратному RAID для не самых критичных задач;
• сценарии, где нужна гибкость, а не максимальная производительность.

▪️ Например, можно собрать несколько HDD в пул и создать mirror-том для файлового хранилища. Посмотреть диски, доступные для пула:


Get-PhysicalDisk


Создать storage pool:


New-StoragePool `
-FriendlyName "DataPool" `
-StorageSubsystemFriendlyName "Windows Storage*" `
-PhysicalDisks (Get-PhysicalDisk -CanPool $true)


Создать mirror virtual disk:


New-VirtualDisk `
-StoragePoolFriendlyName "DataPool" `
-FriendlyName "DataMirror" `
-ResiliencySettingName Mirror `
-UseMaximumSize


После этого диск можно инициализировать, создать раздел и отформатировать:


Get-VirtualDisk -FriendlyName "DataMirror" | Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -UseMaximumSize -DriveLetter D |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data"


▪️ Почему Storage Spaces иногда удобнее аппаратного RAID:

• не нужен отдельный RAID-контроллер;
• проще переносить диски между совместимыми windows-системами;
• управление через PowerShell;
• можно гибко добавлять диски в пул;
• нет зависимости от конкретной модели RAID-контроллера;
• хорошо подходит для типовых windows-хранилищ.

Но есть нюансы. Storage Spaces - это не "бесплатный аппаратный RAID лучше во всем". У parity-сценариев может быть слабая производительность на записи, особенно на обычных HDD. Для баз данных, виртуализации и высоконагруженных задач нужно тщательно тестировать.

Проверять состояние можно так:


Get-StoragePool
Get-VirtualDisk
Get-PhysicalDisk


Если диск начал сыпаться, это нужно увидеть не тогда, когда уже умер второй.

#windowsserver #storagespaces

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🫡2❤1👌1
👌 tcpdump: как быстро проверить, доходят ли пакеты до сервера

Когда сервис не открывается, то первое желание часто такое: сразу лезть в конфиги приложения, firewall, nginx, systemd и логи. Но иногда полезнее начать с более простого вопроса: а пакеты вообще доходят до сервера? Для этого есть старый добрый tcpdump. Он позволяет посмотреть сетевой трафик прямо на интерфейсе и быстро понять, видит ли сервер входящие пакеты. Например, пользователь говорит: "Не открывается сайт на 443 порту".

▪️ На сервере запускаем:


tcpdump -i any port 443


И просим пользователя повторить подключение. Если в выводе появились пакеты - до сервера что-то доходит. Если тишина - проблема может быть раньше:

• firewall перед сервером;
• security group;
• маршрутизация;
• NAT;
• балансировщик;
• неправильный IP;
• провайдерская фильтрация;
• подключение вообще идет не туда.

▪️ Чуть более точный вариант - смотреть только входящий TCP SYN:


tcpdump -i any 'tcp port 443 and tcp[tcpflags] & tcp-syn != 0'


SYN - это начало TCP-подключения. Если SYN приходит, значит клиент хотя бы пытается установить соединение с сервером. Можно сразу фильтровать по IP клиента:


tcpdump -i any host 203.0.113.10 and port 443


Так удобнее, если на сервере много трафика и общий вывод превращается в кашу.

Если нужно проверить SSH:


tcpdump -i any port 22


Если HTTP:


tcpdump -i any port 80


Если DNS:


tcpdump -i any port 53


Для UDP-сервисов тоже работает:


tcpdump -i any udp port 1194


▪️ Полезные ключи:

-n -Не резолвить имена. Вывод будет быстрее и чище.
-nn - Не резолвить ни имена, ни порты. Вместо https будет 443.
-v - Более подробный вывод.
-c 20 - Поймать 20 пакетов и завершиться.

▪️ Пример аккуратной команды для быстрой проверки:


tcpdump -i any -nn -c 20 host 203.0.113.10 and port 443


▪️ Еще один полезный сценарий - понять, отвечает ли сервер. Например, видим входящий SYN от клиента:


203.0.113.10.53044 > 10.0.0.5.443: Flags [S]


А следом должен быть ответ сервера:


10.0.0.5.443 > 203.0.113.10.53044: Flags [S.]


Если входящий SYN есть, но ответа нет - нужно смотреть локальный firewall, сервис, listen-порт или routing обратно. Проверяем, слушает ли порт:


ss -lntp | grep ':443'


Проверяем firewall:


iptables -S
nft list ruleset


Если SYN приходит и SYN-ACK уходит, но клиент все равно не подключается - возможно, проблема на обратном пути.

▪️ Иногда полезно явно указать интерфейс вместо any:


ip a
tcpdump -i eth0 -nn port 443


any удобен для быстрой диагностики, но конкретный интерфейс помогает понять, через какую сетевую карту реально идет трафик.

▪️ Можно сохранить дамп в файл и потом открыть его в Wireshark:


tcpdump -i any -nn host 203.0.113.10 -w capture.pcap


Это удобно, если проблему нужно передать сетевикам или разобрать позже.

#linux #tcpdump #network

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥1
🔐 Windows LAPS: как перестать хранить один локальный admin-пароль на всех машинах

Одна из классических проблем в windows-инфраструктуре: на всех рабочих станциях один и тот же пароль локального администратора. Выглядит удобно. Админу легко подключиться к любой машине. Пароль можно держать для экстренных случаев. Техподдержка знает, что делать, если доменная авторизация не работает. Но с точки зрения безопасности это очень плохая идея. Если пароль локального администратора утек с одной машины, атакующий фактически получает доступ ко всем хостам, где этот пароль такой же. Именно для решения этой проблемы существует Windows LAPS.

Идея простая: у каждой машины должен быть свой уникальный пароль локального администратора, который регулярно меняется автоматически. Не один общий пароль на весь офис. Не excel-файл с паролями. А отдельный пароль для каждого компьютера.

▪️ Как это работает:

• на компьютере есть локальная admin-учетка;
• LAPS генерирует для нее уникальный пароль;
• пароль сохраняется в Active Directory или Entra ID;
• доступ к паролю получают только разрешенные админы;
• пароль автоматически меняется по политике;
• после использования пароль можно сбросить повторно.

Раньше часто использовали microsoft LAPS как отдельный компонент. Сейчас есть windows LAPS, встроенный в современные версии windows. Он поддерживает хранение паролей в active directory и microsoft entra ID.

▪️ Базовый сценарий для доменной инфраструктуры:

• Включаем поддержку Windows LAPS.
• Настраиваем права в Active Directory.
• Создаем Group Policy.
• Указываем, какую локальную учетку админа обслуживать.
• Задаем параметры пароля и срок жизни.
• Проверяем, что пароль появился у объекта компьютера.

▪️ Пример PowerShell-команд для проверки:


Get-LapsADPassword -Identity "PC-001" -AsPlainText


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

Посмотреть параметры LAPS на клиенте:


Get-LapsDiagnostics


Принудительно обновить пароль:


Reset-LapsPassword


▪️ Что важно настроить в политике:

• имя локальной admin-учетки;
• длину пароля;
• сложность пароля;
• срок действия пароля;
• место хранения пароля;
• права на чтение пароля;
• действия после использования пароля.

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

Главная польза LAPS: компрометация одной машины не дает автоматический доступ ко всем остальным. Даже если пароль локального администратора слили с одного ПК, на другом компьютере он будет другим. Это резко снижает риск распространения атаки внутри сети.

#windows #security

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
Надо наказывать, получается

#юмор

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10
❤️ systemctl edit: как правильно переопределять юниты без правки vendor-файлов

В systemd часто нужно чуть-чуть изменить стандартный unit, который приехал из пакета. Например:

• добавить автоматический рестарт;
• изменить переменные окружения;
• переопределить ExecStart;
• добавить лимиты;
• поменять рабочий каталог;
• настроить зависимости.

Плохая идея - править vendor-unit напрямую где-нибудь в:


/lib/systemd/system/


или:


/usr/lib/systemd/system/


После обновления пакета такие изменения могут потеряться или конфликтовать с новой версией юнита.Правильнее использовать override. Покажу на примере nginx.service.

1️⃣ Сначала смотрим полный unit:


systemctl cat nginx.service


Это очень удобная команда. Она показывает не только содержимое unit-файла, но и путь, откуда он загружен. Если для сервиса уже есть override-файлы, они тоже будут показаны в этом же выводе.

2️⃣ Теперь добавим автоперезапуск nginx при падении:


systemctl edit nginx.service


3️⃣ Откроется редактор. Добавляем:


[Service]
Restart=always
RestartSec=5s


4️⃣ Сохраняем и выходим. systemd сам создаст drop-in файл примерно здесь:


/etc/systemd/system/nginx.service.d/override.conf


5️⃣ Проверяем результат:


systemctl cat nginx.service


Теперь в выводе будет видно и исходный unit, и наш override.

6️⃣ После изменения обычно стоит выполнить:


systemctl daemon-reload
systemctl restart nginx.service


И проверить:


systemctl status nginx.service


Важный нюанс: не все параметры переопределяются одинаково. Если вы добавляете новый параметр, обычно достаточно просто указать его. Например:


[Service]
Restart=always
RestartSec=5s


Но если нужно переопределить параметры, которые могут иметь несколько значений, их часто нужно сначала очистить.

▪️ Классический пример - ExecStart. Если в основном unit было:


ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'


А вы хотите заменить команду запуска, нужно сделать так:


[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon off; master_process off;'


Первая строка очищает старое значение. Вторая задает новое. Если просто добавить новый ExecStart, systemd может выдать ошибку или оставить некорректную конфигурацию. То же часто касается параметров семейства:


ExecStart=
ExecStartPre=
ExecStartPost=
ExecReload=
ExecStop=


▪️ Аналогичная логика может понадобиться и для некоторых списочных настроек. Если override "почему-то не работает", полезно проверить итоговую конфигурацию:


systemctl cat nginx.service


И затем:


systemd-analyze verify /etc/systemd/system/nginx.service.d/override.conf


Еще полезная команда:


systemctl revert nginx.service


Она удалит локальные override и вернет unit к vendor-состоянию.

#linux #systemd

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🆘 BgInfo: системная информация прямо на рабочем столе Windows

У Microsoft Sysinternals есть старая, но до сих пор полезная утилита - BgInfo. Она выводит системную информацию прямо поверх обоев рабочего стола. На фоне можно показать:

• имя компьютера
• домен
• пользователя
• IP-адреса
• версию Windows
• uptime
• свободное место на дисках
• AD site
• любые дополнительные поля

Для HelpDesk это удобно: пользователь просто смотрит на рабочий стол и диктует нужные данные. Для админа тоже полезно, особенно когда открыто много RDP-сессий на разные серверы. Сразу видно, где именно ты находишься, и меньше шансов перепутать тестовый сервер с боевым.
BgInfo достаточно гибкий. Кроме стандартных полей, можно добавлять данные через:

• WMI
• registry
• environment variables
• VBS
• PowerShell-скрипты

▪️ Базовая схема внедрения простая.

1️⃣ Создаем шаблон BgInfo. В GUI настраиваем: какие поля показывать, шрифт и цвет, расположение блока, формат вывода, фон и поведение. После этого сохраняем конфигурацию в файл, например: bg_config.bgi

2️⃣ Кладем файлы в SYSVOL / NETLOGON. Например:


\\domain.local\NETLOGON\Bginfo\


Внутри:


Bginfo.exe
bg_config.bgi


3️⃣ Применяем через logon script в GPO. Пример bat-файла:


reg add HKEY_CURRENT_USER\Software\Sysinternals\BGInfo /v EulaAccepted /t REG_DWORD /d 1 /f

%logonserver%\NETLOGON\Bginfo\Bginfo.exe %logonserver%\NETLOGON\Bginfo\bg_config.bgi /silent /timer:00 /nolicprompt


▪️ Что здесь происходит:

• заранее принимаем EULA для пользователя
• запускаем BgInfo из NETLOGON
• применяем готовый .bgi шаблон
• скрываем окно запуска
• не показываем license prompt
• сразу обновляем фон без ожидания таймера

После входа пользователя на рабочий стол автоматически наносится нужная системная информация.

Отдельный плюс - возможность стандартизировать внешний вид. Например, на серверах можно крупно выводить:

SERVER: SRV-APP-01
ENV: PROD
IP: 10.10.20.15


А на рабочих станциях - имя ПК, пользователь, IP и версию ОС.

#windows #bginfo

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
📱 getopts в bash: как нормально разбирать аргументы скрипта

Многие Bash-скрипты сначала выглядят просто: ./backup.sh /data /backup
А потом появляются опции: путь к конфигу, имя окружения, количество попыток, режим работы и т.д. И скрипт быстро превращается в набор странных if, где $1, $2, $3 уже никто нормально не понимает.

🤩 Плохой вариант:


SOURCE="$1"
DEST="$2"
MODE="$3"


Работает, пока аргументов мало. Но как только нужно добавить флаги, порядок начинает ломать все. Для нормального разбора коротких опций в bash есть встроенный механизм getopts.

▪️ Пример скрипта:


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

VERBOSE=0
DRY_RUN=0
CONFIG=""

usage() {
echo "Usage: $0 [-v] [-n] [-c config] source dest"
}

while getopts ":vnc:" opt; do
case "$opt" in
v)
VERBOSE=1
;;
n)
DRY_RUN=1
;;
c)
CONFIG="$OPTARG"
;;
🙂
echo "option -$OPTARG requires an argument" >&2
usage
exit 1
;;
\?)
echo "unknown option: -$OPTARG" >&2
usage
exit 1
;;
esac
done

shift $((OPTIND - 1))

SOURCE="${1:-}"
DEST="${2:-}"

if [[ -z "$SOURCE" || -z "$DEST" ]]; then
usage
exit 1
fi

echo "source: $SOURCE"
echo "dest: $DEST"
echo "config: $CONFIG"
echo "verbose: $VERBOSE"
echo "dry-run: $DRY_RUN"


Теперь скрипт можно запускать так:


./backup.sh -v -n -c /etc/backup.conf /data /backup


или так:


./backup.sh -c /etc/backup.conf -v /data /backup


Порядок флагов уже не так важен.

▪️ Что означает строка: while getopts ":vnc:" opt; do

v - флаг без значения
n - флаг без значения
c: - опция -c требует аргумент
первый : включает более удобную обработку ошибок

То есть -v и -n просто включают режимы, а -c ожидает значение:


-c /etc/backup.conf


Переменная OPTARG содержит аргумент текущей опции. Например, для:


-c /etc/backup.conf


внутри case будет:


CONFIG="$OPTARG"


После обработки флагов важна команда:


shift $((OPTIND - 1))


Она убирает уже разобранные опции из списка аргументов. После этого в $1, $2 остаются обычные позиционные аргументы: например source и dest.

#bash #scripting

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
📎 TCP retransmits: как понять, что сеть теряет пакеты, а не тормозит приложение

Иногда приложение вроде бы работает, CPU нормальный, память есть, база живая, но пользователи жалуются: "все медленно". И начинается классика: смотрим логи приложения, nginx, базу, systemd, load average. А причина может быть ниже - на сетевом уровне. Один из важных признаков сетевых проблем - TCP retransmits.

TCP - надежный протокол. Если пакет потерялся по дороге, получатель его не подтвердил, и отправитель через время отправит этот сегмент заново. Это и есть retransmission. Небольшое количество повторных передач в сети бывает всегда. Но если их много - это уже симптом:

• перегруженный канал;
• проблемы на интерфейсе;
• плохой Wi-Fi или VPN;
• перегруженный firewall/NAT;
• проблемы у провайдера.

Снаружи это часто выглядит не как "сеть упала", а как странная деградация: страницы открываются медленно, API иногда отвечает долго, SSH подвисает, загрузка файлов идет рывками и т.д.

Первое, что можно посмотреть на linux:


netstat -s | grep -i retrans


или через ss:


ss -ti


В выводе ss -ti можно увидеть детали по TCP-соединениям, включая retrans, rtt, cwnd и другие параметры.

Для конкретного направления лучше использовать tcpdump. Например, смотрим трафик между сервером и клиентом:


tcpdump -i any -nn host 203.0.113.10 and port 443


Если нужно сохранить дамп для Wireshark:


tcpdump -i any -nn host 203.0.113.10 and port 443 -w retrans.pcap


В wireshark потом удобно фильтровать:


tcp.analysis.retransmission


Также полезные фильтры:


tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.analysis.duplicate_ack


Если видите много retransmission, duplicate ACK и lost segment - это уже повод смотреть сеть, а не только приложение.

Быстрая проверка маршрута:


mtr -rw -c 100 203.0.113.10


Но тут важно помнить: mtr показывает потери по ICMP/UDP/TCP-проверкам, а не всегда идеально отражает конкретный TCP-трафик приложения. Зато помогает понять, где примерно начинаются проблемы.

Еще полезно проверить ошибки на сетевом интерфейсе:


ip -s link


или:


ethtool -S eth0


#linux #network

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
📂 sshfs: монтируем удаленный каталог через SSH и systemd

sshfs позволяет монтировать удаленную файловую систему через обычное SSH-соединение. То есть если у вас есть SSH-доступ к серверу, можно подключить его каталог как локальную директорию. Это не самый быстрый способ: SSHFS работает через FUSE в user space, плюс само SSH-соединение добавляет накладные расходы. Но для некоторых задач это очень удобно. Особенно когда: SSH уже открыт; NFS/SMB поднимать не хочется; нужен быстрый доступ к отдельному каталогу или нужно временно подключить данные

▪️ Установка:


apt install sshfs


▪️ Для автомонтирования лучше сразу настроить доступ по ключу. Генерируем ключ:


ssh-keygen -t ed25519


Копируем его на удаленный сервер:


ssh-copy-id root@10.20.1.6


Можно подключаться и по паролю, но для systemd-автомонтирования это неудобно: пароль придется вводить интерактивно. С ключом все проще и надежнее.

▪️ Пример. Допустим, нужно смонтировать каталог:


root@10.20.1.6:/etc/letsencrypt


в локальный путь:


/mnt/letsencrypt


Создаем точку монтирования:


mkdir -p /mnt/letsencrypt


Монтируем вручную:


sshfs root@10.20.1.6:/etc/letsencrypt /mnt/letsencrypt


Проверяем:


df -h | grep 10.20.1.6


Размонтировать можно так:


fusermount -u /mnt/letsencrypt


▪️ Теперь сделаем systemd-unit, чтобы монтировать каталог автоматически. Создаем service:


systemctl edit --force --full sshfs-letsencrypt.service


Пример unit-файла:


[Unit]
Description=Mount /etc/letsencrypt over SSHFS
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true

ExecStart=/usr/bin/sshfs root@10.20.1.6:/etc/letsencrypt /mnt/letsencrypt -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
ExecStop=/usr/bin/fusermount -u /mnt/letsencrypt

[Install]
WantedBy=multi-user.target


Перечитываем systemd:


systemctl daemon-reload


Запускаем:


systemctl start sshfs-letsencrypt.service


Добавляем в автозагрузку:


systemctl enable sshfs-letsencrypt.service


Если нужно размонтировать каталог:


systemctl stop sshfs-letsencrypt.service


▪️ Полезные опции:

• reconnect - Пытаться восстановить подключение при обрыве.
• ServerAliveInterval=15 - Периодически проверять, живо ли SSH-соединение.
• ServerAliveCountMax=3 - После нескольких неудачных проверок считать соединение мертвым.

В примере все сделано от root для простоты. Для постоянной схемы лучше использовать отдельного пользователя с минимальными правами. В systemd можно указать:


User=sftp-user
Group=sftp-user


Но тогда важно, чтобы у этого пользователя были права на точку монтирования и SSH-ключи.

#linux #sshfs

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
✏️ Пишем события скриптов в Windows Event Viewer

В Windows-скриптах часто делают логирование в обычные текстовые файлы:


C:\Scripts\Logs\script.log


Это рабочий вариант, но не всегда удобный. Логи могут лежать в разных папках, забываться при переносе скрипта, не попадать в централизованный сбор и быстро превращаться в зоопарк форматов. Иногда удобнее писать важные события прямо в Event Viewer.

▪️ Плюсы такого подхода:

• события видны в стандартном журнале Windows;
• их можно собирать через WEF, SIEM или агент мониторинга;
• проще фильтровать по источнику, Event ID и уровню;
• не нужно отдельно искать лог-файл скрипта;
• события попадают в привычный механизм аудита и диагностики.

▪️ Например, в PowerShell можно создать отдельный источник событий:


New-EventLog -LogName Application -Source "MyScript"
После этого можно писать события в журнал Application:
Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Information `
-EventID 1 `
-Message "Запущен PowerShell-скрипт опроса состояния сервера"


В Event Viewer появится событие с источником MyScript.

Тип события можно менять:

-EntryType Information
-EntryType Warning
-EntryType Error

Например, если скрипт завершился с ошибкой:


Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Error `
-EventID 1001 `
-Message "Скрипт завершился с ошибкой при подключении к серверу"


▪️ Можно использовать свою схему Event ID:

1 - старт скрипта
2 - успешное завершение
100 - предупреждение
1001 - ошибка подключения
1002 - ошибка доступа


Так потом проще строить фильтры и алерты.

▪️ Если не хочется смешивать события с общим Application, можно создать отдельный журнал:


New-EventLog -LogName CustomPSLog -Source "PS1Script"


И писать уже туда:


Write-EventLog `
-LogName CustomPSLog `
-Source "PS1Script" `
-EntryType Information `
-EventID 1 `
-Message "PowerShell script started"


▪️ Для BAT/CMD-скриптов тоже есть вариант - команда eventcreate:


eventcreate /t information /l application /id 1 /d "BAT script started"


Для ошибки:


eventcreate /t error /l application /id 1001 /d "BAT script failed"


Event Viewer удобен не вместо всех логов, а как место для важных событий, которые должны быть видны системе мониторинга и администратору. Если скрипт делает что-то важное, он должен не просто молча выполниться. Он должен оставить понятный след: когда стартовал, чем закончился и где сломался.

#windows #powershell #eventviewer

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
👀 inotifywait: реакция на изменения файлов без cron

Иногда нужно выполнить действие сразу после изменения файла или каталога. Например:

• изменился конфиг - перезапустить сервис
• появился новый файл - обработать его
• загрузили архив - распаковать
• изменился сертификат - перечитать nginx
• в каталог упал лог - отправить уведомление

Первое решение, которое часто приходит в голову - cron. Но cron работает по расписанию. Он не реагирует на событие сразу, а просто периодически проверяет состояние. Для событий в файловой системе удобнее использовать inotifywait.

▪️ Установка:


apt install inotify-tools


▪️ Посмотреть изменения файла:


inotifywait -m /etc/nginx/nginx.conf


Ключ -m включает постоянное наблюдение.

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


/etc/nginx/nginx.conf MODIFY


▪️ Следить за каталогом:


inotifywait -m /var/www


Рекурсивно:


inotifywait -m -r /var/www


Можно выбрать конкретные события:


inotifywait -m -e create,modify,delete /var/www


▪️ Простой пример: перезагрузить nginx после изменения конфига.


while inotifywait -e modify /etc/nginx/nginx.conf; do
nginx -t && systemctl reload nginx
done


Смысл простой:

• ждем изменение файла
• проверяем конфиг
• если всё нормально - reload nginx
• снова ждем следующее изменение

▪️ Еще пример: обработать новые файлы в каталоге.


inotifywait -m -e close_write --format '%w%f' /data/incoming |
while read -r file; do
echo "new file: $file"
/opt/scripts/process-file.sh "$file"
done


Почему close_write, а не просто create? Потому что файл может появиться, но запись в него еще не закончилась. close_write срабатывает, когда файл уже записан и закрыт.

⚠️ inotifywait - не замена очередям, брокерам сообщений и нормальной event-driven архитектуре. У него есть лимиты ядра, события можно потерять при перегрузке, а рекурсивное наблюдение за огромными деревьями может быть тяжелым. Проверить лимиты можно так:


sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_user_instances


#linux #inotify

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤩 Почему места достаточно, но приложение всё равно не может записать файл

Иногда на сервере возникает странная ситуация. Проверяем диск:


df -h


Свободное место есть. Например, десятки гигабайт. Но приложение всё равно пишет: No space left on device

▪️ Первая частая причина - закончились inodes. inode - это запись о файле в файловой системе. Если маленьких файлов очень много, можно упереться не в объем, а в количество файлов. Проверить:


df -i


Если IUse% близко к 100%, новые файлы создаваться не будут, даже если свободные гигабайты еще есть. Типичные виновники: миллионы мелких cache-файлов, сессии приложения, временные файлы, мелкие логи и т.д. Найти каталоги с большим количеством файлов:


find /var -xdev -type f | cut -d/ -f1-3 | sort | uniq -c | sort -nr | head


▪️ Вторая причина - квоты. Для пользователя или группы может быть ограничение, хотя на файловой системе место есть. Проверить:


quota -s


или для XFS:


xfs_quota -x -c 'report -h' /mountpoint


▪️ Третья причина - приложение пишет не туда, куда вы смотрите. Например, вы проверяете /data, а сервис пишет в /var/lib/app, /tmp или внутрь контейнера. Полезно посмотреть mount point:


df -h /path/to/file


И понять, какая файловая система реально используется.

▪️ Четвертая причина - лимиты systemd. У сервиса могут быть ограничения через unit:


systemctl cat myapp.service
systemctl show myapp.service | grep -i limit


▪️ Пятая причина - read-only файловая система. Например, после ошибок диска система могла перемонтировать раздел в ro. Проверить:


findmnt -o TARGET,OPTIONS


или:


mount | grep ' ro,'


#linux #filesystem #storage

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
😩 systemd-analyze: почему сервер долго загружается и кто виноват

Иногда сервер после reboot поднимается подозрительно долго. Вроде железо нормальное, диск живой, сервисов не так много, но до нормального состояния система доходит через минуту, две или даже дольше.

В systemd для такого разбора есть удобная утилита:


systemd-analyze


Она покажет общее время загрузки:


Startup finished in 5.2s (kernel) + 28.4s (userspace) = 33.6s


Здесь видно, сколько заняло ядро и сколько - userspace, то есть запуск systemd-сервисов.

▪️ Чтобы понять, какие иниты запускались дольше всего:


systemd-analyze blame


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


12.834s docker.service
8.421s NetworkManager-wait-online.service
6.102s postgresql.service
3.451s nginx.service


Это хороший первый ориентир, но есть важный нюанс.

blame показывает длительность запуска юнитов, но не всегда показывает реального виновника. Сервисы могут запускаться параллельно, и длинный сервис не обязательно блокировал всю загрузку.

▪️ Для понимания цепочки зависимостей лучше использовать:


systemd-analyze critical-chain


Эта команда показывает критический путь загрузки - что действительно задерживало достижение нужного target.

▪️ Можно посмотреть цепочку для конкретного сервиса:


systemd-analyze critical-chain docker.service


▪️ Частые причины долгой загрузки:

ожидание сети
зависший mount из /etc/fstab
медленный DNS
NFS/SMB mount без `nofail`
долгий старт базы данных
Docker/container runtime
cloud-init
некорректные зависимости в юнитах
таймауты несуществующих устройств


▪️ Отдельно стоит проверить failed-юниты:


systemctl --failed


▪️ Логи текущей загрузки:


journalctl -b


Если проблема была на предыдущем boot:


journalctl -b -1


▪️ Еще полезная команда - построить SVG-график загрузки:


systemd-analyze plot > boot.svg


Файл boot.svg можно открыть в браузере и визуально посмотреть, какие сервисы когда стартовали и сколько длились.

▪️ Для поиска ошибок в unit-файлах:


systemd-analyze verify /etc/systemd/system/myapp.service


Это помогает поймать неправильные директивы, опечатки и странности в конфигурации.

#linux #systemd

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2
💚 Как один неверный chmod -R ломает прод сильнее, чем падение сервиса

Падение сервиса обычно видно сразу. Мониторинг красный, пользователи жалуются, в логах ошибка. Перезапустили, откатили, восстановили. А вот один неверный chmod -R может сломать прод намного тише и неприятнее. Классический сценарий:


chmod -R 777 /var/www


или еще хуже:


chmod -R 755 /


Хотели быстро пофиксить права, а получили хаос.

▪️ Почему это опасно?

Права в linux - это не просто можно читать или нельзя.
От них зависит работа сервисов, безопасность, SSH, sudo, systemd, базы данных, веб-приложения и приватные ключи.

▪️ Что может сломаться:

• SSH перестанет принимать ключи, потому что ~/.ssh и authorized_keys стали слишком открытыми
• приватные ключи начнут считаться небезопасными
• nginx/apache потеряют доступ к нужным файлам или, наоборот, получат лишний доступ
• база данных откажется стартовать из-за неправильных прав на data directory
• sudo может начать ругаться на права конфигов
• приложения начнут писать туда, куда не должны
• исполняемые файлы потеряют нужные биты


▪️ Особенно опасны рекурсивные команды с переменными:


chmod -R 755 "$DIR"


Если $DIR пустой, неправильный или подставился не тот путь - последствия могут быть очень неприятными.

Перед такими командами лучше явно проверять переменные:


: "${DIR:?DIR is empty}"


И сначала смотреть, куда команда попадет:


find "$DIR" -maxdepth 2 -print


Для файлов и директорий права часто должны отличаться.

🤩 Плохо:


chmod -R 755 /var/www/app


🤩 Лучше:


find /var/www/app -type d -exec chmod 755 {} +
find /var/www/app -type f -exec chmod 644 {} +


Так директории остаются проходимыми, а обычные файлы не становятся исполняемыми без необходимости.

▪️ Если нужно дать права конкретному пользователю, часто правильнее менять владельца:


chown -R www-data:www-data /var/www/app/storage


А не открывать все через 777.
777 - это почти всегда сигнал, что проблему не поняли, а просто выключили защиту.

Для диагностики полезно смотреть текущие права:


ls -la
namei -l /var/www/app/storage/file.log
stat /var/www/app/storage


namei -l особенно удобен: он показывает права на каждом уровне пути.
Иногда файл доступен, но один из родительских каталогов не дает пройти дальше.

#linux #chmod

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4
⏰ Точное время до запуска сервисов: одноразовая синхронизация через chrony

Обычно синхронизация времени в Linux работает незаметно: установили chrony, systemd-timesyncd или другой NTP-клиент - и забыли. Но после загрузки виртуальной машины системное время иногда отличается на несколько минут. Служба синхронизации исправит его, однако часть сервисов к этому моменту уже может успеть запуститься.

В результате появляются:

• события в логах с неправильным временем
• ошибки проверки сертификатов
• проблемы с Kerberos и токенами
• некорректный порядок событий
• странности в распределенных системах и мониторинге

Для обычной работы постепенная коррекция времени подходит. Но на старте иногда нужно сначала выставить часы, а уже потом запускать приложение. Для этого можно создать одноразовый systemd-unit с chronyd -q.

▪️ Устанавливаем chrony:


apt install chrony


▪️ Создаем unit:


systemctl edit --force --full chrony-once-sync.service


▪️ Добавляем:


[Unit]
Description=Initial time synchronization with chrony
Wants=network-online.target
After=network-online.target
Before=myapp.service

[Service]
Type=oneshot
ExecStart=/usr/sbin/chronyd -q -t 10

[Install]
WantedBy=multi-user.target


-q - один раз выставить время и завершить работу
-t 10 - прекратить попытку через 10 секунд
After=network-online.target - запускать после готовности сети
Before=myapp.service - выполнить синхронизацию раньше критичного приложения

▪️ Активируем юнит:


systemctl daemon-reload
systemctl enable chrony-once-sync.service


▪️ Проверяем после перезагрузки:


systemctl status chrony-once-sync.service
journalctl -u chrony-once-sync.service -b


▪️ Посмотреть порядок запуска:


systemd-analyze critical-chain myapp.service


#linux #systemd #chrony

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Вы не заставите меня их закрыть. 🤩

#юмор

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10🫡2❤1
📁 Логирование скриптов в Windows Event Viewer

Для логов PowerShell и BAT-скриптов необязательно создавать отдельные текстовые файлы. Важные события можно записывать прямо в Event Viewer. Это удобно, потому что такие записи проще искать, фильтровать и собирать централизованно через WEF, SIEM или систему мониторинга.

▪️ Сначала создадим отдельный источник событий:


New-EventLog -LogName Application -Source "MyScript"


Эту команду обычно достаточно выполнить один раз с правами администратора.

▪️ Теперь можно записать событие в журнал Application:


Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Information `
-EventID 1 `
-Message "Запущен PowerShell-скрипт проверки состояния сервера"


▪️ Для ошибок и предупреждений меняем тип события:


Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Error `
-EventID 1001 `
-Message "Не удалось подключиться к серверу"


Полезно заранее определить свою схему Event ID:

1 -запуск скрипта
2 - успешное завершение
100 - предупреждение
1001 - ошибка выполнения


▪️ Если не хочется смешивать записи с общим журналом Application, можно создать отдельный EVTX-журнал:


New-EventLog -LogName CustomPSLog -Source "PS1Script"


А затем писать события уже в него:


Write-EventLog `
-LogName CustomPSLog `
-Source "PS1Script" `
-EntryType Information `
-EventID 1 `
-Message "Скрипт запущен"


▪️ В BAT- и CMD-скриптах для этого есть команда eventcreate:


eventcreate /t information /l application /id 1 /d "BAT script started"


Для записи ошибки:


eventcreate /t error /l application /id 1001 /d "BAT script failed"


Подробный debug-вывод удобнее оставлять в обычном текстовом логе. Хорошая схема выглядит так: детали — в файл, важные события — в Event Viewer.

#windows #eventviewer

🧑‍💻 NetworkAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1