Files
small-packages/honk/files/honk.init
T
2026-11-08 19:04:57 +08:00

95 lines
4.4 KiB
Bash
Executable File

#!/bin/sh /etc/rc.common
USE_PROCD=1
START=95
STOP=10
. /lib/functions.sh
HONK_CONTROL=/usr/share/honk/control.sh
HONK_CONFIG=/etc/honk/config.dae
boot() {
# 开机自启内置:只要服务是"已启用 + 已初始化"就起来,
# 用户主动停掉(enabled=0)后重启也不会被强行拉起。
start
}
start_service() {
local enabled initialized config_file ready_token ready_hash ready_runtime ready_api_enabled ready_api_listen ready_clash_api_listen ready_clash_api_secret_set old_ready_token
config_load honk
config_get_bool enabled main enabled 0
config_get_bool initialized main initialized 0
[ "$enabled" -eq 1 ] && [ "$initialized" -eq 1 ] || {
logger -t honk "refusing to start before explicit initialization and enablement"
return 1
}
config_get config_file main config_file "$HONK_CONFIG"
[ "$config_file" = "$HONK_CONFIG" ] || {
logger -t honk "refusing non-default config path"
return 1
}
"$HONK_CONTROL" preflight || return 1
"$HONK_CONTROL" local-direct || logger -t honk "local-direct sync skipped"
unset HONK_MAINT_CAP
# 所有配置都走 readiness 标记:状态页据此判断真正就绪,而不是只看进程在不在。
ready_token=$(cat /proc/sys/kernel/random/uuid 2>/dev/null) || return 1
case "$ready_token" in *[!0-9a-f-]*|'') return 1 ;; esac
ready_hash=$(sha256sum "$HONK_CONFIG" 2>/dev/null | awk '{print $1}') || return 1
case "$ready_hash" in *[!0-9a-f]*|'') return 1 ;; esac
ready_runtime=$(/usr/bin/honk-core config validate --config "$HONK_CONFIG" 2>/dev/null) || return 1
ready_api_enabled=$(printf '%s' "$ready_runtime" | jsonfilter -e '@.runtime.native_api_enabled' 2>/dev/null)
ready_api_listen=$(printf '%s' "$ready_runtime" | jsonfilter -e '@.runtime.native_api_listen' 2>/dev/null)
ready_clash_api_listen=$(printf '%s' "$ready_runtime" | jsonfilter -e '@.runtime.clash_api_listen' 2>/dev/null)
ready_clash_api_secret_set=$(printf '%s' "$ready_runtime" | jsonfilter -e '@.runtime.clash_api_secret_set' 2>/dev/null)
case "$ready_api_enabled" in true|false) ;; *) return 1 ;; esac
case "$ready_api_listen" in *[!A-Za-z0-9:._-]*) return 1 ;; esac
case "$ready_clash_api_listen" in *[!A-Za-z0-9:._-]*) return 1 ;; esac
case "$ready_clash_api_secret_set" in true|false) ;; *) return 1 ;; esac
mkdir -p /var/run/honk || return 1
chmod 0700 /var/run/honk || return 1
if [ -f /var/run/honk/readiness ] && [ ! -L /var/run/honk/readiness ]; then
read -r old_ready_token _ < /var/run/honk/readiness
case "$old_ready_token" in ''|*[!0-9a-f-]*) ;; *) rm -f "/var/run/honk/core-ready-$old_ready_token" ;; esac
fi
printf '%s %s\n' "$ready_token" "$ready_hash" > /var/run/honk/readiness || return 1
chmod 0600 /var/run/honk/readiness || return 1
procd_open_instance main
procd_set_param command /usr/bin/honk-core --config "$HONK_CONFIG" --disable-timestamp
# One env call, no empty values: procd drops the whole list when a KEY has an
# empty value, which silently stripped the readiness hash the core requires.
ready_env="DAE_LOCATION_ASSET=/usr/share/v2ray"
ready_env="$ready_env HONK_READY_TOKEN=$ready_token HONK_READY_CONFIG_HASH=$ready_hash HONK_READY_API_ENABLED=$ready_api_enabled HONK_READY_CLASH_API_SECRET_SET=$ready_clash_api_secret_set"
[ -n "$ready_api_listen" ] && ready_env="$ready_env HONK_READY_API_LISTEN=$ready_api_listen"
[ -n "$ready_clash_api_listen" ] && ready_env="$ready_env HONK_READY_CLASH_API_LISTEN=$ready_clash_api_listen"
# shellcheck disable=SC2086
procd_set_param env $ready_env
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn 3600 5 5
procd_set_param term_timeout 20
procd_close_instance
}
# procd 默认的 stop→start 太快,start 的 preflight 会把还没清掉的 dae0 当残留
# 拒绝,restart 完服务就停在停止状态。走 lifecycle 先排空再起。
restart() {
# 没启用时 start 本来就会拒绝,走 lifecycle 只会多打一句误导性的
# “new managed core did not become stable and own its API listener”。
if [ "$(uci get honk.main.enabled 2>/dev/null)" != 1 ]; then
logger -t honk "restart skipped: service is not enabled"
return 0
fi
. /usr/share/honk/lifecycle.sh || return 1
honk_lifecycle_restart 30
}
reload_service() {
# honk-core has no hot-reload API wired here; a reload is an explicit
# restart so existing connections are cycled. The UI only exposes
# restart, this exists so manual `/etc/init.d/honk reload` is defined.
logger -t honk "reload requested, restarting (no hot-reload)"
restart
}