Оповещения: группа «Администратор системы», блок «Кому писать» открыт; копии: адрес хранилища как в проводнике

Администратору (адрес из «Почты») — сбои (ИШ, связь с НРД, службы bj, DEPO) и обновления (новый выпуск bj,
ИШ, лицензия, сертификаты); отделам — переводы и поручения. Существующие установки: администратор получает
всё, что получал. Новые оповещения: «Доступно обновление bj» (раз на выпуск), «Служба … не работает /
снова работает» (модули и служба ключей Валидаты). Резервные копии: \\сервер\папка или сервер + общая
папка по полям → //сервер/папка; понятная причина отказа доступа.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-06 22:44:35 +03:00
parent f07bb53162
commit d23ddf6e0c
16 changed files with 547 additions and 63 deletions
+19 -1
View File
@@ -9,7 +9,25 @@ CRED=/etc/bj/backup-smb.cred
STATUS=/var/lib/bj/backup-status.json
[ -r "$CONF" ] && . "$CONF"
SHARE=${SHARE:-}
DIR=${DIR:-bj-backup}
DIR=${DIR:-}
# smbloc — адрес хранилища, как его вводят (\\nas\backup\bj как в проводнике, //nas/backup, smb://…, сервер
# в «Хранилище» + общая папка в «Папке») → две строки: общая папка для smbclient (//сервер/папка) и путь внутри неё
smbloc(){ python3 - "$1" "$2" <<'PY'
import re,sys
def parts(s):
s=s.strip().replace('\\','/')
m=re.match(r'(?i)smb://',s)
if m: s=s[m.end():]
return [p.strip() for p in s.split('/') if p.strip()]
sp,dp=parts(sys.argv[1]),parts(sys.argv[2])
if not sp: print(''); print('/'.join(dp)); sys.exit()
if len(sp)==1:
if not dp: print('//'+sp[0]); print(''); sys.exit()
sp,dp=[sp[0],dp[0]],dp[1:]
print('//'+sp[0]+'/'+sp[1]); print('/'.join(sp[2:]+dp))
PY
}
mapfile -t _loc < <(smbloc "$SHARE" "$DIR"); SHARE=${_loc[0]:-}; DIR=${_loc[1]:-bj-backup}
KEEP_DAYS=${KEEP_DAYS:-14}
TS=$(date +%Y-%m-%d_%H%M)
W=$(mktemp -d /var/tmp/bj-backup.XXXXXX)
+30 -3
View File
@@ -19,8 +19,25 @@ err() { echo "{\"ok\":false,\"error\":$(q "$1")}"; exit 0; }
[ -r "$CONF" ] && . "$CONF"
# хранилище из запроса (восстановление на новом сервере, проверка до сохранения) или из настроек
SHARE_IN=$(j share); DIR_IN=$(j dir); USER_IN=$(j user); PASS_IN=$(j password)
SHARE=${SHARE_IN:-${SHARE:-}}; DIR=${DIR_IN:-${DIR:-bj-backup}}
case "$SHARE" in //*) ;; \\\\*) SHARE=$(printf '%s' "$SHARE" | tr '\\' '/') ;; ?*) SHARE="//$SHARE" ;; esac
SHARE=${SHARE_IN:-${SHARE:-}}; DIR=${DIR_IN:-${DIR:-}}
# smbloc — адрес хранилища, как его вводят (\\nas\backup\bj как в проводнике, //nas/backup, smb://…, сервер
# в «Хранилище» + общая папка в «Папке») → две строки: общая папка для smbclient (//сервер/папка) и путь внутри неё
smbloc(){ python3 - "$1" "$2" <<'PY'
import re,sys
def parts(s):
s=s.strip().replace('\\','/')
m=re.match(r'(?i)smb://',s)
if m: s=s[m.end():]
return [p.strip() for p in s.split('/') if p.strip()]
sp,dp=parts(sys.argv[1]),parts(sys.argv[2])
if not sp: print(''); print('/'.join(dp)); sys.exit()
if len(sp)==1:
if not dp: print('//'+sp[0]); print(''); sys.exit()
sp,dp=[sp[0],dp[0]],dp[1:]
print('//'+sp[0]+'/'+sp[1]); print('/'.join(sp[2:]+dp))
PY
}
mapfile -t _loc < <(smbloc "$SHARE" "$DIR"); SHARE=${_loc[0]:-}; DIR=${_loc[1]:-bj-backup}
TMPCRED=""
credfile() {
if [ -n "$USER_IN" ] && [ -n "$PASS_IN" ]; then
@@ -72,7 +89,17 @@ case "$cmd" in
f=/tmp/bj-backup-test.$$; echo test > "$f"; top=${DIR%%/*}
smbx "$c" "mkdir \"$top\"; mkdir \"$DIR\"" >/dev/null
out=$(smbx "$c" "cd \"$DIR\"; put $f bj-write-test.txt; del bj-write-test.txt"); rc=$?; rm -f "$f"
if [ $rc -ne 0 ] || printf '%s' "$out" | grep -q "NT_STATUS"; then err "нет доступа на запись в $SHARE/$DIR: $(printf '%s' "$out" | grep -o 'NT_STATUS[A-Z_]*' | head -1)"; fi
if [ $rc -ne 0 ] || printf '%s' "$out" | grep -q "NT_STATUS"; then
why=$(printf '%s' "$out" | grep -o 'NT_STATUS[A-Z_]*' | head -1)
case "$why" in
NT_STATUS_BAD_NETWORK_NAME) why="на сервере нет общей папки «${SHARE##*/}» ($why)" ;;
NT_STATUS_LOGON_FAILURE) why="неверный логин или пароль ($why)" ;;
NT_STATUS_ACCESS_DENIED) why="у логина нет прав на запись ($why)" ;;
NT_STATUS_HOST_UNREACHABLE|NT_STATUS_IO_TIMEOUT|NT_STATUS_CONNECTION_REFUSED) why="сервер хранилища недоступен ($why)" ;;
"") why=$(printf '%s' "$out" | grep -v '^\s*$' | tail -1) ;;
esac
err "нет доступа на запись в $SHARE/$DIR: ${why:-smbclient завершился с кодом $rc}"
fi
ok "доступ на запись к $SHARE/$DIR есть" ;;
run)
systemctl start --no-block bj-backup.service || err "не удалось запустить bj-backup.service"