s
This commit is contained in:
@@ -95,6 +95,8 @@ NEKO_WEBRTC_UDPMUX_1=52300
|
|||||||
NEKO_WEBRTC_UDPMUX_2=52301
|
NEKO_WEBRTC_UDPMUX_2=52301
|
||||||
NEKO_WEBRTC_UDPMUX_3=52302
|
NEKO_WEBRTC_UDPMUX_3=52302
|
||||||
NEKO_WEBRTC_NAT1TO1=
|
NEKO_WEBRTC_NAT1TO1=
|
||||||
|
# 后台 watcher 会定期核对当前 LAN IP;若板子切换 Wi‑Fi / DHCP 后 IP 变化,会自动重启 Neko 刷新 WebRTC NAT 地址
|
||||||
|
NEKO_IP_WATCH_INTERVAL=15
|
||||||
NEKO_PLUGINS_ENABLED=true
|
NEKO_PLUGINS_ENABLED=true
|
||||||
|
|
||||||
# Redroid Android 13(需要 binderfs 或 /dev/binder*;安装脚本会在支持的内核上自动准备)
|
# Redroid Android 13(需要 binderfs 或 /dev/binder*;安装脚本会在支持的内核上自动准备)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ configure_sudoers
|
|||||||
configure_mdns
|
configure_mdns
|
||||||
install_browser_stack
|
install_browser_stack
|
||||||
install_neko_browser
|
install_neko_browser
|
||||||
|
install_neko_ip_watch_service
|
||||||
install_redroid
|
install_redroid
|
||||||
prepare_mitmproxy
|
prepare_mitmproxy
|
||||||
prepare_vscode_server
|
prepare_vscode_server
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ configure_wifi_profile
|
|||||||
install_shellcrash
|
install_shellcrash
|
||||||
install_browser_stack
|
install_browser_stack
|
||||||
install_neko_browser
|
install_neko_browser
|
||||||
|
install_neko_ip_watch_service
|
||||||
install_redroid
|
install_redroid
|
||||||
prepare_mitmproxy
|
prepare_mitmproxy
|
||||||
prepare_vscode_server
|
prepare_vscode_server
|
||||||
|
|||||||
@@ -777,6 +777,36 @@ UNIT
|
|||||||
systemctl enable --now live-console.service
|
systemctl enable --now live-console.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_neko_ip_watch_service() {
|
||||||
|
if [ "${ENABLE_NEKO:-1}" != "1" ]; then
|
||||||
|
systemctl disable --now live-neko-ip-watch.service >/dev/null 2>&1 || true
|
||||||
|
rm -f /etc/systemd/system/live-neko-ip-watch.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
log "Installing Neko LAN IP watcher"
|
||||||
|
chmod +x "$ROOT_DIR/scripts/linux/neko_ip_watch.sh"
|
||||||
|
cat >/etc/systemd/system/live-neko-ip-watch.service <<UNIT
|
||||||
|
[Unit]
|
||||||
|
Description=Live Neko LAN IP watcher
|
||||||
|
After=network-online.target docker.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=$ROOT_DIR
|
||||||
|
Environment=NEKO_IP_WATCH_INTERVAL=${NEKO_IP_WATCH_INTERVAL:-15}
|
||||||
|
ExecStart=/bin/bash $ROOT_DIR/scripts/linux/neko_ip_watch.sh
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
UNIT
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now live-neko-ip-watch.service
|
||||||
|
}
|
||||||
|
|
||||||
configure_sudoers() {
|
configure_sudoers() {
|
||||||
log "Configuring sudoers for live control plane"
|
log "Configuring sudoers for live control plane"
|
||||||
cat >/etc/sudoers.d/live-control-plane <<SUDOERS
|
cat >/etc/sudoers.d/live-control-plane <<SUDOERS
|
||||||
|
|||||||
101
d2ypp2/scripts/linux/neko_ip_watch.sh
Normal file
101
d2ypp2/scripts/linux/neko_ip_watch.sh
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
INSTALL_TAG="${INSTALL_TAG:-neko-ip-watch}"
|
||||||
|
. "$SELF_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
reload_watch_env() {
|
||||||
|
unset ENABLE_NEKO NEKO_IP_WATCH_INTERVAL
|
||||||
|
if [ -f "$STACK_ENV" ]; then
|
||||||
|
set -a
|
||||||
|
. "$STACK_ENV"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
ENABLE_NEKO="${ENABLE_NEKO:-1}"
|
||||||
|
NEKO_IP_WATCH_INTERVAL="${NEKO_IP_WATCH_INTERVAL:-15}"
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_interval() {
|
||||||
|
local value="${1:-15}"
|
||||||
|
case "$value" in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
value=15
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ "$value" -lt 5 ]; then
|
||||||
|
value=5
|
||||||
|
fi
|
||||||
|
printf '%s\n' "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
running_neko_nat1to1_values() {
|
||||||
|
local name value
|
||||||
|
for name in live-neko-1 live-neko-2 live-neko-3; do
|
||||||
|
if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$name"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
value="$(
|
||||||
|
docker inspect "$name" --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null |
|
||||||
|
awk -F= '/^NEKO_WEBRTC_NAT1TO1=/{print $2; exit}'
|
||||||
|
)"
|
||||||
|
if [ -n "$value" ]; then
|
||||||
|
printf '%s\n' "$value"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_refresh_neko_for_ip_change() {
|
||||||
|
local preferred active interval cooldown active_value
|
||||||
|
|
||||||
|
if [ "${ENABLE_NEKO:-1}" != "1" ] || ! have docker; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -Eq '^live-neko-[123]$'; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
preferred="$(detect_preferred_lan_ip || true)"
|
||||||
|
if [ -z "$preferred" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
active=""
|
||||||
|
for active_value in $(running_neko_nat1to1_values || true); do
|
||||||
|
[ -n "$active_value" ] || continue
|
||||||
|
if [ "$active_value" != "$preferred" ]; then
|
||||||
|
active="$active_value"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$active" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
interval="$(normalize_interval "${NEKO_IP_WATCH_INTERVAL:-15}")"
|
||||||
|
cooldown="$interval"
|
||||||
|
if [ "$cooldown" -lt 15 ]; then
|
||||||
|
cooldown=15
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Detected Neko LAN IP drift: container=${active} current=${preferred}; restarting Neko"
|
||||||
|
if bash "$SERVICE_CTL" neko restart; then
|
||||||
|
log "Neko restart finished; refreshed NAT1TO1=${preferred}"
|
||||||
|
else
|
||||||
|
log "WARN: Neko restart failed after LAN IP drift"
|
||||||
|
fi
|
||||||
|
sleep "$cooldown"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
load_env
|
||||||
|
reload_watch_env
|
||||||
|
log "Watching Neko LAN IP changes"
|
||||||
|
while true; do
|
||||||
|
reload_watch_env
|
||||||
|
maybe_refresh_neko_for_ip_change
|
||||||
|
sleep "$(normalize_interval "${NEKO_IP_WATCH_INTERVAL:-15}")"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# git pull 后若只改了 systemd 模板(如 StartLimit),执行本脚本重写 live-console.service 并 enable --now
|
# git pull 后若改了 systemd 模板(如 live-console 或 Neko watcher),执行本脚本重写对应 unit 并 enable --now
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
@@ -10,4 +10,6 @@ ensure_root "$@"
|
|||||||
load_env
|
load_env
|
||||||
log "Rewriting /etc/systemd/system/live-console.service from repo"
|
log "Rewriting /etc/systemd/system/live-console.service from repo"
|
||||||
install_live_console_service
|
install_live_console_service
|
||||||
|
log "Rewriting /etc/systemd/system/live-neko-ip-watch.service from repo"
|
||||||
|
install_neko_ip_watch_service
|
||||||
log "Done. Check: systemctl status live-console.service --no-pager"
|
log "Done. Check: systemctl status live-console.service --no-pager"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ ensure_root "$@"
|
|||||||
load_env
|
load_env
|
||||||
|
|
||||||
log "Stopping systemd services"
|
log "Stopping systemd services"
|
||||||
for svc in live-edge.service live-console.service live-webtty.service live-android-panel.service live-pulseaudio.service live-kmscube.service live-redroid-host.service netdata cockpit.socket shellcrash.service avahi-daemon; do
|
for svc in live-edge.service live-console.service live-neko-ip-watch.service live-webtty.service live-android-panel.service live-pulseaudio.service live-kmscube.service live-redroid-host.service netdata cockpit.socket shellcrash.service avahi-daemon; do
|
||||||
systemctl stop "$svc" >/dev/null 2>&1 || true
|
systemctl stop "$svc" >/dev/null 2>&1 || true
|
||||||
systemctl disable "$svc" >/dev/null 2>&1 || true
|
systemctl disable "$svc" >/dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
@@ -42,6 +42,7 @@ fi
|
|||||||
log "Removing systemd unit files"
|
log "Removing systemd unit files"
|
||||||
rm -f /etc/systemd/system/live-edge.service
|
rm -f /etc/systemd/system/live-edge.service
|
||||||
rm -f /etc/systemd/system/live-console.service
|
rm -f /etc/systemd/system/live-console.service
|
||||||
|
rm -f /etc/systemd/system/live-neko-ip-watch.service
|
||||||
rm -f /etc/systemd/system/live-webtty.service
|
rm -f /etc/systemd/system/live-webtty.service
|
||||||
rm -f /etc/systemd/system/live-android-panel.service
|
rm -f /etc/systemd/system/live-android-panel.service
|
||||||
rm -f /etc/systemd/system/live-pulseaudio.service
|
rm -f /etc/systemd/system/live-pulseaudio.service
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ prepare_python_runtime
|
|||||||
log "Rebuilding web-console (npm)"
|
log "Rebuilding web-console (npm)"
|
||||||
prepare_web_console
|
prepare_web_console
|
||||||
|
|
||||||
|
log "Refreshing Neko LAN IP watcher unit"
|
||||||
|
install_neko_ip_watch_service
|
||||||
|
|
||||||
log "Restarting live-console.service"
|
log "Restarting live-console.service"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl restart live-console.service
|
systemctl restart live-console.service
|
||||||
|
|||||||
@@ -86,6 +86,23 @@ class NekoConfigTests(unittest.TestCase):
|
|||||||
self.assertIn("NEKO_HTTP_PORT_2", common)
|
self.assertIn("NEKO_HTTP_PORT_2", common)
|
||||||
self.assertIn("NEKO_WEBRTC_UDP_RANGE_3", common)
|
self.assertIn("NEKO_WEBRTC_UDP_RANGE_3", common)
|
||||||
|
|
||||||
|
def test_neko_ip_watcher_is_installed_and_restarts_on_drift(self) -> None:
|
||||||
|
common = (ROOT / "scripts" / "linux" / "lib" / "common.sh").read_text(encoding="utf-8")
|
||||||
|
watcher = (ROOT / "scripts" / "linux" / "neko_ip_watch.sh").read_text(encoding="utf-8")
|
||||||
|
upgrade = (ROOT / "scripts" / "linux" / "upgrade_live_console.sh").read_text(encoding="utf-8")
|
||||||
|
uninstall = (ROOT / "scripts" / "linux" / "uninstall_stack.sh").read_text(encoding="utf-8")
|
||||||
|
stack_env = (ROOT / "config" / "system-stack.env.example").read_text(encoding="utf-8")
|
||||||
|
self.assertIn("install_neko_ip_watch_service()", common)
|
||||||
|
self.assertIn("live-neko-ip-watch.service", common)
|
||||||
|
self.assertIn("ExecStart=/bin/bash", common)
|
||||||
|
self.assertIn("scripts/linux/neko_ip_watch.sh", common)
|
||||||
|
self.assertIn("detect_preferred_lan_ip", watcher)
|
||||||
|
self.assertIn('bash "$SERVICE_CTL" neko restart', watcher)
|
||||||
|
self.assertIn("NEKO_IP_WATCH_INTERVAL", watcher)
|
||||||
|
self.assertIn("install_neko_ip_watch_service", upgrade)
|
||||||
|
self.assertIn("live-neko-ip-watch.service", uninstall)
|
||||||
|
self.assertIn("NEKO_IP_WATCH_INTERVAL=15", stack_env)
|
||||||
|
|
||||||
def test_local_browser_prefers_chrome_on_x86_and_chromium_elsewhere(self) -> None:
|
def test_local_browser_prefers_chrome_on_x86_and_chromium_elsewhere(self) -> None:
|
||||||
script = (ROOT / "scripts" / "linux" / "launch_browser.sh").read_text(encoding="utf-8")
|
script = (ROOT / "scripts" / "linux" / "launch_browser.sh").read_text(encoding="utf-8")
|
||||||
self.assertIn("x86_64|amd64", script)
|
self.assertIn("x86_64|amd64", script)
|
||||||
|
|||||||
Reference in New Issue
Block a user