Skip to content

Latest commit

 

History

100 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mytasks — набор служебных скриптов

Коллекция bash/Python-скриптов для автоматизации повседневных задач.

Лицензия

Скрипты предоставляются "AS IS" («как есть»), без каких-либо гарантий. Подробнее см. файл LICENSE.


Конфигурационные файлы

Конфигурационные файлы скриптов находятся в папке conf/ в корне репозитория.

Скрипты, использующие конфигурацию, создают каталог conf/ при первом запуске, если его ещё нет. Рабочие *.conf содержат машинно-зависимые пути и параметры, поэтому не коммитятся; в репозитории хранятся безопасные *.conf.example.

Актуальные шаблоны:

  • auto_delete_old_files.conf.example;
  • btrfs_monitor.conf.example;
  • cloud_backup.conf.example;
  • cloud_backup_qnap.conf.example;
  • getip.conf.example;
  • log_template.conf.example;
  • sources.conf.example;
  • split_by_dash.conf.example;
  • system_monitor.conf.example.

Скопируйте нужный шаблон без суффикса .example и заполните локальными значениями. all_to_mp3.sh при необходимости читает conf/audio_to_mp3.conf; его параметры перечислены в разделе скрипта ниже.


Актуальный формат shell-скриптов

Shell-скрипты в корне репозитория используют общие соглашения:

  • Единая структура секций: SCRIPT ID / PATHS, HELPERS, ARGS, MAIN
  • Явные проверки параметров и зависимостей
  • Безопасные режимы запуска shell (set -eu или set -uo pipefail в зависимости от логики скрипта)
  • для скриптов с JSONL-логированием — каталог logs/ и одна JSON-запись на строку;
  • ротация логов по параметру конкретного скрипта либо по встроенному лимиту.

Единый шаблон логов

Единый шаблон хранится в conf/log_template.conf.

Для коммита в репозиторий используйте пример conf/log_template.conf.example.

Shell-скрипты с JSONL-логированием читают этот файл, если он доступен, и пишут унифицированные поля, подходящие для ELK/OpenSearch, Loki, Graylog и Splunk:

  • @timestamp
  • schema.version
  • compat.targets
  • log.level
  • message
  • event.action
  • service.name

Также сохраняются служебные поля совместимости (script, event, msg, detail, rc и т.д.), чтобы не ломать существующие разборщики.

Это упрощает сопровождение, делает поведение скриптов предсказуемым и улучшает диагностику ошибок.


Скрипты

all_to_mp3.sh

Пакетная конвертация аудиофайлов в MP3 с помощью ffmpeg.

Возможности:

  • Поддерживает любые форматы, распознаваемые ffprobe
  • Обработка файлов в несколько потоков (xargs -P)
  • Встраивает обложку — внешнюю (cover.jpg, folder.jpg, front.jpg) или встроенную в аудио
  • Сохраняет структуру каталогов в выходной папке
  • Ведёт отчёт (audio_to_mp3_report.txt) и лог ошибок (audio_to_mp3_errors.log)

Конфигурация (опциональный файл conf/audio_to_mp3.conf):

Параметр По умолчанию Описание
FORMATS (все форматы) Список расширений для обработки
QUALITY 0 Качество MP3 (0 — наилучшее)
COVER_NAMES cover.jpg folder.jpg front.jpg Имена файлов обложек
JOBS nproc Количество параллельных потоков
OUTPUT_DIR /copy/Music Папка для результата

Использование:

./all_to_mp3.sh /путь/к/музыке

cloud_backup.sh

Резервное копирование /opt/esimych-cloud с удалённого сервера через WireGuard VPN.

Порядок работы:

  1. Поднимает WireGuard-соединение (wg-quick up), если оно не активно
  2. Подключается к удалённому серверу по SSH (sshpass)
  3. Выбирает компрессор на удалённом сервере: zstd, pigz или gzip
  4. Чистит корзины всех пользователей и версии файлов Nextcloud (occ trashbin:cleanup --all-users, occ versions:cleanup)
  5. (Опционально) оптимизирует MariaDB (mariadb-check --optimize, очистка general.log, опционально purge binlogs)
  6. (Опционально) оптимизирует Redis AOF (BGREWRITEAOF)
  7. Создаёт архив удалённой папки и сохраняет его в BACKUP_DIR
  8. Если архив за текущую дату уже существует и проходит проверку целостности, дозаписывает новый поток в тот же файл
  9. Если существующий архив пустой или повреждённый, удаляет его и создаёт заново
  10. Опускает WireGuard (если был поднят скриптом) — управляется параметром WG_KEEP_UP

Зависимости: wg-quick, sshpass (для опциональной оптимизации: redis-cli в соответствующем контейнере)

Конфигурация (conf/cloud_backup.conf):

Параметр По умолчанию Описание
WG_INTERFACE (обязательно) Имя WireGuard-интерфейса (напр. wg0)
REMOTE_HOST (обязательно) IP-адрес удалённого сервера
REMOTE_USER (обязательно) Логин SSH
REMOTE_PASSWORD (обязательно) Пароль SSH
SUDO_PASSWORD (пусто) Пароль для неинтерактивного sudo wg-quick; при пустом значении wg-quick вызывается напрямую
REMOTE_SSH_PORT 22 Порт SSH
REMOTE_PATH /opt/esimych-cloud Путь к папке на удалённой системе
BACKUP_DIR (обязательно) Локальная папка для резервных копий
WG_KEEP_UP 0 Оставить WireGuard активным после завершения
BACKUP_KEEP_COUNT 5 Сколько последних резервных копий и логов хранить
BACKUP_DEGRADATION_MIBS_THRESHOLD 6 Порог средней скорости (MiB/s) для события backup_degradation
OPTIMIZE_MARIADB_BEFORE_BACKUP 0 Выполнить оптимизацию MariaDB перед архивом
MARIADB_SERVICE_NAME mariadb Имя MariaDB-сервиса в docker compose
MARIADB_PURGE_BINLOGS 0 Очистить старые binary logs (PURGE BINARY LOGS)
MARIADB_TRUNCATE_GENERAL_LOG 1 Очистить general.log перед архивом
OPTIMIZE_REDIS_BEFORE_BACKUP 0 Выполнить BGREWRITEAOF для Redis
REDIS_SERVICE_NAME redis Имя Redis-сервиса в docker compose
REDIS_REWRITE_WAIT_SEC 180 Верхний предел ожидания BGREWRITEAOF (сек) — не типичная длительность: определение завершения устойчиво к CRLF в выводе redis-cli INFO, поэтому при штатной работе rewrite завершается за секунды, значение — лишь потолок на случай реальной проблемы

Логи: JSONL-файл logs/cloud_backup-YYYY-MM-DD-HH-MM-SS.jsonl. Хранится BACKUP_KEEP_COUNT последних файлов (тот же параметр, что и для архивов).

Имя архива: cloud_backup-YYYY-MM-DD.tar.gz или cloud_backup-YYYY-MM-DD.tar.zst

Поведение при существующем архиве:

  • tar.gz и tar.zst проверяются на целостность перед дозаписью
  • валидный архив за текущую дату дополняется новым сжатым потоком
  • битый или пустой архив удаляется и пересоздаётся
  • если локально недоступна утилита проверки (gzip или zstd), скрипт не дозаписывает, а создаёт архив заново

Встроенные исключения при архивировании (всегда включены):

  • tmp/*, cache/*, .cache/* в корне REMOTE_PATH
  • data/*/uploads/*
  • data/*/files_trashbin/uploads/*
  • data/*/cache/*
  • data/appdata_*/preview/*
  • data/appdata_*/thumbnails/*
  • data/appdata_*/css/*
  • data/appdata_*/js/*

Эти excludes жёстко заданы в скрипте и не настраиваются через conf/cloud_backup.conf.

Очистка корзины Nextcloud перед архивированием:

  • occ trashbin:cleanup --all-users физически удаляет саму папку data/<user>/files_trashbin (не только её содержимое), если она становится пустой
  • из-за этого встроенный фоновый джоб Nextcloud ExpireTrash (запускается через cron.php независимо от расписания бэкапа) затем падает с NotFoundException.../files_trashbin при каждом своём запуске
  • поэтому сразу после очистки скрипт получает datadirectory и список пользователей через occ и для каждого пользователя выполняет mkdir -p <datadir>/<user>/files_trashbin — это идемпотентно и безопасно

Производительность:

  • SSH-шифр: приоритет aes128-gcm, chacha20-poly1305 — используют аппаратное ускорение AES-NI
  • SSH-сжатие отключено (Compression=no) — tar уже сжимает данные, двойное сжатие только тратит CPU
  • Компрессор выбирается на удалённом сервере: zstd --fast=1 --threads=0, затем pigz -1, при их отсутствии — gzip -1
  • set -o pipefail на удалённой стороне — ошибка tar корректно прерывает передачу
  • JSONL-лог очищается от управляющих символов в detail, чтобы записи были устойчиво парсируемы
  • Пишутся диагностические события backup_metrics (размер/длительность/скорость) и backup_degradation при скорости ниже порога
  • Порог деградации можно задать через BACKUP_DEGRADATION_MIBS_THRESHOLD (MiB/s), по умолчанию 6

Использование:

sudo ./cloud_backup.sh

Cron (каждый день в 21:30):

30 21 * * * root /path/to/mytasks/cloud_backup.sh >> /dev/null 2>&1

Или через sudo crontab -e:

30 21 * * * /home/esimych/esimych-docs/mytasks/cloud_backup.sh

cloud_backup_qnap.sh

QNAP-версия cloud_backup.sh — то же резервное копирование /opt/esimych-cloud через WireGuard VPN, но запускается на самом QNAP NAS (Entware cron / Task Scheduler), а не на десктопе.

Отличия от cloud_backup.sh:

  • Shebang #!/opt/bin/bash — Entware bash напрямую (штатный /bin/sh на QTS не поддерживает массивы/local/${!var})
  • PATH дополняется /opt/sbin:/opt/bin (Entware), т.к. QTS не содержит wg-quick, wg, zstd
  • Нет sudo-кода — Task Scheduler/cron на QNAP и так выполняют скрипт от root
  • WireGuard поднимается в обход wg/wg-quick — на части моделей QTS (проверено на ядре 4.2.8 aarch64) консольная утилита wg(8) не работает в принципе (Protocol not supported), поэтому туннель поднимается напрямую через userspace UAPI-сокет wireguard-go (см. wg_up_userspace/wg_conf_get в коде)
  • Основной способ аутентификации — SSH-ключ (REMOTE_SSH_KEY); пароль используется только если одновременно заданы REMOTE_PASSWORD и доступен sshpass
  • Автоматически переподключает bind-mount /optENTWARE_DATA_DIR, если он слетел после перезагрузки NAS (ensure_entware_mount)
  • Как и десктопная версия, чистит корзину и версии файлов Nextcloud (occ trashbin:cleanup --all-users, occ versions:cleanup) и пересоздаёт папку files_trashbin для каждого пользователя после очистки. Команды выполняются через имя сервиса Compose (NEXTCLOUD_SERVICE_NAME), поэтому не зависят от изменяемого container_name
  • При доступном zstd удалённый поток сжимается командой zstd -5 --threads=0 -c: уровень 5 выбран как компромисс между дополнительным сжатием и нагрузкой на удалённый сервер; при отсутствии zstd сохраняется автоматический переход на pigz -1 или gzip -1

Предварительная настройка на QNAP (разово, вручную) подробно описана в шапке самого скрипта: установка Entware, пакетов (opkg install bash wireguard-tools wireguard-go ncat xxd zstd coreutils-stat), создание конфига WireGuard-клиента с отдельным peer/IP, проверка userspace UAPI-сокета, копирование SSH-ключа на сервер, заполнение conf/cloud_backup_qnap.conf и (опционально, только для RAW_TRANSFER_ENABLED="1") открытие порта передачи в фаерволе удалённого сервера — см. шаг 8 в шапке скрипта.

Конфигурация (conf/cloud_backup_qnap.conf, см. .example):

Параметр По умолчанию Описание
WG_INTERFACE (обязательно) Имя WireGuard-интерфейса (напр. wg0-qnap)
WG_ENDPOINT (пусто) Необязательное переопределение публичного endpoint WireGuard в формате IPv4:port; если пусто, берётся Endpoint из /opt/etc/wireguard/<WG_INTERFACE>.conf
ENTWARE_DATA_DIR /share/Public/entware Постоянный каталог Entware, который скрипт при необходимости подключает в /opt
REMOTE_HOST (обязательно) Внутренний VPN-адрес удалённого сервера; при смене публичного IP не меняется
REMOTE_USER (обязательно) Логин SSH
REMOTE_PASSWORD (необязательно, пусто) Пароль SSH (используется только если найден sshpass)
REMOTE_SSH_KEY (рекомендуется) Путь к приватному SSH-ключу
REMOTE_SSH_PORT 22 Порт SSH
REMOTE_PATH /opt/esimych-cloud Путь к папке на удалённой системе
BACKUP_DIR (обязательно) Папка на QNAP для резервных копий (напр. /share/Public/backups)
WG_KEEP_UP 0 Оставить WireGuard активным после завершения
BACKUP_KEEP_COUNT 5 Сколько последних резервных копий и логов хранить
NEXTCLOUD_SERVICE_NAME nextcloud Имя Nextcloud-сервиса в docker compose для команд occ
SERVICES_START_RETRIES 3 Число попыток запуска и проверки сервисов после бэкапа
SERVICES_START_RETRY_DELAY_SEC 15 Пауза между повторными попытками запуска сервисов
OPTIMIZE_MARIADB_BEFORE_BACKUP 0 Выполнить оптимизацию MariaDB перед архивом
MARIADB_SERVICE_NAME mariadb Имя MariaDB-сервиса в docker compose
MARIADB_PURGE_BINLOGS 0 Очистить старые binary logs
MARIADB_TRUNCATE_GENERAL_LOG 1 Очистить general.log перед архивом
OPTIMIZE_REDIS_BEFORE_BACKUP 0 Выполнить BGREWRITEAOF для Redis
REDIS_SERVICE_NAME valkey Имя сервиса Redis/Valkey в docker compose
REDIS_REWRITE_WAIT_SEC 180 Верхний предел ожидания BGREWRITEAOF (сек), не типичная длительность (см. пояснение в разделе cloud_backup.sh выше)
REDIS_LOG_TAIL_LINES 300 Число последних строк Redis/Valkey, сохраняемых перед docker compose down
DB_OPTIMIZE_INTERVAL_DAYS 7 Интервал выполнения включённых оптимизаций MariaDB/Redis; дата последнего запуска хранится в state/cloud_backup_qnap-db-optimize.state
SSH_CIPHERS chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-ctr Приоритет SSH-шифров; chacha20-poly1305 первым, т.к. на слабых ARM-чипах без аппаратного AES он обычно быстрее программного AES-GCM/CTR, а расшифровку входящего потока бэкапа выполняет именно QNAP
RAW_TRANSFER_ENABLED 0 Передавать поток бэкапа через сырой TCP (nc/ncat) внутри WireGuard-туннеля в обход дополнительного слоя SSH-шифрования — см. раздел «Передача в обход SSH-шифрования» ниже. 0 — обычная передача через SSH (без изменений)
RAW_TRANSFER_PORT 8873 TCP-порт для приёма потока на удалённом сервере (нужно один раз открыть в фаерволе, см. шаг 8 в шапке скрипта)
RAW_TRANSFER_CONNECT_RETRIES 10 Число попыток подключения к листенеру (по 2 сек между попытками)
RAW_TRANSFER_REMOTE_TIMEOUT_SEC 21600 Потолок времени жизни удалённого листенера (защита от зависшего процесса, если QNAP так и не подключился)
RAW_TRANSFER_STATUS_POLL_RETRIES 5 Число попыток получить статус завершения удалённого пайплайна после приёма данных
NETWORK_SPEED_TEST_MB 50 Размер тестовой передачи (МБ) для замера реальной скорости сети QNAP↔REMOTE_HOST перед началом бэкапа (событие network_speed_test)
BACKUP_DEGRADATION_MIBS_THRESHOLD 4 Порог средней скорости, ниже которого создаётся backup_degradation

Логи: JSONL-файл logs/cloud_backup_qnap-YYYY-MM-DD-HH-MM-SS.jsonl на QNAP. Хранится BACKUP_KEEP_COUNT последних файлов (см. cleanup_logs, тот же параметр, что и для архивов).

Диагностика скорости: перед передачей и во время неё скрипт фиксирует сетевой тест, RTT, load average, доступную память и IO QNAP. Итоговое событие backup_metrics содержит размер, длительность, среднюю скорость и агрегированные ресурсные показатели. При скорости ниже BACKUP_DEGRADATION_MIBS_THRESHOLD создаётся backup_degradation с вероятной причиной. Ошибки raw-transfer дополняются снимком состояния удалённого сервера.

После бэкапа docker compose up -d и состояние контейнеров проверяются до SERVICES_START_RETRIES раз. Если после всех попыток остаются unhealthy, exited, dead или restarting контейнеры, в лог записываются docker compose ps -a и логи Redis/Valkey, а сам скрипт завершается с ненулевым кодом.

Передача в обход SSH-шифрования (RAW_TRANSFER_ENABLED): при значении 1 сжатый поток передаётся через сырой TCP внутри WireGuard-туннеля, без дополнительного SSH-шифрования. WireGuard продолжает обеспечивать конфиденциальность и целостность; SSH используется для управляющих команд и запуска листенера.

Для корректного завершения потока используются:

  • удалённая сторона: nc -N -l ... — без флага -N OpenBSD nc не закрывает сокет по EOF своего stdin и висит до RAW_TRANSFER_REMOTE_TIMEOUT_SEC (часы) вместо того, чтобы завершиться сразу после отправки всех данных;
  • сторона QNAP: ncat --recv-only ... < /dev/null — флаг запрещает отправку локального stdin, а перенаправление позволяет процессу завершиться после получения EOF от сервера.

Порт RAW_TRANSFER_PORT нужно открыть в фаерволе удалённого сервера. При недоступности nc или исчерпании попыток подключения скрипт автоматически переходит на SSH-передачу.

Имя архива и поведение при дозаписи — идентично cloud_backup.sh (см. выше): cloud_backup_qnap-YYYY-MM-DD.tar.zst/.tar.gz, проверка целостности и дозапись валидного архива за текущую дату, встроенные excludes для кэшей/preview/tmp.

Планирование запуска на QNAP — Планировщик задач QTS (если доступен) либо персистентный crontab (в отличие от обычного Linux, /etc/config/crontab переживает перезагрузку NAS, т.к. хранится в конфигурации прошивки):

vi /etc/config/crontab
# добавить строку (например, каждый день в 04:00):
0 4 * * * /share/Public/tasks/cloud_backup_qnap.sh >/dev/null 2>&1
crontab /etc/config/crontab
/etc/init.d/crond.sh restart

Важно: не запускайте cloud_backup.sh (десктоп) и cloud_backup_qnap.sh одновременно против одного и того же REMOTE_HOST — оба скрипта независимо управляют docker compose down/up -d на удалённом сервере, и параллельный запуск может привести к преждевременному перезапуску сервисов или конфликту жизненного цикла контейнеров.

Важно: в crontab вызывайте скрипт напрямую, не через sh: явный sh /share/Public/tasks/cloud_backup_qnap.sh игнорирует шебанг #!/opt/bin/bash и запускает Bash-скрипт системным /bin/sh QTS.


auto_delete_old_files.sh

Автоматически удаляет старые файлы по сроку хранения из указанной папки.

Конфигурация (conf/auto_delete_old_files.conf):

Параметр По умолчанию Описание
TARGET_DIR (обязательно) Каталог, где нужно удалять старые файлы
FILE_TYPES all Типы файлов: all или список расширений (log,tmp,bak)
KEEP_DAYS 30 Сколько дней хранить файлы

Правило удаления: удаляются только файлы (-type f) старше KEEP_DAYS дней.

Использование:

./auto_delete_old_files.sh

Cron (каждый день в 20:30):

30 20 * * * /home/esimych/esimych-docs/mytasks/auto_delete_old_files.sh >/dev/null 2>&1

check-store-mount.sh

Проверяет, смонтированы ли все точки монтирования из /etc/fstab.

Возможности:

  • Пропускает виртуальные ФС (/proc, /sys, /dev, swap и др.)
  • При обнаружении несмонтированных точек отправляет desktop-уведомление через notify-send
  • Дублирует сообщение в консоль
  • Предназначен для запуска через cron или autostart

Использование:

./check-store-mount.sh

btrfs_monitor.sh

Мониторинг счётчиков ошибок Btrfs на корневом разделе (или другой точке монтирования).

Что делает:

  • Читает btrfs device stats для ROOT_PATH
  • Сравнивает с прошлым запуском (state-файл)
  • При росте счётчиков выводит alert, пишет ERROR в JSONL-лог и завершает работу с кодом 1
  • На первом запуске только инициализирует baseline

Конфигурация:

  • conf/btrfs_monitor.conf
  • пример: conf/btrfs_monitor.conf.example

Использование:

./btrfs_monitor.sh

Cron (каждые 6 часов):

0 */6 * * * /home/esimych/esimych-docs/mytasks/btrfs_monitor.sh >/dev/null 2>&1

system_monitor.sh

Диагностика системы: жёсткие диски через SMART (smartctl), CPU (температура, загрузка, load average) и GPU (NVIDIA, через nvidia-smi). Опрос, запись состояния в SQLite и формирование HTML-отчёта (таблицы, диаграммы, аналитическая справка по каждому диску). Предназначен для запуска по расписанию и/или при загрузке системы.

Что делает:

Диски:

  • Определяет физические диски автоматически через lsblk (или берёт список из DISKS в конфиге), пропуская zram, loop, ram, sr, dm-
  • Опрашивает каждый диск через smartctl -a -j (JSON) и разбирает результат через jq: health, модель, серийный номер, температура, наработка (power-on hours), Reallocated_Sector_Ct, Current_Pending_Sector, Offline_Uncorrectable (для NVMe — соответствующие поля nvme_smart_health_information_log)
  • Определяет устойчивое системное имя диска (/dev/disk/by-id/..., например ata-ST4000DM004-2U9104_WW608PYW) — не меняется при перестановке дисков/перезагрузке, в отличие от /dev/sdX; хранится в SQLite вместе с остальными метриками
  • Определяет точки монтирования диска через lsblk -J + jq, с привязкой к разделу (например nvme0n1p1: /, /var/log, /var/cache, /var/tmp, /root, /srv; nvme0n1p2: /boot/efi) — на btrfs один и тот же раздел часто смонтирован сразу в несколько мест через подтома (subvolumes); JSON-разбор через jq берётся не случайно: построчный lsblk -o MOUNTPOINT (ед. число) отдаёт только одну точку на раздел и может молча потерять корень /
  • Определяет объём диска в байтах через lsblk -bdn -o SIZE (не зависит от smartctl — доступен даже если SMART недоступен/диск не поддерживается) и показывает его в отчёте в человекочитаемом виде (КиБ/МиБ/ГиБ/ТиБ)

CPU:

  • Температура — через lm_sensors (sensors -j), ищет главный тепловой датчик пакета (Tctl/Tdie на AMD, Package id 0 на Intel); опционально — если sensors не установлен/не настроен, CPU всё равно опрашивается, просто без температуры
  • Загрузка (%) — две выборки /proc/stat с интервалом в 1 секунду (тот же принцип, что использует top/mpstat), без дополнительных зависимостей
  • Load average (1/5/15 мин) — из /proc/loadavg

GPU (NVIDIA):

  • Через nvidia-smi --query-gpu=... --format=csv: модель, температура, загрузка (%), использование видеопамяти, потребляемая мощность — по каждой видеокарте отдельно (поддержка нескольких GPU)
  • Опционально — если nvidia-smi не найден (нет NVIDIA GPU или драйвера), опрос GPU просто пропускается, это не ошибка

Отчёт и хранение:

  • Пишет каждый опрос как строки в таблицы disk_stats/cpu_stats/gpu_stats в SQLite (DB_FILE), не перезаписывая историю — на её основе строятся графики. Все данные, которые попадают в отчёт, сначала сохраняются в SQLite (ничего не вычисляется «на лету» только для HTML) — это сделано специально, чтобы дальше можно было строить аналитические отчёты поверх накопленной истории
  • Формирует HTML-отчёт целиком из данных SQLite: сводные плитки (кол-во объектов в норме/внимание/критично по дискам+CPU+GPU вместе), таблица метрик по каждому диску (с колонками «Точка монтирования» и «Объём»), аналитическая справка по каждому диску (деградация поверхности, риск отказа, перегрев, точки монтирования и т.д.), таблицы и графики по CPU и GPU, график истории температуры дисков и диаграмма Reallocated/Pending-секторов — всё встроенным SVG, без внешних JS-библиотек. Графики CPU/GPU совмещают температуру (°C) и проценты (загрузка, VRAM) на одной общей шкале 0-100 — это не «две оси», а честно общий диапазон, единица измерения проставлена у каждой точки
  • При критическом состоянии любого объекта (диск: SMART FAILED/неисправимые ошибки чтения/температура выше TEMP_CRIT_C; CPU/GPU: температура выше CPU_TEMP_CRIT_C/GPU_TEMP_CRIT_C) отправляет desktop-уведомление через notify-send (как btrfs_monitor.sh / check-store-mount.sh) и завершается с кодом 1; предупреждения (переназначенные/ожидающие секторы диска, температура выше порога «внимание») только пишутся в лог, без уведомления
  • Ротирует и JSONL-логи (KEEP_LOGS), и HTML-отчёты (REPORT_KEEP)

Конфигурация:

  • conf/system_monitor.conf
  • пример: conf/system_monitor.conf.example
Параметр По умолчанию Описание
DISKS (пусто = автоопределение) Список дисков через запятую (sda,sdb), пусто — автоопределение через lsblk
DB_FILE state/system_monitor.db Путь к базе SQLite с историей опросов
REPORT_DIR system_reports/ рядом со скриптом Каталог для HTML-отчётов
REPORT_KEEP 5 Сколько последних HTML-отчётов хранить
KEEP_LOGS 10 Сколько последних JSONL-логов хранить
HISTORY_POINTS 30 Сколько последних опросов показывать на графиках истории
SMARTCTL_BIN smartctl Путь к бинарю smartctl, если не в PATH
SENSORS_BIN sensors Путь к бинарю sensors (lm_sensors), если не в PATH; опционально
NVIDIA_SMI_BIN nvidia-smi Путь к бинарю nvidia-smi, если не в PATH; опционально
TEMP_WARN_C, TEMP_CRIT_C 50, 60 Пороги температуры дисков (°C) для «внимание»/«критично»
CPU_TEMP_WARN_C, CPU_TEMP_CRIT_C 80, 90 Пороги температуры CPU (°C)
GPU_TEMP_WARN_C, GPU_TEMP_CRIT_C 75, 85 Пороги температуры GPU (°C)
APP_NAME, ICON_NAME, URGENCY SystemMonitor, utilities-system-monitor, critical Параметры desktop-уведомления

Использование:

# Опрос дисков/CPU/GPU + запись в SQLite + HTML-отчёт
sudo ./system_monitor.sh

# Только пересобрать HTML-отчёт из уже накопленных данных, без опроса
sudo ./system_monitor.sh -r

Важно: для чтения SMART-атрибутов smartctl обычно требует root — крон-запись нужно добавлять в root-crontab (sudo crontab -e), а не в обычный пользовательский. Опрос CPU/GPU root не требует, но так как весь скрипт обычно запускается под root ради дисков, они опрашиваются в том же (привилегированном) запуске.

Расписание — systemd timer (рекомендуется):

Юнит-файлы лежат в systemd/system-monitor.service и systemd/system-monitor.timer. Таймер срабатывает в 00/06/12/18 часов, а благодаря Persistent=true пропущенный слот (машина была выключена) выполняется при первой же загрузке — и не более одного раза за интервал. Обычный cron 0 */6 пропуски не догоняет: если компьютер включают, скажем, в 18:30 и выключают до полуночи, замеры не будут попадать в базу вообще.

sudo cp systemd/system-monitor.service systemd/system-monitor.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now system-monitor.timer

# Проверка
systemctl list-timers system-monitor.timer
journalctl -u system-monitor.service -n 20

Если раньше скрипт стоял в root-crontab — строку 0 */6 * * * …system_monitor.sh оттуда нужно убрать (sudo crontab -e), иначе опрос будет идти дважды.

Cron (альтернатива, без догоняния пропусков):

0 */6 * * * /home/esimych/esimych-docs/mytasks/system_monitor.sh >/dev/null 2>&1

Актуальный отчёт всегда доступен по стабильному пути system_reports/latest.html; предыдущие версии хранятся как system_reports/system_monitor-<timestamp>.html (не более REPORT_KEEP штук).


cp1251_to_utf8.sh

Рекурсивная перекодировка текстовых файлов из Windows-1251 в UTF-8.

Возможности:

  • Пропускает бинарные и уже UTF-8 файлы
  • Атомарная замена через временный файл (mktemp)
  • Сохраняет права и владельца файла
  • Режим --dry-run — только показывает, что будет перекодировано

Использование:

./cp1251_to_utf8.sh <каталог>
./cp1251_to_utf8.sh <каталог> --dry-run
./cp1251_to_utf8.sh -h

delete_by_ext.sh

Рекурсивное удаление файлов по расширению с логированием.

Опции:

Опция Описание
-d DIR Каталог для обработки (обязательно)
-e EXT Расширение без точки, например: tmp, log, bak
--dry-run Показать файлы без удаления
-h Справка

Использование:

./delete_by_ext.sh -d /tmp -e log --dry-run
./delete_by_ext.sh -d ./downloads -e tmp

Лог пишется в logs/delete_by_ext-YYYY-MM-DD-HH-MM-SS.jsonl; хранятся 10 последних JSONL-файлов.


doc2fb2.sh

Рекурсивная конвертация DOC / DOCX / RTF / ODT → FB2.

Цепочки конвертации:

  • docx, odt → pandoc → fb2
  • doc, rtf → LibreOffice → odt → pandoc → fb2
  • Fallback для rtf: pandoc напрямую, затем unrtf → txt → pandoc
  • Fallback для doc: antiword / catdoc / wvText → txt → pandoc

Ключевые опции:

Опция Описание
-d, --dir DIR Исходный каталог (обязательно)
-o, --out OUTDIR Выходной каталог
-n, --dry-run Без изменений, только показать
--overwrite Перезаписывать существующие FB2
--skip-newer Пропускать, если FB2 новее источника
--exclude PATTERN Исключить файлы по маске (можно несколько раз)
`--only doc docx
--author NAME Принудительно установить автора
--toc / --no-toc Добавить/убрать оглавление
`--log-level info error`

Использование:

./doc2fb2.sh -d /книги --dry-run
./doc2fb2.sh -d /книги -o /fb2 --overwrite --log-level error

Лог: JSONL-файл doc2fb2_*.jsonl. Логи старше 10 дней удаляются автоматически.


getip.sh

Определяет текущий внешний IP-адрес и ведёт его историю.

Возможности:

  • Запрашивает внешний IP у настраиваемого URL-сервиса через curl
  • Сохраняет текущий IP в файл
  • Добавляет запись с временной меткой, если полученного IP ещё нет в файле истории
  • Все пути и URL задаются через конфиг-файл conf/getip.conf

Конфигурация (conf/getip.conf):

Параметр По умолчанию
IP_SERVICE_URL https://icanhazip.com
IP_FILE /var/downloads/clouddata/nextcloud/work/ip.txt
IP_HISTORY_FILE /var/downloads/clouddata/nextcloud/work/ip_history.txt

Примеры совместимых сервисов: https://api.ipify.org, https://ifconfig.me/ip, https://checkip.amazonaws.com

Использование:

./getip.sh

hp_p1005_garuda.sh

Скрипт установки и настройки принтера HP LaserJet P1005 на Garuda Linux (Arch-based).

Возможности:

  • Устанавливает необходимые пакеты: hplip, system-config-printer, CUPS
  • Настраивает службы CUPS
  • Запуск без аргументов = --all (выполнить все шаги)
  • JSONL-логирование в файл hp_p1005_garuda_YYYY-MM-DD-HH-MM-SS.jsonl

Использование:

sudo ./hp_p1005_garuda.sh
sudo ./hp_p1005_garuda.sh --all

lowercase_ext.sh

Переименовывает расширения файлов в нижний регистр (.JPG.jpg, .MP3.mp3).

Режимы:

Режим Описание
--dry-run Показать, что будет переименовано
--apply Реально переименовать файлы

Использование:

./lowercase_ext.sh --dry-run /path/to/dir
./lowercase_ext.sh --apply   /path/to/dir

Показывает прогресс в процентах при обработке.


mht_to_fb2.py

Рекурсивно обрабатывает MHT/MHTML и CHM в указанном каталоге.

Возможности:

  • Умная автодетекция кодировки: UTF-8, CP1251, KOI8-R, Latin-1
  • Извлекает текст и структуру из HTML-части архива
  • MHT/MHTML конвертирует через pandoc в FB2 рядом с исходником; после успешной обычной конвертации удаляет исходный веб-архив
  • Для CHM не выполняет конвертацию, а удаляет одноимённый FB2, если он существует
  • --overwrite разрешает перезаписать существующий FB2
  • --dry-run не удаляет исходный MHT/MHTML и только имитирует удаление FB2 для CHM, но текущая реализация всё равно запускает pandoc и может записать FB2
  • JSONL-логирование в папку logs/

Требования: Python 3, pandoc

Использование:

python3 mht_to_fb2.py /архивы
python3 mht_to_fb2.py /архивы --overwrite
python3 mht_to_fb2.py /архивы --dry-run

music_downloader.sh

Обёртка для запуска Python-проекта music_downloader.

Порядок работы:

  1. Активирует виртуальное окружение (venv) в папке music_downloader/, если оно существует.
  2. Запускает music_downloader.py и сохраняет его код выхода.
  3. Деактивирует venv; при коде выхода загрузчика 0 запускает split_by_dash.sh, если он найден.
  4. Логирует результат и возвращает код выхода загрузчика.

Конфигурация загрузчика: в music_downloader/music_downloader.json общий непустой список download_paths задаётся в корне JSON, рядом с sites. Каждый трек любого моста сохраняется во все указанные папки. path задаёт каталог, max_size_mb — лимит его общего размера (по умолчанию 1024 МБ), а не квоту отдельного сайта. При переходе со старого формата перенесите общий список из сайта в корень JSON и удалите копии из sites: локальные настройки папок мостов больше не используются.

Папки и лимиты проверяются до обращения к сайтам и перед сохранением каждого трека. Размер проверяется в байтах, в том числе для каждого блока потока без Content-Length. Если трек не помещается хотя бы в одну папку, загрузчик удаляет его незавершённые .part, не записывает его в БД и завершает работу с кодом 2, без запуска сортировщика. Уже сохранённые треки остаются. Контроль рассчитан на один процесс загрузчика; параллельные записи других программ требуют квот файловой системы. Отсутствующий/пустой глобальный список, отсутствующая папка или уже достигнутый лимит также завершают запуск с кодом 2. Ошибки отдельных сайтов и треков логируются, но не обязательно меняют итоговый код выхода. При отсутствии файла конфигурации текущий загрузчик возвращает 0 без скачивания — подготовьте JSON до запуска обёртки. Пути сортировщика настраиваются отдельно.

Jamendo для категории / использует официальный API последних треков вместо HTML главной страницы, выбирая только записи с разрешённым скачиванием. Пустые результаты и ошибки явно логируются; подробности — в README загрузчика.

Мосты shazam_com (мировой Top 200; аудио ищется по точному совпадению в Sefon и LMusic) и mychords_net (новинки, аудио из встроенного плеера xpleer) получают ссылку на файл только перед скачиванием нового трека (resolve_track), поэтому уже скачанные позиции не вызывают лишних запросов.

Логи: в общей папке logs/ обёртка пишет music_downloader-<timestamp>.jsonl (оставляет последние 10 файлов), Python-движок — music_downloader_engine-<timestamp>.jsonl (очистка по глобальным log_cleanup_days и log_max_files, по умолчанию 10 дней и 10 файлов). Текстовый вывод загрузчика и сортировщика записывается в logs/cron_execution.log.

Использование:

./music_downloader.sh

Подробнее — в README загрузчика. Каталог music_downloader/ входит в этот репозиторий как обычная папка, без вложенного .git и без submodule. Код, драйверы, тесты и шаблон конфигурации версионируются вместе с mytasks; рабочий JSON, БД, логи и venv исключены правилами music_downloader/.gitignore. CI загрузчика находится в .github/workflows/music-downloader.yml.


replace_encoding.sh

Заменяет строку в текстовых файлах (поиск + замена через sed).

По умолчанию заменяет windows-1251utf-8 во всех текстовых файлах каталога. Если каталог не указан, используется текущий (.).

Опции:

Опция Описание
-d, --dry-run Показать файлы без изменений
-n, --no-recursive Только текущий каталог (без подкаталогов)
-h, --help Справка

Использование:

./replace_encoding.sh /path/to/dir
./replace_encoding.sh /path/to/dir "старая строка" "новая строка"
./replace_encoding.sh -d /path/to/dir

sources.sh

Синхронизация файлов на основе конфиг-файла conf/sources.conf с помощью rsync.

Формат конфига (каждая строка):

источник | назначение | rsync-аргументы

Опции:

Опция Описание
-c Указать альтернативный конфиг
-n Режим dry-run (передаёт --dry-run в rsync)
-E Разобрать кавычки в аргументах rsync через xargs, без выполнения eval
-h Справка

Логи: JSONL-файл logs/sources_YYYY-MM-DD-report.jsonl. Логи старше 10 дней удаляются автоматически.

Использование:

./sources.sh
./sources.sh -n
./sources.sh -c /path/to/my.conf

split_by_dash.sh

Раскладывает файлы по папкам-исполнителям по шаблону Исполнитель - Название.

Алгоритм:

  • Ищет - (или , ) в имени файла
  • Часть до разделителя становится именем подпапки
  • Файл перемещается в эту подпапку; при конфликте имён добавляет суффикс .1, .2

Источники каталогов:

  1. Аргумент командной строки: ./split_by_dash.sh /путь/к/папке
  2. Конфиг-файл conf/split_by_dash.conf (список папок, по одной на строку)

Перенос результата (опционально):

  • Строка DEST_DIR=/путь/к/каталогу в conf/split_by_dash.conf задаёт каталог, куда переносятся все получившиеся папки-исполнители после разбора
  • Если папки с таким именем в DEST_DIR ещё нет — она переносится целиком
  • Если такая папка уже существует — файлы объединяются в неё (конфликты имён также разрешаются суффиксом .1, .2…), а опустевший источник удаляется
  • Без DEST_DIR папки остаются внутри исходного каталога
  • Все операции переноса/объединения логируются

Логи: JSONL-файл в logs/. Хранятся 10 последних файлов.

Использование:

./split_by_dash.sh /path/to/music
./split_by_dash.sh   # использует conf/split_by_dash.conf

unpack-fb2zip.sh

Распаковывает архивы *.fb2.zip, извлекая .fb2-файлы в тот же каталог.

Возможности:

  • Рекурсивный поиск *.fb2.zip
  • Конфликты имён разрешаются суффиксами _1, _2
  • Режим --dry-run
  • JSONL-логирование

Опции:

Опция Описание
-p, --path DIR Корневая папка для поиска (обязательно)
--dry-run Только показать действия
--log FILE Путь к JSONL-логу
-h, --help Справка

Использование:

./unpack-fb2zip.sh -p /книги
./unpack-fb2zip.sh -p /книги --dry-run

Зависимости

Скрипт Основные зависимости
all_to_mp3.sh ffmpeg, ffprobe, find, xargs
auto_delete_old_files.sh POSIX shell, find, sort, awk, sed
btrfs_monitor.sh Bash, btrfs, findmnt, awk; опц.: notify-send
check-store-mount.sh Bash, mountpoint, timeout; опц.: notify-send
cloud_backup.sh Bash, wg-quick, sshpass, ssh; удалённо: docker, tar, один из zstd/pigz/gzip
cloud_backup_qnap.sh Entware Bash, wireguard-go, ncat, xxd, ssh; удалённо: docker, tar, nc, один из zstd/pigz/gzip
cp1251_to_utf8.sh iconv, file, find
delete_by_ext.sh find
doc2fb2.sh pandoc, libreoffice; опц.: unrtf, antiword, catdoc, wvText
getip.sh curl
hp_p1005_garuda.sh Arch/Garuda, pacman, lsusb, systemctl, CUPS (lp), system-config-printer
lowercase_ext.sh Bash, find, mv
mht_to_fb2.py Python 3, pandoc
music_downloader.sh Bash, Python 3, локальный проект music_downloader/; после успеха — split_by_dash.sh
replace_encoding.sh Bash, grep, sed
sources.sh POSIX shell, rsync, xargs
split_by_dash.sh POSIX shell, find, mv, sed
system_monitor.sh Bash, smartctl (root), jq, sqlite3, lsblk; опц.: sensors, nvidia-smi, notify-send
unpack-fb2zip.sh Bash, find, unzip

Тесты (bats-core)

Каталог tests/ содержит отдельные Bats-тесты для актуальных shell-скриптов и общий all_scripts_syntax.bats, который проверяет синтаксис каждого корневого *.sh по его шебангу. Внешние команды стабируются через временный PATH; для system_monitor.sh настоящими остаются sqlite3 и jq.

Установка и полный запуск:

git clone --depth 1 https://github.com/bats-core/bats-core.git /tmp/bats-core
sudo /tmp/bats-core/install.sh /usr/local
bats --print-output-on-failure tests

Запуск одного набора:

bats --print-output-on-failure tests/cloud_backup_qnap.bats

GitHub CI:

  • Workflow: .github/workflows/bats-tests.yml
  • Запускается автоматически на push и pull_request

Статический анализ и проверки стиля

При изменении корневых *.sh или *.py запускается workflow статического анализа.

GitHub CI: .github/workflows/shellcheck.yml

Шаг Что проверяется
ShellCheck error Ошибки и предупреждения уровня error (блокируют merge)
ShellCheck style Предупреждения уровня style (предпочтительный [[ ]], braces, case *)…)
bash/sh syntax bash -n или sh -n по shebang для каждого .sh
Unbraced variable scan grep-сканнер небракетированных $VAR в локальном bash-коде (не в remote-shell строках)
Python syntax python3 -m py_compile для каждого .py в корне

Workflow запускается при изменении *.sh или *.py.

Перед локальной отправкой изменений shell-скрипта дополнительно выполняйте все опциональные проверки ShellCheck:

bash -n path/to/script.sh
shellcheck -S style path/to/script.sh
shellcheck -o all path/to/script.sh

About

рабочие скрипты

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages