Оповещения: группа «Администратор системы», блок «Кому писать» открыт; копии: адрес хранилища как в проводнике
Администратору (адрес из «Почты») — сбои (ИШ, связь с НРД, службы 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:
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user