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