完善安装脚本,增加对 1GB Huge Pages 的支持,优化服务管理与权限设置
Build and Release / build-and-test (arm64) (push) Successful in 23s
Build and Release / build-and-test (amd64) (push) Successful in 34s
Build and Release / release (push) Skipped

This commit is contained in:
2026-08-05 12:33:33 +08:00
parent 3ce5a2a120
commit 99a17f1852
2 changed files with 396 additions and 86 deletions
+238 -48
View File
@@ -16,6 +16,10 @@ declare -r RESET="\033[0m"
INSTALL_DIR="/etc/miner/xxxig"
CONFIG_FILE="$INSTALL_DIR/config.json"
LOG_FILE="$INSTALL_DIR/xxxig.log"
HUGEPAGES_HELPER="/usr/local/libexec/xxxig-enable-1gb-pages"
HUGEPAGES_SERVICE="/etc/systemd/system/xxxig-hugepages.service"
SYSTEMD_DROPIN_DIR="/etc/systemd/system/xxxig.service.d"
SYSTEMD_DROPIN="$SYSTEMD_DROPIN_DIR/hugepages.conf"
# Gitea 配置
GITEA_SERVER="gitea.bcde.io"
@@ -36,6 +40,7 @@ DEFAULT_ONE_GB_PAGES="false"
DEFAULT_VERBOSE="true"
DEFAULT_CC_ENABLED="false"
DEFAULT_CC_TLS="false"
DEFAULT_KEEP_NAME="false"
# 辅助函数
log() { echo -e "${1}${2}${RESET}"; }
@@ -67,12 +72,17 @@ get_gitea_latest_version() {
uninstall_xxxig() {
if [[ $os_type == "alpine" ]]; then
rc-service xxxig stop 2>/dev/null || true
rc-service xxxig-hugepages stop 2>/dev/null || true
rc-update del xxxig default 2>/dev/null || true
rm -rf "$INSTALL_DIR" /etc/init.d/xxxig
rc-update del xxxig-hugepages default 2>/dev/null || true
rm -rf "$INSTALL_DIR" /etc/init.d/xxxig /etc/init.d/xxxig-hugepages
rm -f "$HUGEPAGES_HELPER" "$HUGEPAGES_SERVICE"
else
systemctl stop xxxig 2>/dev/null || true
systemctl disable xxxig 2>/dev/null || true
systemctl stop xxxig xxxig-hugepages 2>/dev/null || true
systemctl disable xxxig xxxig-hugepages 2>/dev/null || true
rm -rf "$INSTALL_DIR" /etc/systemd/system/xxxig.service
rm -f "$SYSTEMD_DROPIN" "$HUGEPAGES_HELPER" "$HUGEPAGES_SERVICE"
rmdir "$SYSTEMD_DROPIN_DIR" 2>/dev/null || true
systemctl daemon-reload 2>/dev/null || true
fi
}
@@ -90,6 +100,98 @@ install_xxxig() {
chmod +x "$INSTALL_DIR/xxxigDaemon" "$INSTALL_DIR/xxxig"
}
create_xxxig_user() {
if [[ "$os_type" == "alpine" ]]; then
getent group xxxig >/dev/null || addgroup -S xxxig
getent passwd xxxig >/dev/null || \
adduser -S -D -H -h "$INSTALL_DIR" -s /sbin/nologin -G xxxig xxxig
else
getent group xxxig >/dev/null || addgroup --system xxxig
getent passwd xxxig >/dev/null || \
adduser --system --ingroup xxxig --no-create-home \
--home "$INSTALL_DIR" --shell /usr/sbin/nologin xxxig
fi
}
set_runtime_permissions() {
touch "$LOG_FILE"
chown -R root:root "$INSTALL_DIR"
chown xxxig:xxxig "$CONFIG_FILE" "$LOG_FILE"
chmod 640 "$CONFIG_FILE"
chmod 640 "$LOG_FILE"
chmod 755 "$INSTALL_DIR" "$INSTALL_DIR/xxxigDaemon" "$INSTALL_DIR/xxxig"
}
write_hugepages_helper() {
mkdir -p "$(dirname "$HUGEPAGES_HELPER")"
cat >"$HUGEPAGES_HELPER" <<'EOF'
#!/bin/sh
set -eu
sysctl -w vm.nr_hugepages="$(nproc)"
found=0
for node in /sys/devices/system/node/node*; do
file="$node/hugepages/hugepages-1048576kB/nr_hugepages"
[ -e "$file" ] || continue
printf '3\n' >"$file"
actual=$(cat "$file")
[ "$actual" -ge 3 ] || exit 1
found=1
done
[ "$found" -eq 1 ]
EOF
chmod 755 "$HUGEPAGES_HELPER"
}
write_hugepages_service() {
cat >"$HUGEPAGES_SERVICE" <<EOF
[Unit]
Description=Reserve Huge Pages for XXXig
Before=xxxig.service
ConditionPathExists=/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
[Service]
Type=oneshot
ExecStart=$HUGEPAGES_HELPER
[Install]
WantedBy=multi-user.target
EOF
}
configure_systemd_hugepages() {
[[ "$one_gb_pages" == "true" ]] || return 0
log "$BLUE" "配置 1GB Huge Pages 持久池..."
write_hugepages_helper
write_hugepages_service
mkdir -p "$SYSTEMD_DROPIN_DIR"
cat >"$SYSTEMD_DROPIN" <<'EOF'
[Unit]
Requires=xxxig-hugepages.service
After=xxxig-hugepages.service
EOF
}
configure_alpine_hugepages() {
[[ "$one_gb_pages" == "true" ]] || return 0
log "$BLUE" "配置 1GB Huge Pages 持久池..."
write_hugepages_helper
cat >/etc/init.d/xxxig-hugepages <<EOF
#!/sbin/openrc-run
description="Reserve Huge Pages for XXXig"
start() {
ebegin "Reserving Huge Pages for XXXig"
$HUGEPAGES_HELPER
eend \$?
}
EOF
chmod 755 /etc/init.d/xxxig-hugepages
rc-update add xxxig-hugepages default
}
# 配置 CPU 亲和性
configure_cpu_rx() {
local cpu_cores=$(nproc)
@@ -109,6 +211,29 @@ configure_cpu_rx() {
}
# 更新配置文件
append_pool_options() {
[[ "$one_gb_pages" == "true" ]] && jq_cmd+=' | .randomx."1gb-pages" = true'
[[ "$pool_keepalive" == "true" ]] && jq_cmd+=' | .pools[0].keepalive = true'
[[ -n "$pool_tls_fingerprint" ]] && \
jq_cmd+=" | .pools[0].\"tls-fingerprint\" = \"$pool_tls_fingerprint\""
[[ "$pool_daemon" == "true" ]] && jq_cmd+=' | .pools[0].daemon = true'
[[ "$pool_submit_to_origin" == "true" ]] && \
jq_cmd+=" | .pools[0].\"submit-to-origin\" = true | .pools[0].\"self-select\" = \"$pool_self_select\""
return 0
}
append_cc_options() {
if [[ "$cc_enabled" == "true" ]]; then
jq_cmd+=" | .\"cc-client\".enabled = true
| .\"cc-client\".servers[0].url = \"$cc_url\"
| .\"cc-client\".servers[0].\"access-token\" = \"$cc_token\"
| .\"cc-client\".servers[0].\"use-tls\" = $cc_tls
| .\"cc-client\".\"worker-id\" = \"$cc_work_id\""
else
jq_cmd+=' | ."cc-client".enabled = false'
fi
}
replace_config() {
[[ ! -f "$CONFIG_FILE" ]] && error "配置文件缺失"
@@ -123,76 +248,87 @@ replace_config() {
| .pools[0].nicehash = $pool_nicehash
| .\"verbose\" = $verbose"
[[ "$one_gb_pages" == "true" ]] && jq_cmd+=" | .randomx.\"1gb-pages\" = true"
[[ "$pool_keepalive" == "true" ]] && jq_cmd+=" | .pools[0].keepalive = true"
[[ -n "$pool_tls_fingerprint" ]] && jq_cmd+=" | .pools[0].\"tls-fingerprint\" = \"$pool_tls_fingerprint\""
[[ "$pool_daemon" == "true" ]] && jq_cmd+=" | .pools[0].daemon = true"
if [[ "$pool_submit_to_origin" == "true" ]]; then
jq_cmd+=" | .pools[0].\"submit-to-origin\" = true | .pools[0].\"self-select\" = \"$pool_self_select\""
fi
if [[ "$cc_enabled" == "true" ]]; then
jq_cmd+=" | .\"cc-client\".enabled = true
| .\"cc-client\".servers[0].url = \"$cc_url\"
| .\"cc-client\".servers[0].\"access-token\" = \"$cc_token\"
| .\"cc-client\".servers[0].\"use-tls\" = $cc_tls
| .\"cc-client\".\"worker-id\" = \"$cc_work_id\""
else
jq_cmd+=" | .\"cc-client\".enabled = false"
fi
append_pool_options
append_cc_options
jq "$jq_cmd" "$CONFIG_FILE" >"$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
configure_cpu_rx
}
# 创建并启动服务
create_service() {
if [[ "$os_type" == "alpine" ]]; then
cat >/etc/init.d/xxxig <<'EOF'
create_alpine_service() {
local hugepages_dependency=""
[[ "$one_gb_pages" == "true" ]] && hugepages_dependency=" need xxxig-hugepages"
cat >/etc/init.d/xxxig <<EOF
#!/sbin/openrc-run
name="XXXig Miner"
description="XXXig Miner Service"
command="/etc/miner/xxxig/xxxigDaemon"
command_args="-c /etc/miner/xxxig/config.json"
pidfile="/run/${RC_SVCNAME}.pid"
command_user="xxxig:xxxig"
pidfile="/run/\${RC_SVCNAME}.pid"
command_background="yes"
rc_ulimit="-n 65535"
rc_ulimit="-n 65535 -l unlimited"
depend() {
need net
$hugepages_dependency
after network
}
EOF
chmod +x /etc/init.d/xxxig
rc-update add xxxig default
rc-service xxxig start
else
cat >/etc/systemd/system/xxxig.service <<EOF
chmod 755 /etc/init.d/xxxig
rc-update add xxxig default
rc-service xxxig start
}
write_systemd_service() {
cat >/etc/systemd/system/xxxig.service <<EOF
[Unit]
Description=XXXig Miner
After=network.target
[Service]
User=root
Type=simple
User=xxxig
Group=xxxig
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/xxxigDaemon -c $CONFIG_FILE
Restart=always
RestartSec=10
LimitNOFILE=65535
LimitMEMLOCK=infinity
AmbientCapabilities=CAP_IPC_LOCK
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=$INSTALL_DIR
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now xxxig.service
}
start_systemd_service() {
systemctl daemon-reload
if [[ "$one_gb_pages" == "true" ]]; then
systemctl enable xxxig-hugepages.service
fi
systemctl enable --now xxxig.service
}
create_service() {
if [[ "$os_type" == "alpine" ]]; then
create_alpine_service
else
write_systemd_service
start_systemd_service
fi
}
show_usage() {
cat <<EOF
用法: $0 [选项]
选项:
-v, --version <版本> XXXig 版本 (默认: $DEFAULT_VERSION)
-t, --threads <数字> 线程数 (默认: 自动)
@@ -213,15 +349,14 @@ show_usage() {
--cc-work-id <ID> CC 工作 ID
--cc-token <令牌> CC 访问令牌
--cc-tls 启用 CC TLS
--keep-name 保留已有矿池密码和 CC worker-id
-h, --help 显示帮助信息
示例:
$0 -o pool.example.com:3333 -w YOUR_WALLET_ADDRESS
EOF
exit 1
}
parse_args() {
init_args() {
version=$DEFAULT_VERSION
threads=$DEFAULT_THREADS
pool_algo=$DEFAULT_POOL_ALGO
@@ -242,7 +377,10 @@ parse_args() {
cc_token=""
cc_tls=$DEFAULT_CC_TLS
one_gb_pages=$DEFAULT_ONE_GB_PAGES
keep_name=$DEFAULT_KEEP_NAME
}
read_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-v | --version) version="$2"; shift 2 ;;
@@ -265,21 +403,26 @@ parse_args() {
--verbose) verbose="true"; shift ;;
--cc) cc_enabled="true"; shift ;;
--cc-tls) cc_tls="true"; shift ;;
--keep-name | --preserve-name) keep_name="true"; shift ;;
-h | --help) show_usage ;;
*) error "无效选项: $1" ;;
esac
done
}
# 验证必需参数
validate_args() {
[[ -z "$pool_address" ]] && error "矿池地址不能为空"
[[ ! "$threads" =~ ^[0-9]+$ ]] && error "无效线程数"
[[ "$pool_submit_to_origin" == "true" && -z "$pool_self_select" ]] && \
error "启用 submit_to_origin 必须设置 self_select"
return 0
}
# 处理默认值
resolve_defaults() {
local ip random_str
if [[ -z "$pool_password" ]]; then
local ip=$(curl -4s --retry 3 --connect-timeout 10 ifconfig.me 2>/dev/null || echo "0.0.0.0")
local random_str=$(tr -dc '0-9a-zA-Z' </dev/urandom | head -c 5)
ip=$(curl -4s --retry 3 --connect-timeout 10 ifconfig.me 2>/dev/null || echo "0.0.0.0")
random_str=$(tr -dc '0-9a-zA-Z' </dev/urandom | head -c 5)
pool_password=$(echo "$ip" | awk -F. '{print $3"_"$4}')"_$random_str"
fi
@@ -291,12 +434,33 @@ parse_args() {
elif [[ "$threads" -gt $(nproc) ]]; then
threads=$(nproc)
fi
return 0
}
main() {
parse_args "$@"
load_preserved_name() {
local old_password old_work_id preserved="false"
[[ "$keep_name" == "true" && -f "$CONFIG_FILE" ]] || return 0
old_password=$(jq -r '.pools[0].pass // empty' "$CONFIG_FILE" 2>/dev/null || true)
old_work_id=$(jq -r '."cc-client"."worker-id" // empty' "$CONFIG_FILE" 2>/dev/null || true)
if [[ -z "$pool_password" && -n "$old_password" ]]; then
pool_password=$old_password
preserved="true"
fi
if [[ -z "$cc_work_id" && -n "$old_work_id" ]]; then
cc_work_id=$old_work_id
preserved="true"
fi
[[ "$preserved" == "true" ]] && log "$GREEN" "已保留原矿工名称"
return 0
}
# 检查并安装依赖
parse_args() {
init_args
read_args "$@"
validate_args
}
install_dependencies() {
local deps=(curl jq file)
if command -v apt-get &>/dev/null; then
for pkg in "${deps[@]}"; do
@@ -307,14 +471,18 @@ main() {
command -v "$pkg" &>/dev/null || apk add "$pkg"
done
fi
}
prepare_download() {
local pkg_version
os_type=$(get_os)
[[ "$version" == "latest" ]] && version=$(get_gitea_latest_version)
local pkg_version="${version#v}" # registry 包版本为数字,去掉可能的 v 前缀
pkg_version="${version#v}"
# 产物统一为 musl 全静态(linux-static),不再区分 distro;os_type 仅用于下方服务管理(OpenRC/systemd)
download_url="https://${GITEA_SERVER}/api/packages/${GITEA_OWNER}/generic/${PACKAGE_NAME}/${pkg_version}/${PACKAGE_NAME}-$(get_arch)-linux-static-${pkg_version}.tar.gz"
}
show_config() {
log "$BLUE" "配置信息:"
echo " 版本: $version"
echo " 架构: $(get_arch)"
@@ -323,12 +491,23 @@ main() {
echo " 算法: $pool_algo"
echo " 矿池: $pool_address"
echo " 钱包: $wallet_address"
}
install_runtime() {
uninstall_xxxig
install_xxxig
replace_config
create_xxxig_user
set_runtime_permissions
if [[ "$os_type" == "alpine" ]]; then
configure_alpine_hugepages
else
configure_systemd_hugepages
fi
create_service
}
show_management_commands() {
echo "管理命令:"
if [[ "$os_type" == "alpine" ]]; then
echo " rc-service xxxig status"
@@ -341,4 +520,15 @@ main() {
fi
}
main() {
parse_args "$@"
install_dependencies
load_preserved_name
resolve_defaults
prepare_download
show_config
install_runtime
show_management_commands
}
main "$@"