59fc774f08
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
182 lines
9.7 KiB
Bash
Executable File
182 lines
9.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# upgrade-ish-v107.sh — полное автоматическое обновление ИШ до версии 107 на
|
|
# Astra Linux (amd64) в headless-режиме (сервер без графической сессии).
|
|
#
|
|
# ИШ 107 принёс изменения, из-за которых он «из коробки» не стартует как
|
|
# systemd-служба без графики. Этот скрипт решает ВСЕ слои (проверено 19.08.2026,
|
|
# см. память ish-v107-upgrade):
|
|
# 1. Установка .deb (dpkg).
|
|
# 2. gnome-keyring для секретов (v107 хранит пароли в OS SecretStore/libsecret).
|
|
# 3. Виртуальный дисплей Xvfb (v107 igate-svc тянет GTK/GVFS).
|
|
# 4. Параметры канала WSL для v107 (короткий URL, TLS-отпечаток GOST, DN, chain,
|
|
# M2M) — через configure-ish-v107.sql.
|
|
# 5. Самоочистка stale-состояния (ExecStartPre) — иначе рестарты флакуют.
|
|
#
|
|
# Конфигурация ИШ живёт в PostgreSQL и ПЕРЕЖИВАЕТ обновление.
|
|
#
|
|
# Использование:
|
|
# sudo ./upgrade-ish-v107.sh /путь/к/igate-107-0-930-amd64.zip
|
|
# Опционально переменные окружения:
|
|
# SVC_USER (по умолчанию igate) — пользователь службы ИШ
|
|
# IGATE_DB (по умолчанию igate) — имя БД PostgreSQL
|
|
# CHAN_ID (по умолчанию auto) — id канала в channels (auto = найти WSL)
|
|
# KEYRING_PASS_FILE (/var/lib/igate/.keyring-pass) — файл пароля keyring
|
|
#
|
|
set -euo pipefail
|
|
|
|
ZIP="${1:?укажите путь к igate-107-*-amd64.zip}"
|
|
SVC_USER="${SVC_USER:-igate}"
|
|
IGATE_DB="${IGATE_DB:-igate}"
|
|
IGATE_DIR="/opt/nsd/igate"
|
|
WRAPPER="/usr/local/bin/igate-run.sh" # вне /opt — переживает переустановку .deb
|
|
DROPIN_DIR="/etc/systemd/system/igate.service.d"
|
|
SQL_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
|
|
|
|
log(){ echo -e "\n=== $* ==="; }
|
|
[ "$(id -u)" = 0 ] || { echo "нужен root (sudo)"; exit 1; }
|
|
|
|
SVC_UID="$(id -u "$SVC_USER")"
|
|
KEYRING_PASS_FILE="${KEYRING_PASS_FILE:-/var/lib/$SVC_USER/.keyring-pass}"
|
|
HOME_DIR="$(getent passwd "$SVC_USER" | cut -d: -f6)"
|
|
|
|
log "0/9 Проверка зависимостей"
|
|
for bin in dpkg gnome-keyring-daemon dbus-run-session xvfb-run loginctl psql; do
|
|
command -v "$bin" >/dev/null || { echo "нет $bin — установите (gnome-keyring, dbus-x11, xvfb, libsecret-tools, postgresql-client)"; exit 1; }
|
|
done
|
|
echo "все зависимости на месте"
|
|
|
|
log "1/9 Распаковка дистрибутива"
|
|
unzip -o -q "$ZIP" -d "$WORK"
|
|
DEB="$(ls "$WORK"/*.deb 2>/dev/null | head -1)"
|
|
[ -n "$DEB" ] || { echo "в архиве нет .deb"; exit 1; }
|
|
echo "пакет: $(basename "$DEB") версия: $(dpkg-deb -f "$DEB" Version)"
|
|
|
|
log "2/9 Бэкап установки, конфига службы и БД"
|
|
mkdir -p "/var/backups/ish-pre107-$STAMP"
|
|
BK="/var/backups/ish-pre107-$STAMP"
|
|
[ -d "$IGATE_DIR" ] && tar czf "$BK/opt-nsd-igate.tar.gz" -C "$(dirname "$IGATE_DIR")" "$(basename "$IGATE_DIR")" 2>/dev/null || true
|
|
[ -d "$DROPIN_DIR" ] && cp -a "$DROPIN_DIR" "$BK/dropin" || true
|
|
( cd /tmp && sudo -u postgres pg_dump -d "$IGATE_DB" -Fc | cat > "$BK/igate-db.dump" ) 2>/dev/null || echo " (пропуск дампа БД)"
|
|
echo "$BK" > /var/backups/ish-last-backup.txt
|
|
echo "бэкап: $BK"
|
|
|
|
log "3/9 Остановка службы и очистка stale-состояния"
|
|
systemctl stop igate 2>/dev/null || true
|
|
pkill -9 -u "$SVC_USER" -f igate-svc 2>/dev/null || true
|
|
pkill -9 -u "$SVC_USER" -f Xvfb 2>/dev/null || true
|
|
rm -f /tmp/CoreFxPipe_NSD.IGate.* 2>/dev/null || true
|
|
|
|
log "4/9 Установка пакета (.deb)"
|
|
echo "igate igate/service boolean false" | debconf-set-selections
|
|
echo "igate igate/shortcut boolean false" | debconf-set-selections
|
|
DEBIAN_FRONTEND=noninteractive dpkg -i --force-confnew "$DEB" || apt-get -f install -y || true
|
|
echo "версия установлена: $(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null)"
|
|
|
|
log "5/9 Подготовка keyring (пароль + linger для XDG_RUNTIME_DIR)"
|
|
loginctl enable-linger "$SVC_USER"
|
|
if [ ! -f "$KEYRING_PASS_FILE" ]; then
|
|
umask 077
|
|
# локальный пароль keyring (только для сервисного хранилища секретов ИШ)
|
|
head -c 18 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20 > "$KEYRING_PASS_FILE"
|
|
chown "$SVC_USER":"$SVC_USER" "$KEYRING_PASS_FILE"; chmod 600 "$KEYRING_PASS_FILE"
|
|
echo "создан $KEYRING_PASS_FILE"
|
|
else
|
|
echo "используется существующий $KEYRING_PASS_FILE"
|
|
fi
|
|
# сбросить возможно несовместимый старый login.keyring — wrapper создаст заново
|
|
rm -f "$HOME_DIR/.local/share/keyrings/login.keyring" 2>/dev/null || true
|
|
|
|
log "6/9 Установка wrapper $WRAPPER"
|
|
cat > "$WRAPPER" <<EOF
|
|
#!/usr/bin/env bash
|
|
# headless-запуск igate-svc v107: gnome-keyring + виртуальный дисплей.
|
|
# Запускается из ExecStart через dbus-run-session (сессионная шина уже есть).
|
|
export HOME=$HOME_DIR
|
|
export XDG_DATA_HOME="\$HOME/.local/share"
|
|
export XDG_RUNTIME_DIR="/run/user/\$(id -u)"
|
|
export GIO_USE_VFS=local
|
|
eval "\$(printf '%s\n' "\$(cat $KEYRING_PASS_FILE)" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)"
|
|
export GNOME_KEYRING_CONTROL SSH_AUTH_SOCK
|
|
cd "\$HOME"
|
|
exec xvfb-run -a $IGATE_DIR/igate-svc/igate-svc
|
|
EOF
|
|
chmod +x "$WRAPPER"; echo "wrapper установлен"
|
|
|
|
log "7/9 Настройка systemd (drop-in с самоочисткой и авто-рестартом)"
|
|
mkdir -p "$DROPIN_DIR"
|
|
cat > "$DROPIN_DIR/override.conf" <<EOF
|
|
[Unit]
|
|
StartLimitIntervalSec=300
|
|
StartLimitBurst=8
|
|
|
|
[Service]
|
|
User=$SVC_USER
|
|
WorkingDirectory=$HOME_DIR
|
|
# САМООЧИСТКА stale-состояния перед стартом — иначе рестарты флакуют
|
|
# (осиротевшие CoreFxPipe-сокеты / login.keyring / X-локи).
|
|
ExecStartPre=-/bin/bash -c 'rm -f /tmp/CoreFxPipe_NSD.IGate.* $HOME_DIR/.local/share/keyrings/login.keyring; find /tmp -maxdepth 1 -name ".X9*-lock" -delete 2>/dev/null; true'
|
|
ExecStart=
|
|
ExecStart=/usr/bin/dbus-run-session -- $WRAPPER
|
|
Restart=on-failure
|
|
RestartSec=8
|
|
EOF
|
|
systemctl daemon-reload
|
|
|
|
log "8/9 Параметры канала v107 (SQL) + миграция паролей"
|
|
CHAN_ID="${CHAN_ID:-auto}"
|
|
if [ "$CHAN_ID" = auto ]; then
|
|
CHAN_ID="$(cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -tAc "select id from channels where type='WSL' order by id limit 1" 2>/dev/null | tr -d '[:space:]')"
|
|
fi
|
|
[ -n "$CHAN_ID" ] || { echo "не найден WSL-канал в channels — укажите CHAN_ID вручную"; exit 1; }
|
|
echo "канал id=$CHAN_ID"
|
|
if [ -f "$SQL_DIR/configure-ish-v107.sql" ]; then
|
|
( cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -v chan_id="$CHAN_ID" -f "$SQL_DIR/configure-ish-v107.sql" )
|
|
else
|
|
echo " ⚠️ configure-ish-v107.sql не найден рядом со скриптом — параметры канала НЕ применены"
|
|
fi
|
|
# Утилита миграции v107 (флаг миграции); финальный Console.ReadKey в headless
|
|
# безвреден — миграция сохраняется до него.
|
|
if [ -x "$IGATE_DIR/igate-mig/igate-mig" ]; then
|
|
sudo -u "$SVC_USER" bash -c '
|
|
export HOME='"$HOME_DIR"' XDG_DATA_HOME='"$HOME_DIR"'/.local/share XDG_RUNTIME_DIR=/run/user/'"$SVC_UID"'
|
|
dbus-run-session -- bash -c "
|
|
eval \$(printf %s\\\\n \"\$(cat '"$KEYRING_PASS_FILE"')\" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)
|
|
echo \"\" | timeout 30 '"$IGATE_DIR"'/igate-mig/igate-mig --data '"$HOME_DIR"' >/dev/null 2>&1 || true
|
|
"' 2>/dev/null || true
|
|
echo "igate-mig выполнен (флаг миграции)"
|
|
fi
|
|
|
|
log "9/9 Запуск и проверка"
|
|
systemctl start igate
|
|
OK=0
|
|
for i in $(seq 1 8); do
|
|
sleep 5
|
|
if ss -tlnp 2>/dev/null | grep -q ':8090'; then OK=1; break; fi
|
|
systemctl is-active --quiet igate || break
|
|
done
|
|
VER="$(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null || true)"
|
|
STATE="$(curl -s http://localhost:8090/api/admin/engine/state 2>/dev/null || true)"
|
|
echo "версия: $VER"
|
|
echo "engine/state: ${STATE:-нет ответа}"
|
|
echo "8090: $(ss -tlnp 2>/dev/null | grep -c ':8090') слушатель"
|
|
if [ "$OK" = 1 ] && [ "$STATE" = '"Running"' ]; then
|
|
echo -e "\n✅ ИШ 107 запущен и работает."
|
|
else
|
|
cat <<MSG
|
|
|
|
⚠️ Web API 8090 не поднялся. Диагностика:
|
|
• лог движка: /var/lib/$SVC_USER/.local/share/NSD Integration Gateway/logs-svc/log.txt
|
|
(искать RefreshToken/Unable to start/fingerprint/HTTP)
|
|
• если 'CA fingerprint mismatch' — сервер покажет actual-отпечаток, вписать его
|
|
в wslTlsCACertFingerprint (не перепутать контур/крипту GOST↔RSA)
|
|
• если RefreshToken пустой — проверить wslEndpoint (должен быть КОРОТКИМ базовым)
|
|
Откат на предыдущую версию:
|
|
systemctl stop igate && rm -rf $IGATE_DIR &&
|
|
tar xzf $BK/opt-nsd-igate.tar.gz -C $(dirname "$IGATE_DIR") &&
|
|
printf '[Service]\nWorkingDirectory=$HOME_DIR\n' > $DROPIN_DIR/override.conf &&
|
|
systemctl daemon-reload && systemctl start igate
|
|
MSG
|
|
fi
|