Java 17 для службы подписи: установщик ставит openjdk-17-jre-headless там, где Java по умолчанию старее (Ubuntu 22.04 — 11; crypto-service собран под 17), в слой образа кладётся Java 17; «Подготовка модулей» и проверка готовности не принимают падающую по кругу службу за работающую (работает ≥ 5 с) и называют причину — в том числе «слишком старая Java» с командой исправления
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -9,6 +9,8 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -47,17 +49,19 @@ func prepareItems(rc *RuntimeConfig, running, finished bool, runErr string) []Pr
|
||||
it := PrepareItem{Title: prepareTitle(c)}
|
||||
_, statErr := os.Stat(c.Path)
|
||||
present := statErr == nil
|
||||
us := ""
|
||||
var u unitRun
|
||||
if present && c.Unit != "" {
|
||||
us = unitState(c.Unit).State
|
||||
u = unitRunState(c.Unit)
|
||||
}
|
||||
switch {
|
||||
case us == "active":
|
||||
case u.State == "active" && u.Up >= 5*time.Second:
|
||||
it.State, it.Detail = "ok", "установлен, служба работает"
|
||||
case us == "activating" || us == "reloading":
|
||||
case (u.State == "activating" || u.State == "active") && u.Restarts >= 3:
|
||||
it.State, it.Detail = "err", "установлен, но служба падает при запуске: "+unitFailCause(c)
|
||||
case u.State == "activating" || u.State == "reloading" || u.State == "active":
|
||||
it.State, it.Detail = "run", "установлен, служба запускается…"
|
||||
case present && c.Unit == "bj-crypto":
|
||||
it.State, it.Detail = "warn", "установлен, служба не запущена ("+us+") — обмену не мешает: пакеты для НРД подписывает шлюз"
|
||||
it.State, it.Detail = "warn", "установлен, служба не запущена ("+u.State+") — обмену не мешает: пакеты для НРД подписывает шлюз"
|
||||
case present:
|
||||
it.State, it.Detail = "ok", "установлен; служба заработает, когда модуль будет настроен (глава «Запуск»)"
|
||||
case running:
|
||||
@@ -77,6 +81,61 @@ func prepareItems(rc *RuntimeConfig, running, finished bool, runErr string) []Pr
|
||||
return out
|
||||
}
|
||||
|
||||
// unitRun — служба: состояние, сколько работает после последнего запуска, сколько раз systemd её перезапускал.
|
||||
type unitRun struct {
|
||||
State string
|
||||
Up time.Duration
|
||||
Restarts int
|
||||
}
|
||||
|
||||
func unitRunState(unit string) unitRun {
|
||||
r := unitRun{State: "unknown"}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
out, err := exec.CommandContext(ctx, "systemctl", "show", unit, "--property=ActiveState,NRestarts,ActiveEnterTimestampMonotonic").Output()
|
||||
if err != nil {
|
||||
return r
|
||||
}
|
||||
var since int64
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
k, v, _ := strings.Cut(strings.TrimSpace(line), "=")
|
||||
switch k {
|
||||
case "ActiveState":
|
||||
r.State = v
|
||||
case "NRestarts":
|
||||
r.Restarts, _ = strconv.Atoi(v)
|
||||
case "ActiveEnterTimestampMonotonic":
|
||||
since, _ = strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
}
|
||||
if b, err := os.ReadFile("/proc/uptime"); err == nil && since > 0 {
|
||||
if f := strings.Fields(string(b)); len(f) > 0 {
|
||||
if up, err := strconv.ParseFloat(f[0], 64); err == nil {
|
||||
r.Up = time.Duration(up*float64(time.Second)) - time.Duration(since)*time.Microsecond
|
||||
}
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// unitFailCause — причина падения службы модуля по последней строке её журнала ошибок — понятными словами.
|
||||
func unitFailCause(c release.Component) string {
|
||||
logs := map[string]string{"bj-crypto": "/var/log/bj/crypto-service.err", "bj-npr": "/var/log/bj/bj-npr.err", "bj-quikexport": "/var/log/bj/bj-quikexport.err"}
|
||||
b, err := os.ReadFile(logs[c.Unit])
|
||||
if err != nil {
|
||||
return "подробности — в журнале службы " + c.Unit
|
||||
}
|
||||
lines := strings.Split(strings.TrimSpace(string(b)), "\n")
|
||||
last := strings.TrimSpace(lines[len(lines)-1])
|
||||
if strings.Contains(string(b[max(0, len(b)-4000):]), "UnsupportedClassVersionError") {
|
||||
return "на сервере слишком старая Java (нужна 17 или новее): sudo apt-get install openjdk-17-jre-headless — служба запустится сама"
|
||||
}
|
||||
if len(last) > 240 {
|
||||
last = last[:240] + "…"
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
// prepareTitle — название модуля для экрана.
|
||||
func prepareTitle(c release.Component) string {
|
||||
switch c.Name {
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/release"
|
||||
)
|
||||
|
||||
// cryptoJarPath — модуль службы пробной подписи bj-crypto (компонент crypto-service.jar).
|
||||
@@ -134,10 +136,12 @@ func readinessChecks(ctx context.Context, rc *RuntimeConfig) []ReadyCheck {
|
||||
// Служба bj-crypto — пробная подпись и проверка ключа из bj; пакеты для НРД подписывает шлюз, поэтому
|
||||
// её остановка обмену не мешает. Модуль приезжает с обновлениями — до них службы нет, это не ошибка.
|
||||
if _, err := os.Stat(cryptoJarPath); err == nil {
|
||||
out, _ := exec.CommandContext(cctx, "systemctl", "is-active", "bj-crypto.service").Output()
|
||||
if svc := strings.TrimSpace(string(out)); svc != "active" {
|
||||
if u := unitRunState("bj-crypto"); !(u.State == "active" && u.Up >= 5*time.Second) {
|
||||
c.State, c.Link = "warn", "/admin/setup#sec-crypto"
|
||||
c.Detail += "; служба пробной подписи bj-crypto не запущена (" + pickStr(svc, "нет") + ") — обмену не мешает: пакеты для НРД подписывает шлюз"
|
||||
c.Detail += "; служба пробной подписи bj-crypto не работает (" + pickStr(u.State, "нет") + ") — обмену не мешает: пакеты для НРД подписывает шлюз"
|
||||
if cc, ok := release.ComponentByName("crypto-service.jar"); ok && (u.Restarts >= 3 || u.State == "failed") {
|
||||
c.Detail += ". Причина: " + unitFailCause(cc)
|
||||
}
|
||||
} else {
|
||||
c.Detail += ", служба пробной подписи bj-crypto работает"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user