fix(deploy): надёжный рендер шаблонов и устойчивый цикл подстановки
- render_template: значения передаются через окружение (envsubst), а не
подставляются в variadic-аргументы — многострочные значения больше не
ломают разбор, неполный список не уводит bash в бесконечный цикл
- export "$pair": bash сам разбирает KEY=value (было export "${pair}")
- шаблоны переведены на ${VAR}-синтаксис, добавлен compose.test.yaml.tpl
для тестового режима установщика (--skip-tls без публикации портов)
- dry-run не требует root и работает вне Linux (проверка ОС пропускается)
- install.sh: учитываются --livekit-*-порты и --turn-*-порты в livekit.yaml,
исправлено экранирование апострофа в итоговой сводке
- scripts/debug-install.sh: трассировка установщика в контейнере
This commit is contained in:
+71
-14
@@ -41,6 +41,11 @@ die() {
|
||||
}
|
||||
|
||||
need_root() {
|
||||
# В режиме --dry-run изменения не применяются, поэтому root не требуется:
|
||||
# это позволяет проверять установщик на машине разработчика.
|
||||
if [ "${DRY_RUN:-0}" = "1" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
die "запустите установщик от root: sudo bash deploy/install.sh"
|
||||
fi
|
||||
@@ -145,8 +150,8 @@ profile_values() {
|
||||
PROFILE_SWAP_GB=2 PROFILE_BACKUP_KEEP=30 PROFILE_SHARE_SOFT=4K/30 PROFILE_SHARE_MAX=4K/60
|
||||
;;
|
||||
pro)
|
||||
PROFILE_SQLITE_CACHE_MB=64 PROFILE_SQLITE_MMAP_MB=1024 PROFILE_SQLITE_READ_POOL="$(nproc)"
|
||||
PROFILE_GOMAXPROCS="$(nproc)" PROFILE_LRU_ENTRIES=200000
|
||||
PROFILE_SQLITE_CACHE_MB=64 PROFILE_SQLITE_MMAP_MB=1024 PROFILE_SQLITE_READ_POOL="$(detect_cpus)"
|
||||
PROFILE_GOMAXPROCS="$(detect_cpus)" PROFILE_LRU_ENTRIES=200000
|
||||
PROFILE_LIVEKIT_MAX_PARTICIPANTS=100 PROFILE_LIVEKIT_MAX_VIDEO=32 PROFILE_LIVEKIT_SIMULCAST=3
|
||||
PROFILE_UPLOAD_MB=250 PROFILE_APP_LIMIT=4g PROFILE_LIVEKIT_LIMIT=6g
|
||||
PROFILE_SWAP_GB=0 PROFILE_BACKUP_KEEP=60 PROFILE_SHARE_SOFT=4K/60 PROFILE_SHARE_MAX=4K/60
|
||||
@@ -164,8 +169,12 @@ profile_values() {
|
||||
|
||||
detect_profile() {
|
||||
local cpus ram_mb
|
||||
cpus="$(nproc)"
|
||||
ram_mb="$(awk '/MemTotal/ {printf "%d", $2/1024}' /proc/meminfo)"
|
||||
cpus="$(detect_cpus)"
|
||||
if [ -r /proc/meminfo ]; then
|
||||
ram_mb="$(awk '/MemTotal/ {printf "%d", $2/1024}' /proc/meminfo)"
|
||||
else
|
||||
ram_mb=4096
|
||||
fi
|
||||
if [ "$cpus" -le 1 ] && [ "$ram_mb" -lt 3072 ]; then
|
||||
printf 'lite'
|
||||
elif [ "$cpus" -le 2 ] || [ "$ram_mb" -lt 5120 ]; then
|
||||
@@ -179,19 +188,45 @@ detect_profile() {
|
||||
|
||||
# --- рендеринг шаблонов ---------------------------------------------------
|
||||
|
||||
# render_template src dst KEY=value...
|
||||
#
|
||||
# Значения передаются через окружение, а не подставляются в аргументы: это
|
||||
# исключает разбор значений с пробелами и переносами строк и делает рендер
|
||||
# предсказуемым (bash ${var//pat/repl} на многострочных значениях и variadic
|
||||
# аргументах ведёт себя неочевидно). Если gettext-base (envsubst) недоступен,
|
||||
# используется эквивалентная замена средствами bash.
|
||||
render_template() {
|
||||
local src="$1" dst="$2"
|
||||
shift 2
|
||||
local content
|
||||
content="$(cat "$src")"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
local key="${1%%=*}" value="${1#*=}"
|
||||
content="${content//"{{${key}}}"/$value}"
|
||||
# Нечётное число аргументов означает, что вызов неполный: сообщаем об этом,
|
||||
# но продолжаем — значения, которые всё же переданы, будут применены,
|
||||
# а незаполненные плейсхолдеры видны в предупреждении ниже.
|
||||
if [ $(( $# % 2 )) -ne 0 ]; then
|
||||
warn "render_template($(basename "$src")): нечётное число аргументов: $#"
|
||||
fi
|
||||
|
||||
# export "$pair" разбирает KEY=value сам; export "${pair}" трактует всю
|
||||
# пару как имя переменной — из-за этого значения не попадали в окружение.
|
||||
local pair
|
||||
for pair in "$@"; do
|
||||
export "$pair"
|
||||
done
|
||||
|
||||
local content
|
||||
if command -v envsubst >/dev/null 2>&1; then
|
||||
content="$(envsubst <"$src")"
|
||||
else
|
||||
content="$(cat "$src")"
|
||||
for pair in "$@"; do
|
||||
local key="${pair%%=*}" value="${pair#*=}"
|
||||
content="${content//"{{${key}}}"/$value}"
|
||||
done
|
||||
fi
|
||||
|
||||
if printf '%s' "$content" | grep -q '{{[A-Z_]\{2,\}}}'; then
|
||||
local leftover
|
||||
leftover="$(printf '%s' "$content" | grep -o '{{[A-Z_]\{2,\}}}' | sort -u | tr '\n' ' ')"
|
||||
warn "в шаблоне $src остались незаполненные плейсхолдеры: $leftover"
|
||||
warn "в шаблоне $(basename "$src") остались незаполненные плейсхолдеры: $leftover"
|
||||
fi
|
||||
printf '%s\n' "$content" >"$dst"
|
||||
}
|
||||
@@ -218,7 +253,14 @@ env_set() {
|
||||
# --- общие проверки -------------------------------------------------------
|
||||
|
||||
check_os() {
|
||||
[ -r /etc/os-release ] || die "не удалось прочитать /etc/os-release"
|
||||
if [ ! -r /etc/os-release ]; then
|
||||
# macOS и другие не-Linux системы: допустимо только для --dry-run.
|
||||
if [ "${DRY_RUN:-0}" = "1" ]; then
|
||||
warn "не Linux (нет /etc/os-release): проверка ОС пропущена в режиме --dry-run"
|
||||
return 0
|
||||
fi
|
||||
die "не удалось прочитать /etc/os-release"
|
||||
fi
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/os-release
|
||||
case "${ID:-}" in
|
||||
@@ -243,11 +285,15 @@ check_os() {
|
||||
|
||||
check_resources() {
|
||||
local cpus ram_mb disk_mb
|
||||
cpus="$(nproc)"
|
||||
ram_mb="$(awk '/MemTotal/ {printf "%d", $2/1024}' /proc/meminfo)"
|
||||
cpus="$(detect_cpus)"
|
||||
if [ -r /proc/meminfo ]; then
|
||||
ram_mb="$(awk '/MemTotal/ {printf "%d", $2/1024}' /proc/meminfo)"
|
||||
else
|
||||
ram_mb=0
|
||||
fi
|
||||
disk_mb="$(df -Pm / | awk 'NR==2 {print $4}')"
|
||||
info "ресурсы: ${cpus} vCPU, ${ram_mb} MB RAM, ${disk_mb} MB свободно на /"
|
||||
if [ "$ram_mb" -lt 1800 ]; then
|
||||
if [ "$ram_mb" -gt 0 ] && [ "$ram_mb" -lt 1800 ]; then
|
||||
warn "меньше 2 GB RAM: профиль lite может не уложиться в бюджет (AGENT.md 9.1)"
|
||||
fi
|
||||
if [ "$disk_mb" -lt 8000 ]; then
|
||||
@@ -255,6 +301,17 @@ check_resources() {
|
||||
fi
|
||||
}
|
||||
|
||||
detect_cpus() {
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
nproc
|
||||
return
|
||||
fi
|
||||
if command -v sysctl >/dev/null 2>&1; then
|
||||
sysctl -n hw.ncpu 2>/dev/null && return
|
||||
fi
|
||||
printf '2'
|
||||
}
|
||||
|
||||
check_command() {
|
||||
have "$1" && ok "найдено: $1" || warn "отсутствует: $1 (будет установлено)"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user