Skip to Content

Скрипт обновления 1.26.10.x → 1.26.10.3

Скрипты выполняют шаги статей обновления с 1.26.10.0, 1.26.10.1 и 1.26.10.2 до 1.26.10.3: с 1.26.10.0, с 1.26.10.1, с 1.26.10.2. Скриптов два: для машины сервера и для целевых машин. Каждый сам определяет текущую версию машины, поэтому один и тот же скрипт подходит для обновления с любой из трёх версий.

Перед каждым шагом скрипт показывает, что будет сделано, и предлагает шаг пропустить. Если ввод идёт не из терминала, шаги пропускаются, а не выполняются молча.

ℹ️

Обязательные пакеты: unzip; на машине сервера – ещё acl. Необязательные: wget – для загрузки из Nexus по HTTPS, 7zip – для архивов .tar.7z. Отсутствующие пакеты можно установить из комплекта поставки согласно статье Установка пакета из комплекта поставки.

Машина сервера

Скрипт update-server-1.26.10.3.sh определяет текущую версию по тегам образов в /app/Primo.AI/Api/docker-compose.yaml и загружает только те образы, которых на машине ещё нет. Затем он обновляет Api.MachineInfo, выдаёт контейнерам права на тома, меняет теги образов в docker-compose.yaml и перезапускает компоненты. Прежний docker-compose.yaml сохраняется рядом с суффиксом .bak-<версия>.

Образы и дистрибутивы скрипт берёт на выбор: скачивает из Nexus по HTTPS, загружает образы из Docker-реестра Nexus или берёт файлы, которые уже лежат на машине, – тогда он спросит путь к каталогу. В каталоге архивы образов (<имя>.tar.7z или <имя>.tar) и Api.MachineInfo-linux.zip могут лежать вместе или в подкаталогах docker/images и linux, как в Nexus. Недостающие файлы скрипт называет до начала изменений.

  1. Сохраните скрипт в файл: выполните команду, вставьте текст скрипта из блока ниже, нажмите Enter, затем Ctrl+D.
tee update-server-1.26.10.3.sh > /dev/null
  1. Уберите пробелы и символы CR в конце строк. При копировании со страницы в пустые строки попадает пробел, а если текст побывал в Windows (Блокнот, WinSCP в текстовом режиме) – ещё и символ CR, с которым скрипт падает на первой строке с ошибкой $'\r': command not found. Без этого шага не сойдётся и контрольная сумма:
sed -i 's/[[:space:]]*$//' update-server-1.26.10.3.sh
  1. Сверьте контрольную сумму с указанной под скриптом. Не совпала – текст повреждён при копировании, скопируйте заново:
sha256sum update-server-1.26.10.3.sh
  1. Запустите скрипт от имени пользователя с правами sudo и доступом к Docker:
bash update-server-1.26.10.3.sh

После обновления убедитесь, что Центр управления доступен по HTTPS (порт 44392), и выполните повторный вход в систему.

#!/bin/bash # Обновление машины сервера AI Server 1.26.10.0 / 1.26.10.1 / 1.26.10.2 -> 1.26.10.3 set -euo pipefail NEXUS_RAW=https://nexus.primo-rpa.ru/repository/raw/1.26.10/ai-server REGISTRY=nexus.primo-rpa.ru:8000/primo-rpa COMPOSE=/app/Primo.AI/Api/docker-compose.yaml VOLUMES=/app/Primo.AI/Api/volumes MACHINEINFO_DIR=/app/Primo.AI/Api.MachineInfo # Образы машины сервера и их теги в версии 1.26.10.3 IMAGES="ai-server-api:1.26.10.3 ai-server-auth:1.26.10.3 ai-server-inference:1.26.10.3 ai-server-logs:1.26.10.3 ai-server-machineinfo:1.26.10.3 ai-server-ui:1.26.10.2 ai-server-langflow-frontend:1.26.10.2 ai-server-langflow-backend:1.26.10.1" fail() { echo "Ошибка: $*" >&2; exit 1; } need() { command -v "$1" >/dev/null 2>&1 || fail "не найдена команда $1 – установите пакет $2"; } # Показывает, что будет сделано на шаге, и предлагает его пропустить step() { local title=$1 a shift echo echo "=== $title" printf ' %s\n' "$@" read -r -p "Выполнить шаг? [Y/n] " a || { echo; echo "Нет ответа – шаг пропущен"; return 1; } case "$a" in n|N) echo "Шаг пропущен"; return 1 ;; esac } # Файл на машине: в указанном каталоге или в его подкаталогах с раскладкой Nexus find_local() { local f for f in "$src/$1" "$src/docker/images/$1" "$src/linux/$1" "$src/ai-server/docker/images/$1" "$src/ai-server/linux/$1"; do [ -f "$f" ] && { echo "$f"; return 0; } done return 1 } # Откуда возьмётся образ: для варианта 3 – путь к архиву .tar или .tar.7z image_source() { local name=${1%%:*} case "$method" in 1) echo "$NEXUS_RAW/docker/images/$name.tar.7z" ;; 2) echo "$REGISTRY/$1" ;; 3) find_local "$name.tar" || find_local "$name.tar.7z" ;; esac } # Откуда возьмётся дистрибутив: $1 – имя файла, $2 – подкаталог в Nexus file_source() { if [ "$method" = "3" ]; then find_local "$1"; else echo "$NEXUS_RAW/$2/$1"; fi } load_image() { local item=$1 name=${1%%:*} from from=$(image_source "$item") case "$from" in http*) wget -nv -O "$work/$name.tar.7z" "$from" from=$work/$name.tar.7z ;; esac case "$from" in "$REGISTRY"/*) docker pull "$from" ;; *.tar.7z) 7z x -y -o"$work" "$from" >/dev/null [ "$from" = "$work/$name.tar.7z" ] && rm -f "$from" docker load -i "$work/$name.tar" rm -f "$work/$name.tar" ;; *.tar) docker load -i "$from" ;; esac docker image inspect "$REGISTRY/$item" >/dev/null 2>&1 || fail "после загрузки на машине нет образа $REGISTRY/$item" } # Путь к дистрибутиву на машине; из Nexus файл скачивается во временный каталог get_file() { local from from=$(file_source "$1" "$2") case "$from" in http*) wget -nv -O "$work/$1" "$from" >&2; echo "$work/$1" ;; *) echo "$from" ;; esac } [ -f "$COMPOSE" ] || fail "не найден $COMPOSE – скрипт выполняется на машине сервера" # Текущая версия – старший тег 1.26.10.x среди образов AI Server в docker-compose.yaml current=$(grep -oE 'primo-rpa/ai-server-[a-z-]+:1\.26\.10\.[0-9]+' "$COMPOSE" | grep -oE '[0-9]+$' | sort -n | tail -n 1 || true) [ -n "$current" ] || fail "в $COMPOSE нет образов AI Server 1.26.10.x. Скрипт обновляет только версии 1.26.10.x, для других версий используйте статью обновления своей версии" if [ "$current" -ge 3 ]; then echo "Машина сервера уже на версии 1.26.10.$current, обновление не требуется" exit 0 fi echo "Текущая версия машины сервера: 1.26.10.$current" echo echo "Откуда брать образы и дистрибутивы?" echo " 1 – скачать архивы из Nexus по HTTPS (https://nexus.primo-rpa.ru, порт 443)" echo " 2 – образы из Docker-реестра Nexus (nexus.primo-rpa.ru:8000), дистрибутивы из Nexus по HTTPS" echo " 3 – файлы уже лежат на этой машине" read -r -p "Вариант [1]: " method || fail "нет ответа" method=${method:-1} case "$method" in 1|2|3) ;; *) fail "неизвестный вариант: $method" ;; esac src="" if [ "$method" = "3" ]; then echo "Нужны архивы образов <имя>.tar.7z или <имя>.tar и Api.MachineInfo-linux.zip – в одном каталоге" echo "или в подкаталогах docker/images и linux, как в Nexus." read -r -p "Каталог с файлами: " src || fail "нет ответа" src=${src%/} [ -d "$src" ] || fail "каталог $src не найден" fi need docker docker need unzip unzip need setfacl acl [ "$method" = "3" ] || need wget wget # Загружаются только образы, которых ещё нет на машине с нужным тегом missing="" for item in $IMAGES; do docker image inspect "$REGISTRY/$item" >/dev/null 2>&1 || missing="$missing $item" done # Все источники проверяются до начала изменений absent="" for item in $missing; do from=$(image_source "$item") || { absent="$absent ${item%%:*}.tar.7z"; continue; } case "$from" in *.7z) need 7z 7zip ;; esac done file_source Api.MachineInfo-linux.zip linux >/dev/null || absent="$absent Api.MachineInfo-linux.zip" [ -z "$absent" ] || fail "в каталоге $src нет файлов:$absent" work=$(mktemp -d "$PWD/ai-server-update.XXXXXX") trap 'rm -rf "$work"' EXIT h=$(getent passwd primo | cut -d: -f6 || true) if [ -n "$h" ] && [ ! -d "$h" ] && step "Домашний каталог пользователя primo" \ "У пользователя primo, от имени которого работает Api.MachineInfo, нет домашнего каталога." \ "Будет создан каталог $h"; then sudo install -d -m 700 -o primo -g "$(id -gn primo)" "$h" fi if [ -z "$missing" ]; then echo echo "=== Загрузка образов" echo " Все образы 1.26.10.3 уже есть на машине, загружать нечего." else plan=() for item in $missing; do if [ "$method" = "2" ]; then plan+=("docker pull $REGISTRY/$item"); else plan+=("$REGISTRY/$item <- $(image_source "$item")"); fi done if step "Загрузка образов" "${plan[@]}"; then for item in $missing; do load_image "$item"; done fi fi if step "Обновление Api.MachineInfo" \ "Источник: $(file_source Api.MachineInfo-linux.zip linux)" \ "Служба Primo.AI.Api.MachineInfo будет остановлена, файлы распакованы в $MACHINEINFO_DIR" \ "без appsettings* (конфигурация сохраняется), служба будет запущена снова"; then zip=$(get_file Api.MachineInfo-linux.zip linux) sudo systemctl stop Primo.AI.Api.MachineInfo sudo unzip -o -q "$zip" -x "appsettings*" -d "$MACHINEINFO_DIR/" sudo chmod +x "$MACHINEINFO_DIR/Primo.AI.Api.MachineInfo" sudo chown primo:primo-ai "$MACHINEINFO_DIR/" sudo systemctl start Primo.AI.Api.MachineInfo fi if step "Права контейнеров на тома" \ "В $VOLUMES будут созданы недостающие каталоги томов и выданы права через ACL:" \ "UID 1001 (Api, Auth, Inference, Logs) – conf, Api_*, Logs; UID 1000 (nginx, Конструктор агентских систем) – nginx, langflow_data"; then sudo mkdir -p "$VOLUMES/Api_Models" "$VOLUMES/Api_ContextFiles" "$VOLUMES/Api_LangflowScriptPreset" \ "$VOLUMES/Api_SmartOcrTestFile" "$VOLUMES/Api_TestPackage" \ "$VOLUMES/Logs/Api" "$VOLUMES/Logs/Api.Auth" "$VOLUMES/Logs/Api.Inference" "$VOLUMES/Logs/Api.Logs" \ "$VOLUMES/langflow_data/logs" for dir in conf Api_Models Api_ContextFiles Api_LangflowScriptPreset Api_SmartOcrTestFile Api_TestPackage Logs; do sudo setfacl -R -m u:1001:rwX "$VOLUMES/$dir" sudo find "$VOLUMES/$dir" -type d -exec setfacl -d -m u:1001:rwX {} + done for dir in nginx langflow_data; do sudo setfacl -R -m u:1000:rwX "$VOLUMES/$dir" sudo find "$VOLUMES/$dir" -type d -exec setfacl -d -m u:1000:rwX {} + done fi if step "Обновление docker-compose.yaml" \ "Прежний файл будет сохранён как $COMPOSE.bak-1.26.10.$current, теги образов в $COMPOSE станут такими:" \ "ai-server-api, -auth, -inference, -logs – 1.26.10.3; ai-server-ui, -langflow-frontend – 1.26.10.2; ai-server-langflow-backend – 1.26.10.1"; then sudo cp -p "$COMPOSE" "$COMPOSE.bak-1.26.10.$current" sudo sed -i -E \ -e 's#(image:[[:space:]]+nexus\.primo-rpa\.ru:8000/primo-rpa/ai-server-(api|auth|inference|logs)):1\.26\.10\.[0-2]#\1:1.26.10.3#' \ -e 's#(image:[[:space:]]+nexus\.primo-rpa\.ru:8000/primo-rpa/ai-server-(ui|langflow-frontend)):1\.26\.10\.[01]#\1:1.26.10.2#' \ -e 's#(image:[[:space:]]+nexus\.primo-rpa\.ru:8000/primo-rpa/ai-server-langflow-backend):1\.26\.10\.0#\1:1.26.10.1#' \ "$COMPOSE" for item in $IMAGES; do case "$item" in ai-server-machineinfo:*) continue ;; esac grep -qE "primo-rpa/$item([[:space:]]|\$)" "$COMPOSE" || fail "в $COMPOSE не найден образ $item. Прежний файл сохранён как $COMPOSE.bak-1.26.10.$current" done fi if step "Перезапуск компонентов" \ "docker compose -f $COMPOSE down, затем up -d"; then docker compose -f "$COMPOSE" down docker compose -f "$COMPOSE" up -d fi echo echo "Готово. Убедитесь, что Центр управления доступен по HTTPS (порт 44392), и выполните повторный вход в систему."

Контрольная сумма update-server-1.26.10.3.sh (SHA-256): 69fb1d90df018a0be24bb958d76abda11fc025b0d910d24de3bd4ed470386948

Целевые машины

⚠️

Перед запуском скрипта остановите все процессы целевой машины через Центр управления (UI).

Скрипт update-target-1.26.10.3.sh определяет версию по тегам образов в конфигурации агента /app/Primo.AI/Agent/appsettings.ProdLinux.json и загружает новые версии только тех образов серверов, которые уже есть на машине, – отвечать, какие серверы на ней работают, не нужно. Затем он обновляет файлы агента, теги образов в его конфигурации и перезапускает агента. Прежняя конфигурация агента сохраняется рядом с суффиксом .bak-<версия>. Если в конфигурации нет параметра vLLM AdditionalArgs, скрипт подскажет, как добавить его вручную, и дождётся этого.

Образы и дистрибутивы скрипт берёт на выбор: скачивает из Nexus по HTTPS, загружает образы из Docker-реестра Nexus или берёт файлы, которые уже лежат на машине, – тогда он спросит путь к каталогу. В каталоге архивы образов (<имя>.tar.7z или <имя>.tar) и Agent-linux.zip могут лежать вместе или в подкаталогах docker/images и linux, как в Nexus. Недостающие файлы скрипт называет до начала изменений.

  1. Сохраните скрипт в файл: выполните команду, вставьте текст скрипта из блока ниже, нажмите Enter, затем Ctrl+D.
tee update-target-1.26.10.3.sh > /dev/null
  1. Уберите пробелы и символы CR в конце строк. При копировании со страницы в пустые строки попадает пробел, а если текст побывал в Windows (Блокнот, WinSCP в текстовом режиме) – ещё и символ CR, с которым скрипт падает на первой строке с ошибкой $'\r': command not found. Без этого шага не сойдётся и контрольная сумма:
sed -i 's/[[:space:]]*$//' update-target-1.26.10.3.sh
  1. Сверьте контрольную сумму с указанной под скриптом. Не совпала – текст повреждён при копировании, скопируйте заново:
sha256sum update-target-1.26.10.3.sh
  1. Запустите скрипт от имени пользователя с правами sudo и доступом к Docker:
bash update-target-1.26.10.3.sh
#!/bin/bash # Обновление целевой машины AI Server 1.26.10.0 / 1.26.10.1 / 1.26.10.2 -> 1.26.10.3 set -euo pipefail NEXUS_RAW=https://nexus.primo-rpa.ru/repository/raw/1.26.10/ai-server REGISTRY=nexus.primo-rpa.ru:8000/primo-rpa AGENT_DIR=/app/Primo.AI/Agent CONFIG=$AGENT_DIR/appsettings.ProdLinux.json # Образы серверов целевой машины и их теги в версии 1.26.10.3 IMAGES="ai-server-nlp:1.26.10.2 ai-server-idp-cpu:1.26.10.2 ai-server-idp-gpu:1.26.10.2 ai-server-rag-gpu:1.26.10.2 ai-server-ft:1.26.10.2 ai-server-sdc:1.26.10.2 ai-server-ollama:1.26.10.2 ai-server-langflow-backend:1.26.10.1" fail() { echo "Ошибка: $*" >&2; exit 1; } ask() { local a; read -r -p "$1 [y/n] " a; [ "$a" = "y" ] || [ "$a" = "Y" ]; } need() { command -v "$1" >/dev/null 2>&1 || fail "не найдена команда $1 – установите пакет $2"; } # Показывает, что будет сделано на шаге, и предлагает его пропустить step() { local title=$1 a shift echo echo "=== $title" printf ' %s\n' "$@" read -r -p "Выполнить шаг? [Y/n] " a || { echo; echo "Нет ответа – шаг пропущен"; return 1; } case "$a" in n|N) echo "Шаг пропущен"; return 1 ;; esac } # Файл на машине: в указанном каталоге или в его подкаталогах с раскладкой Nexus find_local() { local f for f in "$src/$1" "$src/docker/images/$1" "$src/linux/$1" "$src/ai-server/docker/images/$1" "$src/ai-server/linux/$1"; do [ -f "$f" ] && { echo "$f"; return 0; } done return 1 } # Откуда возьмётся образ: для варианта 3 – путь к архиву .tar или .tar.7z image_source() { local name=${1%%:*} case "$method" in 1) echo "$NEXUS_RAW/docker/images/$name.tar.7z" ;; 2) echo "$REGISTRY/$1" ;; 3) find_local "$name.tar" || find_local "$name.tar.7z" ;; esac } # Откуда возьмётся дистрибутив: $1 – имя файла, $2 – подкаталог в Nexus file_source() { if [ "$method" = "3" ]; then find_local "$1"; else echo "$NEXUS_RAW/$2/$1"; fi } load_image() { local item=$1 name=${1%%:*} from from=$(image_source "$item") case "$from" in http*) wget -nv -O "$work/$name.tar.7z" "$from" from=$work/$name.tar.7z ;; esac case "$from" in "$REGISTRY"/*) docker pull "$from" ;; *.tar.7z) 7z x -y -o"$work" "$from" >/dev/null [ "$from" = "$work/$name.tar.7z" ] && rm -f "$from" docker load -i "$work/$name.tar" rm -f "$work/$name.tar" ;; *.tar) docker load -i "$from" ;; esac docker image inspect "$REGISTRY/$item" >/dev/null 2>&1 || fail "после загрузки на машине нет образа $REGISTRY/$item" } # Путь к дистрибутиву на машине; из Nexus файл скачивается во временный каталог get_file() { local from from=$(file_source "$1" "$2") case "$from" in http*) wget -nv -O "$work/$1" "$from" >&2; echo "$work/$1" ;; *) echo "$from" ;; esac } [ -f "$CONFIG" ] || fail "не найден $CONFIG – скрипт выполняется на целевой машине" # Текущая версия – старший тег 1.26.10.x среди образов серверов в конфигурации агента names=$(for item in $IMAGES; do printf '%s|' "${item%%:*}"; done) current=$(grep -oE "primo-rpa/(${names%|}):1\.26\.10\.[0-9]+" "$CONFIG" | grep -oE '[0-9]+$' | sort -n | tail -n 1 || true) [ -n "$current" ] || fail "в $CONFIG нет образов AI Server 1.26.10.x. Скрипт обновляет только версии 1.26.10.x, для других версий используйте статью обновления своей версии" echo "Версия образов в конфигурации агента: 1.26.10.$current" echo echo "Откуда брать образы и дистрибутивы?" echo " 1 – скачать архивы из Nexus по HTTPS (https://nexus.primo-rpa.ru, порт 443)" echo " 2 – образы из Docker-реестра Nexus (nexus.primo-rpa.ru:8000), дистрибутивы из Nexus по HTTPS" echo " 3 – файлы уже лежат на этой машине" read -r -p "Вариант [1]: " method || fail "нет ответа" method=${method:-1} case "$method" in 1|2|3) ;; *) fail "неизвестный вариант: $method" ;; esac src="" if [ "$method" = "3" ]; then echo "Нужны архивы образов <имя>.tar.7z или <имя>.tar и Agent-linux.zip – в одном каталоге" echo "или в подкаталогах docker/images и linux, как в Nexus." read -r -p "Каталог с файлами: " src || fail "нет ответа" src=${src%/} [ -d "$src" ] || fail "каталог $src не найден" fi need docker docker need unzip unzip [ "$method" = "3" ] || need wget wget # Обновляются образы тех серверов, которые уже загружены на машину в версии 1.26.10.x missing="" for item in $IMAGES; do name=${item%%:*} docker image inspect "$REGISTRY/$item" >/dev/null 2>&1 && continue docker image ls --format '{{.Tag}}' "$REGISTRY/$name" | grep -q '^1\.26\.10\.' && missing="$missing $item" done # Все источники проверяются до начала изменений absent="" for item in $missing; do from=$(image_source "$item") || { absent="$absent ${item%%:*}.tar.7z"; continue; } case "$from" in *.7z) need 7z 7zip ;; esac done file_source Agent-linux.zip linux >/dev/null || absent="$absent Agent-linux.zip" [ -z "$absent" ] || fail "в каталоге $src нет файлов:$absent" echo echo "Перед обновлением остановите все процессы этой машины через Центр управления (UI)." ask "Процессы остановлены, продолжить?" || exit 0 work=$(mktemp -d "$PWD/ai-server-update.XXXXXX") trap 'rm -rf "$work"' EXIT h=$(getent passwd agent | cut -d: -f6 || true) if [ -n "$h" ] && [ ! -d "$h" ] && step "Домашний каталог пользователя agent" \ "У пользователя agent, от имени которого работает агент, нет домашнего каталога." \ "Будет создан каталог $h"; then sudo install -d -m 700 -o agent -g "$(id -gn agent)" "$h" fi if [ -z "$missing" ]; then echo echo "=== Загрузка образов" echo " Образы серверов на машине уже актуальны, загружать нечего." else plan=() for item in $missing; do if [ "$method" = "2" ]; then plan+=("docker pull $REGISTRY/$item"); else plan+=("$REGISTRY/$item <- $(image_source "$item")"); fi done if step "Загрузка образов" "${plan[@]}"; then for item in $missing; do load_image "$item"; done fi fi if step "Обновление файлов агента" \ "Источник: $(file_source Agent-linux.zip linux)" \ "Служба Primo.AI.Agent будет остановлена, файлы распакованы в $AGENT_DIR" \ "без appsettings* (конфигурация сохраняется); агент запустится на шаге «Перезапуск агента»"; then zip=$(get_file Agent-linux.zip linux) sudo systemctl stop Primo.AI.Agent sudo unzip -o -q "$zip" -x "appsettings*" -d "$AGENT_DIR/" sudo chmod +x "$AGENT_DIR/Primo.AI.Agent" sudo chown -R agent:primo-ai "$AGENT_DIR/" fi if step "Обновление конфигурации агента" \ "Прежний файл будет сохранён как $CONFIG.bak-1.26.10.$current, теги образов в $CONFIG станут такими:" \ "ai-server-nlp, -idp-cpu, -idp-gpu, -rag-gpu, -ft, -sdc, -ollama – 1.26.10.2; ai-server-langflow-backend – 1.26.10.1"; then sudo cp -p "$CONFIG" "$CONFIG.bak-1.26.10.$current" sudo sed -i -E \ -e 's#(nexus\.primo-rpa\.ru:8000/primo-rpa/ai-server-(nlp|idp-cpu|idp-gpu|rag-gpu|ft|sdc|ollama)):1\.26\.10\.[01]"#\1:1.26.10.2"#' \ -e 's#(nexus\.primo-rpa\.ru:8000/primo-rpa/ai-server-langflow-backend):1\.26\.10\.0"#\1:1.26.10.1"#' \ "$CONFIG" fi if ! grep -q 'max-num-seqs' "$CONFIG" && step "Параметр vLLM AdditionalArgs" \ "В конфигурации агента нет параметра AdditionalArgs у vLLM. Без него гибридные модели с Mamba-слоями" \ "(Qwen3.6 и др.) на vLLM не запускаются. Если vLLM на машине не используется, шаг можно пропустить." \ "Параметр добавляется вручную: в $CONFIG в секции LlmEngineProcess -> EnginesDockerRun -> Vllm" \ "после \"ExposePort\": true допишите (с запятой после true): \"AdditionalArgs\": [ \"--max-num-seqs 128\" ]"; then read -r -p "Добавьте параметр в другом окне терминала и нажмите Enter: " _ grep -q 'max-num-seqs' "$CONFIG" || echo "Внимание: параметр --max-num-seqs в $CONFIG не найден" fi if step "Перезапуск агента" \ "sudo systemctl restart Primo.AI.Agent"; then sudo systemctl restart Primo.AI.Agent fi echo echo "Готово."

Контрольная сумма update-target-1.26.10.3.sh (SHA-256): 3e654b04af99faca99b57ae65d874d1c0986465cc9f92d45ffea3234014bcb6a

Что дальше

После обновления всех машин выполните проверку работоспособности системы.