mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-19 14:23:42 +08:00
Fix static ARM builds and OpenWrt VoWiFi setup
This commit is contained in:
+197
-11
@@ -1,12 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# vocat install / update script for binary + systemd deployments.
|
||||
# vocat install / update script for systemd and OpenWrt/procd deployments.
|
||||
#
|
||||
# Usage:
|
||||
# sudo bash install.sh [version] # install a specific version
|
||||
# sudo bash install.sh # install latest release
|
||||
# sudo bash install.sh --force # reinstall even at the same version
|
||||
# curl -fsSL <raw url> | sudo bash # one-liner (latest)
|
||||
# bash install.sh [version] # run directly when already root
|
||||
# sudo bash install.sh [version] # run through sudo as a normal user
|
||||
# bash install.sh --check-env # check VoWiFi host prerequisites
|
||||
#
|
||||
# Behavior:
|
||||
# - Prompts for script language (中文 / English) as soon as it runs.
|
||||
@@ -14,7 +13,9 @@
|
||||
# - On first install, generates a random 32-char admin password, writes it to
|
||||
# /etc/vocat/env (0600, loaded by the systemd unit), and prints it ONCE.
|
||||
# - On update, preserves the existing env file and credentials.
|
||||
# - (Re)writes the systemd unit and restarts the service.
|
||||
# - Verifies Linux XFRM/IPsec support required by IMS; on OpenWrt it tries
|
||||
# the matching opkg packages first.
|
||||
# - (Re)writes a systemd or OpenWrt/procd service and restarts it.
|
||||
#
|
||||
# Published script: must contain no secrets, IPs, or passwords.
|
||||
|
||||
@@ -31,6 +32,7 @@ LINK_PATH="/usr/local/bin/vocat"
|
||||
ENV_DIR="/etc/vocat"
|
||||
ENV_FILE="${ENV_DIR}/env"
|
||||
UNIT_PATH="/etc/systemd/system/vocat.service"
|
||||
OPENWRT_INIT_PATH="/etc/init.d/vocat"
|
||||
|
||||
# --- Language ----------------------------------------------------------------
|
||||
LANG_CHOICE=""
|
||||
@@ -76,14 +78,44 @@ die() {
|
||||
|
||||
prompt_language
|
||||
|
||||
# BusyBox/OpenWrt images often omit coreutils' install(1). Provide the small
|
||||
# subset used by this script so the same installer works on router firmware.
|
||||
if ! command -v install >/dev/null 2>&1; then
|
||||
install() {
|
||||
if [ "${1:-}" = "-d" ]; then
|
||||
shift
|
||||
local mode="0755"
|
||||
if [ "${1:-}" = "-m" ]; then
|
||||
mode="$2"
|
||||
shift 2
|
||||
fi
|
||||
mkdir -p "$@"
|
||||
chmod "$mode" "$@"
|
||||
return
|
||||
fi
|
||||
local mode="0755"
|
||||
if [ "${1:-}" = "-m" ]; then
|
||||
mode="$2"
|
||||
shift 2
|
||||
fi
|
||||
[ "$#" -eq 2 ] || return 2
|
||||
cp "$1" "$2"
|
||||
chmod "$mode" "$2"
|
||||
}
|
||||
fi
|
||||
|
||||
# --- Parse args --------------------------------------------------------------
|
||||
FORCE=0
|
||||
CHECK_ENV=0
|
||||
SKIP_VOWIFI_CHECK="${VOCAT_SKIP_VOWIFI_CHECK:-0}"
|
||||
TARGET_VERSION=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--force) FORCE=1 ;;
|
||||
--check-env) CHECK_ENV=1 ;;
|
||||
--skip-vowifi-check) SKIP_VOWIFI_CHECK=1 ;;
|
||||
-h|--help)
|
||||
msg "用法: sudo bash install.sh [--force] [版本]" "Usage: sudo bash install.sh [--force] [version]"
|
||||
msg "用法: bash install.sh [--force] [--check-env] [--skip-vowifi-check] [版本]" "Usage: bash install.sh [--force] [--check-env] [--skip-vowifi-check] [version]"
|
||||
exit 0
|
||||
;;
|
||||
*) TARGET_VERSION="${arg#v}" ;;
|
||||
@@ -110,6 +142,89 @@ resolve_target_version() {
|
||||
TARGET_VERSION="${tag#v}"
|
||||
}
|
||||
|
||||
# --- Host prerequisites ------------------------------------------------------
|
||||
is_openwrt() {
|
||||
[ -f /etc/openwrt_release ] || [ -x /sbin/procd ]
|
||||
}
|
||||
|
||||
xfrm_works() {
|
||||
command -v ip >/dev/null 2>&1 && ip xfrm state list >/dev/null 2>&1
|
||||
}
|
||||
|
||||
opkg_has_package() {
|
||||
opkg list "$1" 2>/dev/null | grep -q "^$1 -"
|
||||
}
|
||||
|
||||
install_openwrt_vowifi_packages() {
|
||||
msg "正在检查 OpenWrt/Kwrt 的 VoWiFi 内核组件..." "Checking OpenWrt/Kwrt VoWiFi kernel components..."
|
||||
opkg update >/dev/null 2>&1 || msg \
|
||||
"警告:opkg 软件源更新失败,将使用现有索引继续检查。" \
|
||||
"Warning: opkg feed update failed; checking the existing index."
|
||||
|
||||
local packages=""
|
||||
local package
|
||||
for package in \
|
||||
ip-full \
|
||||
kmod-ipsec kmod-ipsec4 kmod-ipsec6 \
|
||||
kmod-crypto-authenc kmod-crypto-cbc kmod-crypto-aes \
|
||||
kmod-crypto-hmac kmod-crypto-sha1; do
|
||||
if opkg_has_package "$package"; then
|
||||
packages="$packages $package"
|
||||
fi
|
||||
done
|
||||
if [ -n "$packages" ]; then
|
||||
# Kernel packages must come from this firmware's own feed. opkg checks
|
||||
# the kernel ABI and refuses mismatched modules; never bypass that check.
|
||||
# shellcheck disable=SC2086
|
||||
opkg install $packages >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
install_linux_ip_tool() {
|
||||
command -v ip >/dev/null 2>&1 && return 0
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update -qq && apt-get install -y iproute2
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
dnf install -y iproute
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
yum install -y iproute
|
||||
elif command -v pacman >/dev/null 2>&1; then
|
||||
pacman -Sy --noconfirm iproute2
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
apk add --no-cache iproute2
|
||||
fi
|
||||
}
|
||||
|
||||
check_vowifi_environment() {
|
||||
if [ "$SKIP_VOWIFI_CHECK" = "1" ]; then
|
||||
msg \
|
||||
"已跳过 VoWiFi 内核环境检查;IMS 通话和短信可能不可用。" \
|
||||
"Skipped the VoWiFi kernel check; IMS calls and SMS may not work."
|
||||
return
|
||||
fi
|
||||
|
||||
if is_openwrt && command -v opkg >/dev/null 2>&1; then
|
||||
# Install the crypto algorithms even when NETLINK_XFRM already works;
|
||||
# some minimal images provide xfrm_user but omit AES-CBC/authenc.
|
||||
install_openwrt_vowifi_packages
|
||||
elif ! xfrm_works; then
|
||||
install_linux_ip_tool
|
||||
fi
|
||||
if xfrm_works; then
|
||||
msg "VoWiFi XFRM/IPsec 环境安装并验证成功。" "VoWiFi XFRM/IPsec environment installed and verified."
|
||||
return
|
||||
fi
|
||||
|
||||
if is_openwrt; then
|
||||
die \
|
||||
"当前 OpenWrt/Kwrt 内核 $(uname -r) 不支持 NETLINK_XFRM,且软件源没有匹配的 kmod-ipsec。请使用包含 kmod-ipsec、kmod-ipsec4、kmod-ipsec6、kmod-crypto-authenc、kmod-crypto-cbc、kmod-crypto-aes 和 kmod-crypto-sha1 的同版本固件;严禁安装其他内核版本的 kmod。仅使用非 VoWiFi 功能时可加 --skip-vowifi-check。" \
|
||||
"The OpenWrt/Kwrt kernel $(uname -r) lacks NETLINK_XFRM and its feed has no matching kmod-ipsec. Use a firmware built with matching kmod-ipsec, kmod-ipsec4/6, crypto-authenc, CBC, AES and SHA1 modules. Never force kmods from another kernel. Use --skip-vowifi-check only for non-VoWiFi operation."
|
||||
fi
|
||||
die \
|
||||
"当前 Linux 内核不支持 XFRM/IPsec,VoWiFi IMS 无法工作。请启用 CONFIG_XFRM、CONFIG_XFRM_USER、CONFIG_INET_ESP、CONFIG_INET6_ESP、AES-CBC 和 HMAC-SHA1。" \
|
||||
"This Linux kernel lacks XFRM/IPsec required by VoWiFi IMS. Enable CONFIG_XFRM, CONFIG_XFRM_USER, CONFIG_INET_ESP, CONFIG_INET6_ESP, AES-CBC and HMAC-SHA1."
|
||||
}
|
||||
|
||||
# --- Skip if already installed at the same version ---------------------------
|
||||
skip_if_equal() {
|
||||
[ -x "$BINARY_PATH" ] || return 0
|
||||
@@ -159,6 +274,10 @@ download_and_verify() {
|
||||
[ -n "$expected" ] || die "SHA256SUMS 中找不到 $asset 的校验行。" "$asset not found in SHA256SUMS."
|
||||
actual=$(sha256sum "${VOCAT_TMP}/vocat" | awk '{print $1}')
|
||||
[ "$actual" = "$expected" ] || die "SHA-256 校验失败。" "SHA-256 verification failed."
|
||||
chmod 0755 "${VOCAT_TMP}/vocat"
|
||||
"${VOCAT_TMP}/vocat" version >/dev/null 2>&1 || die \
|
||||
"Downloaded binary cannot run on this system; keeping the installed version." \
|
||||
"The downloaded binary cannot run on this host; the installed version was not changed."
|
||||
}
|
||||
|
||||
# --- Install binary ----------------------------------------------------------
|
||||
@@ -246,11 +365,73 @@ EOF
|
||||
chmod 0644 "$UNIT_PATH"
|
||||
}
|
||||
|
||||
write_openwrt_init() {
|
||||
cat > "$OPENWRT_INIT_PATH" <<'EOF'
|
||||
#!/bin/sh /etc/rc.common
|
||||
START=95
|
||||
STOP=10
|
||||
USE_PROCD=1
|
||||
PROCD_TERM_TIMEOUT=40
|
||||
PROGRAM=/opt/vocat/bin/vocat
|
||||
ENV_FILE=/etc/vocat/env
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROGRAM" serve
|
||||
procd_set_param env VOCAT_DATABASE_PATH=/opt/vocat/data/vocat.db
|
||||
if [ -r "$ENV_FILE" ]; then
|
||||
while IFS='=' read -r name value; do
|
||||
case "$name" in VOCAT_*) procd_append_param env "$name=$value" ;; esac
|
||||
done < "$ENV_FILE"
|
||||
fi
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
service_triggers() { procd_add_reload_trigger vocat; }
|
||||
EOF
|
||||
chmod 0755 "$OPENWRT_INIT_PATH"
|
||||
}
|
||||
|
||||
write_service() {
|
||||
if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
|
||||
write_unit
|
||||
return
|
||||
fi
|
||||
if [ -x /sbin/procd ] || [ -x /sbin/ubusd ]; then
|
||||
write_openwrt_init
|
||||
return
|
||||
fi
|
||||
die "Unsupported service manager." "Neither systemd nor OpenWrt procd was detected."
|
||||
}
|
||||
|
||||
enable_and_start() {
|
||||
if [ -x "$OPENWRT_INIT_PATH" ] && { [ -x /sbin/procd ] || [ -x /sbin/ubusd ]; }; then
|
||||
"$OPENWRT_INIT_PATH" enable
|
||||
if "$OPENWRT_INIT_PATH" restart; then
|
||||
sleep 2
|
||||
if "$OPENWRT_INIT_PATH" running; then
|
||||
rm -f "${BINARY_PATH}.bak"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
if [ -e "${BINARY_PATH}.bak" ]; then
|
||||
cp -a "${BINARY_PATH}.bak" "$BINARY_PATH"
|
||||
"$OPENWRT_INIT_PATH" restart || true
|
||||
fi
|
||||
die "OpenWrt vocat service failed to start." "The OpenWrt vocat service failed to start."
|
||||
fi
|
||||
systemctl daemon-reload
|
||||
systemctl enable vocat
|
||||
if systemctl restart vocat; then
|
||||
return
|
||||
local attempt
|
||||
for attempt in 1 2 3 4 5; do
|
||||
if systemctl is-active --quiet vocat; then
|
||||
rm -f "${BINARY_PATH}.bak"
|
||||
return
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
if [ -e "${BINARY_PATH}.bak" ]; then
|
||||
msg "新版本启动失败,正在恢复旧二进制。" "The new version failed to start; restoring the previous binary."
|
||||
@@ -261,14 +442,19 @@ enable_and_start() {
|
||||
}
|
||||
|
||||
# --- Main --------------------------------------------------------------------
|
||||
resolve_target_version
|
||||
detect_arch
|
||||
check_vowifi_environment
|
||||
if [ "$CHECK_ENV" -eq 1 ]; then
|
||||
msg "VoCat 运行环境检查完成。" "VoCat host environment check completed."
|
||||
exit 0
|
||||
fi
|
||||
resolve_target_version
|
||||
skip_if_equal
|
||||
download_and_verify
|
||||
install_binary
|
||||
ensure_data_dir
|
||||
setup_env
|
||||
write_unit
|
||||
write_service
|
||||
enable_and_start
|
||||
|
||||
if [ "$FIRST_INSTALL" -eq 1 ]; then
|
||||
@@ -281,7 +467,7 @@ if [ "$FIRST_INSTALL" -eq 1 ]; then
|
||||
echo
|
||||
msg "用户名为 admin。请立即记录此密码。" "Username is admin. Record this password now."
|
||||
msg "登录后或运行以下命令修改密码:" "Change it via the web UI or run:"
|
||||
echo " sudo vocat menu"
|
||||
echo " vocat menu"
|
||||
msg "==========================================" "=============================================="
|
||||
else
|
||||
echo
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=95
|
||||
STOP=10
|
||||
USE_PROCD=1
|
||||
PROCD_TERM_TIMEOUT=40
|
||||
|
||||
PROGRAM=/opt/vocat/bin/vocat
|
||||
ENV_FILE=/etc/vocat/env
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROGRAM" serve
|
||||
procd_set_param env VOCAT_DATABASE_PATH=/opt/vocat/data/vocat.db
|
||||
if [ -r "$ENV_FILE" ]; then
|
||||
while IFS='=' read -r name value; do
|
||||
case "$name" in
|
||||
VOCAT_*) procd_append_param env "$name=$value" ;;
|
||||
esac
|
||||
done < "$ENV_FILE"
|
||||
fi
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger vocat
|
||||
}
|
||||
Reference in New Issue
Block a user