#!/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 — поставить часы сейчас по серверам службы времени (не ждать её плавной подстройки) 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 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