update 2026-11-03 23:44:20

This commit is contained in:
action committed 2026-11-03 23:44:20 +08:00
1 parent 22194cf4dd
commit 0350fcc2e5
37 files changed
+500 -1291

No files matched your search

+18
View File
@@ -61,6 +61,10 @@ define Package/$(PKG_NAME)/description
Main functions of Lucky: dynamic domain name ddns-go service, socat,reverse proxy ,wake on lan
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/lucky
endef
define Build/Prepare
[ ! -f $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz ] && wget https://github.com/gdy666/lucky/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -O $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz
tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR)
@@ -72,6 +76,20 @@ endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky
$(INSTALL_DIR) $(1)/usr/libexec
$(INSTALL_BIN) ./files/lucky-call $(1)/usr/libexec/lucky-call
$(INSTALL_BIN) ./files/lucky-watchdog $(1)/usr/libexec/lucky-watchdog
$(INSTALL_DIR) $(1)/usr/share/lucky
echo '$(LUCKY_ARCH)' > $(1)/usr/share/lucky/arch
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/lucky.init $(1)/etc/init.d/lucky
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/luckyuci $(1)/etc/config/lucky
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || /usr/libexec/lucky-watchdog sync
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
+129
View File
@@ -0,0 +1,129 @@
#!/bin/sh
# SPDX-License-Identifier: MIT
PROG=/usr/bin/lucky
INIT=/etc/init.d/lucky
DEFAULT_CONFIG_DIR=/etc/config/lucky.daji
RESET_LOCK_DIR=/var/lock/lucky-reset-auth.lock
fail() {
echo "$1" >&2
exit "${2:-1}"
}
config_dir() {
local value newline
value="$(uci -q get lucky.@lucky[0].configdir)"
[ -n "$value" ] || value="$DEFAULT_CONFIG_DIR"
newline='
'
case "$value" in
*"$newline"* | //* | / | /proc | /proc/* | /sys | /sys/* | /dev | /dev/* | /run | /run/* | */../* | */.. | */./* | */.) ;;
/*)
printf '%s\n' "$value"
return 0
;;
esac
fail "Lucky config directory is unsafe" 2
}
require_program() {
[ -x "$PROG" ] || fail "Lucky is not installed" 127
}
set_conf() {
local key="$1"
local value="$2"
local dir
dir="$(config_dir)" || exit $?
require_program
if [ -n "$value" ]; then
"$PROG" -setconf -key "$key" -value "$value" -cd "$dir"
else
"$PROG" -setconf -key "$key" -cd "$dir"
fi
}
service_action() {
local action="$1"
local enabled
case "$action" in
start | restart) enabled=1 ;;
stop) enabled=0 ;;
*) fail "Unsupported service action" 2 ;;
esac
uci -q set "lucky.@lucky[0].enabled=$enabled" || fail "Unable to update Lucky service state"
uci commit lucky || fail "Unable to save Lucky service state"
"$INIT" "$action"
}
case "$1" in
info)
[ "$#" -eq 1 ] || fail "Usage: lucky-call info" 2
require_program
exec "$PROG" -info
;;
base)
[ "$#" -eq 1 ] || fail "Usage: lucky-call base" 2
dir="$(config_dir)" || exit $?
require_program
exec "$PROG" -baseConfInfo -cd "$dir"
;;
status)
[ "$#" -eq 1 ] || fail "Usage: lucky-call status" 2
if ubus call service list '{"name":"lucky"}' 2> /dev/null |
jsonfilter -e '@.lucky.instances.*.running' 2> /dev/null | grep -qx true; then
echo true
else
echo false
fi
;;
arch)
[ "$#" -eq 1 ] || fail "Usage: lucky-call arch" 2
if [ -r /usr/share/lucky/arch ]; then
exec sed -n '1p' /usr/share/lucky/arch
fi
exec uname -m
;;
service)
[ "$#" -eq 2 ] || fail "Usage: lucky-call service start|stop|restart" 2
service_action "$2"
;;
set-port)
[ "$#" -eq 2 ] || fail "Usage: lucky-call set-port PORT" 2
case "$2" in *[!0-9]* | '') fail "Port must be an integer from 1 to 65535" 2 ;; esac
[ "$2" -ge 1 ] 2> /dev/null && [ "$2" -le 65535 ] 2> /dev/null || fail "Port must be an integer from 1 to 65535" 2
set_conf AdminWebListenPort "$2"
;;
set-safe-url)
[ "$#" -eq 2 ] || fail "Usage: lucky-call set-safe-url /path" 2
[ "${#2}" -le 256 ] || fail "Safe URL is too long" 2
case "$2" in *[[:space:]]*) fail "Safe URL must not contain whitespace" 2 ;; '' | /*) ;; *) fail "Safe URL must be empty or begin with /" 2 ;; esac
set_conf SetSafeURL "$2"
;;
set-internet)
[ "$#" -eq 2 ] || fail "Usage: lucky-call set-internet true|false" 2
case "$2" in true | false) ;; *) fail "Internet access must be true or false" 2 ;; esac
set_conf AllowInternetaccess "$2"
;;
reset-auth)
[ "$#" -eq 1 ] || fail "Usage: lucky-call reset-auth" 2
mkdir "$RESET_LOCK_DIR" 2> /dev/null || fail "Another credential reset is already running"
trap 'rmdir "$RESET_LOCK_DIR" 2>/dev/null' EXIT HUP INT TERM
password="$(dd if=/dev/urandom bs=12 count=1 2> /dev/null | hexdump -v -e '1/1 "%02x"')"
[ "${#password}" -eq 24 ] || fail "Unable to generate a secure password"
set_conf AllowInternetaccess false > /dev/null || fail "Unable to disable Internet access before resetting credentials"
"$INIT" stop || fail "Unable to stop Lucky before resetting credentials"
set_conf AdminAccount admin > /dev/null || fail "Unable to reset the admin account"
set_conf AdminPassword "$password" > /dev/null || fail "The account changed, but the password update failed"
if "$INIT" restart; then
restarted=true
else
restarted=false
fi
printf '{"account":"admin","password":"%s","restarted":%s}\n' "$password" "$restarted"
;;
*)
fail "Unsupported Lucky operation" 2
;;
esac
+100
View File
@@ -0,0 +1,100 @@
#!/bin/sh
# SPDX-License-Identifier: MIT
# Only this exact entry belongs to us. Never remove user-created Lucky jobs.
ENTRY='* * * * * [ -x /usr/libexec/lucky-watchdog ] && /usr/libexec/lucky-watchdog check # lucky-watchdog'
ROOT_CRONTAB=/etc/crontabs/root
temporary=
fail() {
echo "$1" >&2
exit 1
}
configured() {
case "$(uci -q get lucky.@lucky[0].watchdog)" in 1 | on | true | yes) return 0 ;; *) return 1 ;; esac
}
scheduled() {
grep -qxF "$ENTRY" "$ROOT_CRONTAB" 2> /dev/null
}
status() {
local enabled=false installed=false paused=false cron_running=false
configured && enabled=true
scheduled && installed=true
[ -e /var/run/lucky.stopped ] && paused=true
case "$(uci -q get lucky.@lucky[0].enabled)" in 1 | on | true | yes) ;; *) paused=true ;; esac
pidof crond > /dev/null && cron_running=true
printf '{"enabled":%s,"scheduled":%s,"paused":%s,"cron_running":%s}\n' "$enabled" "$installed" "$paused" "$cron_running"
}
sync_cron() {
local enabled="$1"
# An unconfigured installation does not require cron or touch its files.
[ "$enabled" = 1 ] || scheduled || return 0
[ ! -L "$ROOT_CRONTAB" ] || fail "Refusing a symlinked root crontab"
[ ! -e "$ROOT_CRONTAB" ] || [ -f "$ROOT_CRONTAB" ] || fail "Invalid root crontab"
command -v crontab > /dev/null || fail "Cron is not installed"
temporary="$(mktemp -d /tmp/lucky-watchdog.XXXXXX)" || fail "Cannot prepare crontab"
if [ -e "$ROOT_CRONTAB" ]; then
cat "$ROOT_CRONTAB" > "$temporary/before" || fail "Cannot read crontab"
else
: > "$temporary/before"
fi
# awk also handles a final line without a newline before appending our job.
awk -v entry="$ENTRY" '$0 != entry { print }' "$temporary/before" > "$temporary/after" || fail "Cannot prepare crontab"
[ "$enabled" = 1 ] && printf '%s\n' "$ENTRY" >> "$temporary/after"
if ! cmp -s "$temporary/before" "$temporary/after"; then
if [ -e "$ROOT_CRONTAB" ]; then
cmp -s "$temporary/before" "$ROOT_CRONTAB" || fail "Crontab changed; please retry"
else
[ ! -s "$temporary/before" ] || fail "Crontab changed; please retry"
fi
crontab -u root "$temporary/after" || fail "Cannot install crontab"
fi
if [ "$enabled" = 1 ]; then
/etc/init.d/cron enable || fail "Cannot enable cron"
pidof crond > /dev/null || /etc/init.d/cron start || fail "Cannot start cron"
fi
}
[ "$#" -eq 1 ] || fail "Usage: lucky-watchdog status|enable|disable|sync|remove|check"
case "$1" in
check)
# Avoid a transient process named "lucky" being mistaken for the core by
# other maintenance helpers using pidof. rc.common still takes procd's lock.
exec /bin/sh /etc/rc.common /etc/init.d/lucky watchdog
;;
status)
status
exit 0
;;
enable | disable | sync | remove) ;;
*) fail "Unsupported watchdog operation" ;;
esac
umask 077
exec 9> /var/lock/lucky-watchdog.lock
flock -x 9 || fail "Cannot lock watchdog settings"
trap '[ -z "$temporary" ] || { rm -f "$temporary/before" "$temporary/after"; rmdir "$temporary"; }' EXIT
case "$1" in
enable | disable)
enabled=0
[ "$1" = enable ] && enabled=1
# Set the option only after the cron update succeeds. A failed enable never
# starts recovery; a failed disable still leaves the old setting visible.
sync_cron "$enabled"
uci -q set "lucky.@lucky[0].watchdog=$enabled" && uci commit lucky || fail "Cannot save watchdog settings"
status
;;
sync)
enabled=0
configured && enabled=1
sync_cron "$enabled"
;;
remove)
sync_cron 0
;;
esac
+96
View File
@@ -0,0 +1,96 @@
#!/bin/sh /etc/rc.common
# SPDX-License-Identifier: MIT
START=99
STOP=15
USE_PROCD=1
EXTRA_COMMANDS="watchdog"
EXTRA_HELP=" watchdog Recover an unexpectedly stopped service"
PROG=/usr/bin/lucky
DEFAULT_CONFIG_DIR=/etc/config/lucky.daji
STOP_MARKER=/var/run/lucky.stopped
WATCHDOG_LAST=/var/run/lucky-watchdog.last
validate_config_dir() {
local newline
newline='
'
case "$1" in
*"$newline"* | //* | / | /proc | /proc/* | /sys | /sys/* | /dev | /dev/* | /run | /run/* | */../* | */.. | */./* | */.) ;;
/*) return 0 ;;
*) ;;
esac
logger -t lucky -p daemon.err "Rejected unsafe config directory: $1"
return 1
}
start_instance() {
local section="$1"
local enabled config_dir logger_enabled
config_get_bool enabled "$section" enabled 0
[ "$enabled" -eq 1 ] || return 0
config_get config_dir "$section" configdir "$DEFAULT_CONFIG_DIR"
config_get_bool logger_enabled "$section" logger 1
validate_config_dir "$config_dir" || return 1
umask 077
mkdir -p "$config_dir" || return 1
procd_open_instance "$section"
procd_set_param command "$PROG" -cd "$config_dir"
procd_set_param respawn 3600 5 5
procd_set_param stderr 1
[ "$logger_enabled" -eq 1 ] && procd_set_param stdout 1
procd_set_param file /etc/config/lucky
procd_close_instance
}
start_service() {
rm -f "$STOP_MARKER"
[ "$WATCHDOG_RECOVERY" = 1 ] || rm -f "$WATCHDOG_LAST"
config_load lucky
config_foreach start_instance lucky
}
stop_service() {
# rc.common serializes both stop and watchdog with procd's service lock.
# Write before stopping: maintenance must never race with a cron recovery.
umask 077
: > "$STOP_MARKER"
}
watchdog() {
local service now last
procd_lock
[ ! -e "$STOP_MARKER" ] || return 0
case "$(uci -q get lucky.@lucky[0].watchdog)" in 1 | on | true | yes) ;; *) return 0 ;; esac
case "$(uci -q get lucky.@lucky[0].enabled)" in 1 | on | true | yes) ;; *) return 0 ;; esac
[ -x "$PROG" ] || return 0
# Query the supervisor without executing the core; fail closed if ubus fails.
service="$(ubus -t 3 call service list '{"name":"lucky"}')" || return 0
if printf '%s\n' "$service" | jsonfilter -e '@.lucky.instances.*.running' | grep -qx true; then
return 0
fi
pidof lucky > /dev/null && return 0
# Repeated OOMs or a broken binary must not trigger a restart every minute.
read -r now _ < /proc/uptime
now="${now%%.*}"
last="$(cat "$WATCHDOG_LAST" 2> /dev/null)"
case "$last" in '' | *[!0-9]*) last=0 ;; esac
[ "$last" -eq 0 ] || [ "$((now - last))" -ge 300 ] || return 0
umask 077
printf '%s\n' "$now" > "$WATCHDOG_LAST" || return 1
logger -t lucky -p daemon.notice "Watchdog recovering unexpectedly stopped Lucky service"
WATCHDOG_RECOVERY=1 start
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger lucky
}
+5
View File
@@ -0,0 +1,5 @@
config lucky
option enabled '1'
option logger '1'
option watchdog '0'
option configdir '/etc/config/lucky.daji'