76e6f82369
«Сервер: HTTPS» → «Адрес без номера порта»: bj слушает 443 (тот же HTTPS) и 80 (переход на https://имя/), переходы и адреса — без «:8443». Право на порты <1024 — drop-in systemd AmbientCapabilities=CAP_NET_BIND_SERVICE через root-помощника (bj-system-admin ports on|off, bj перезапускается). Нет права/порт занят — bj работает по 8443, в настройках видна причина. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
93 lines
6.7 KiB
Bash
Executable File
93 lines
6.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# bj-system-admin — системные настройки сервера bj из веб-интерфейса (через root-демон bj-keymedia).
|
|
# tz — часовой пояс сервера (BJ_EXTRA: "Europe/Moscow")
|
|
# ntp — серверы времени (BJ_EXTRA: "ntp1.example.ru ntp2.example.ru"): ntpd, chrony или systemd-timesyncd —
|
|
# что стоит на сервере. Время важно для подписей и обмена с НРД.
|
|
# sync — поставить часы сейчас по серверам службы времени (не ждать её плавной подстройки)
|
|
# ports — адрес bj без номера порта (BJ_EXTRA: on|off): службе bj-server право слушать 443/80
|
|
# (drop-in AmbientCapabilities=CAP_NET_BIND_SERVICE), перезапуск bj через 3 с
|
|
set -uo pipefail
|
|
q() { python3 -c "import json,sys;print(json.dumps(sys.argv[1],ensure_ascii=False))" "$1"; }
|
|
ok() { echo "{\"ok\":true,\"output\":$(q "$1")}"; }
|
|
err() { echo "{\"ok\":false,\"error\":$(q "$1")}"; exit 0; }
|
|
cmd=${1:-}
|
|
case "$cmd" in
|
|
ports)
|
|
d=/etc/systemd/system/bj-server.service.d; f=$d/50-bj-std-ports.conf
|
|
case "${BJ_EXTRA:-on}" in
|
|
on) mkdir -p "$d" && printf '%s\n' '[Service]' '# bj слушает 443 (HTTPS) и 80 (переход на https://) — адрес без номера порта' 'AmbientCapabilities=CAP_NET_BIND_SERVICE' > "$f" || err "не удалось записать $f" ;;
|
|
off) rm -f "$f" ;;
|
|
*) err "ports: on или off" ;;
|
|
esac
|
|
systemctl daemon-reload || err "systemctl daemon-reload не выполнился"
|
|
systemd-run --quiet --on-active=3 /bin/systemctl restart bj-server.service >/dev/null 2>&1 || { (sleep 3; systemctl restart bj-server.service) >/dev/null 2>&1 & }
|
|
ok "порты 443/80: ${BJ_EXTRA:-on}; bj перезапустится через 3 с"
|
|
;;
|
|
ntp)
|
|
servers=$(printf '%s' "${BJ_EXTRA:-}" | tr ',;' ' ' | xargs)
|
|
[ -n "$servers" ] || err "не указан сервер времени"
|
|
for s in $servers; do [[ "$s" =~ ^[A-Za-z0-9][A-Za-z0-9.-]{0,252}$ ]] || err "недопустимое имя сервера времени: $s"; done
|
|
if systemctl is-active --quiet ntp || systemctl is-active --quiet ntpd || [ -f /etc/ntp.conf ] && ! systemctl is-active --quiet chrony && ! systemctl is-active --quiet systemd-timesyncd; then
|
|
conf=/etc/ntp.conf; [ -f "$conf" ] || err "нет /etc/ntp.conf"
|
|
cp -a "$conf" "$conf.bak-bj" 2>/dev/null
|
|
python3 - "$conf" $servers <<'PY' || err "не удалось изменить /etc/ntp.conf"
|
|
import sys,re
|
|
p,servers=sys.argv[1],sys.argv[2:]
|
|
out=[]
|
|
for l in open(p).read().split("\n"):
|
|
if l.startswith("server ") and l.rstrip().endswith("# bj"): continue # прежние наши
|
|
if re.match(r"^(server|pool) ",l): l="#bj# "+l # чужие — выключаем
|
|
out.append(l)
|
|
out+=[f"server {s} iburst # bj" for s in servers]
|
|
open(p,"w").write("\n".join(out).rstrip("\n")+"\n")
|
|
PY
|
|
svc=ntp; systemctl is-active --quiet ntpd && svc=ntpd
|
|
systemctl restart "$svc" || err "служба $svc не перезапустилась"
|
|
ok "серверы времени: $servers (служба $svc)"
|
|
elif systemctl is-active --quiet chrony || [ -d /etc/chrony ]; then
|
|
d=/etc/chrony/sources.d; mkdir -p "$d"
|
|
: > "$d/bj.sources"; for s in $servers; do echo "server $s iburst" >> "$d/bj.sources"; done
|
|
grep -q '^sourcedir /etc/chrony/sources.d' /etc/chrony/chrony.conf 2>/dev/null || echo 'sourcedir /etc/chrony/sources.d' >> /etc/chrony/chrony.conf
|
|
systemctl restart chrony || err "служба chrony не перезапустилась"
|
|
ok "серверы времени: $servers (служба chrony)"
|
|
else
|
|
mkdir -p /etc/systemd/timesyncd.conf.d
|
|
printf '[Time]\nNTP=%s\n' "$servers" > /etc/systemd/timesyncd.conf.d/bj.conf
|
|
timedatectl set-ntp true >/dev/null 2>&1
|
|
systemctl restart systemd-timesyncd || err "служба systemd-timesyncd не перезапустилась"
|
|
ok "серверы времени: $servers (служба systemd-timesyncd)"
|
|
fi ;;
|
|
sync)
|
|
synced() { hwclock --systohc >/dev/null 2>&1; ok "$1"; exit 0; }
|
|
if systemctl is-active --quiet chrony || systemctl is-active --quiet chronyd; then
|
|
chronyc -n sources 2>/dev/null | grep -q '^\^' || err "серверы времени не заданы"
|
|
chronyc -a 'burst 4/4' >/dev/null 2>&1; sleep 8
|
|
chronyc -a makestep >/dev/null 2>&1 || err "chrony не выполнил коррекцию часов"
|
|
sleep 1; synced "время синхронизировано (chrony, расхождение $(chronyc -n tracking | sed -n 's/^System time *: //p'))"
|
|
elif systemctl is-active --quiet ntp || systemctl is-active --quiet ntpd || { [ -f /etc/ntp.conf ] && ! systemctl is-active --quiet systemd-timesyncd; }; then
|
|
srv=$(awk '/^(server|pool) / && !seen[$2]++ {print $2}' /etc/ntp.conf 2>/dev/null | xargs)
|
|
[ -n "$srv" ] || err "серверы времени не заданы"
|
|
command -v ntpd >/dev/null || err "нет программы ntpd"
|
|
svc=ntp; systemctl is-active --quiet ntpd && svc=ntpd
|
|
systemctl stop "$svc" >/dev/null 2>&1
|
|
out=$(timeout 45 ntpd -gq 2>&1); rc=$?
|
|
systemctl start "$svc" >/dev/null 2>&1
|
|
[ $rc -eq 0 ] || err "серверы времени ($srv) не ответили за 45 с"
|
|
synced "время синхронизировано (ntpd, серверы $srv)"
|
|
else
|
|
timedatectl set-ntp true >/dev/null 2>&1
|
|
systemctl restart systemd-timesyncd || err "служба systemd-timesyncd не перезапустилась"
|
|
for _ in $(seq 1 15); do
|
|
[ "$(timedatectl show -p NTPSynchronized --value)" = yes ] && synced "время синхронизировано (systemd-timesyncd, сервер $(timedatectl show-timesync -p ServerName --value 2>/dev/null))"
|
|
sleep 2
|
|
done
|
|
err "служба времени не получила время за 30 с — серверы времени недоступны"
|
|
fi ;;
|
|
tz)
|
|
zone=$(printf '%s' "${BJ_EXTRA:-}" | tr -d ' ')
|
|
[[ "$zone" =~ ^[A-Za-z]+(/[A-Za-z_+-]+)*$ ]] && [ -f "/usr/share/zoneinfo/$zone" ] || err "неизвестный часовой пояс: $zone"
|
|
timedatectl set-timezone "$zone" 2>/dev/null || { ln -sf "/usr/share/zoneinfo/$zone" /etc/localtime && echo "$zone" > /etc/timezone; } || err "не удалось установить часовой пояс"
|
|
ok "часовой пояс сервера: $zone" ;;
|
|
*) err "неизвестная команда: $cmd" ;;
|
|
esac
|