diff --git a/modules.d/000-menu.toml b/modules.d/000-menu.toml index a195891..db454b5 100644 --- a/modules.d/000-menu.toml +++ b/modules.d/000-menu.toml @@ -10,4 +10,5 @@ sub_menus = [ "security_tools", #安全工具 "app_deployment", #应用部署 "utility_tools", #其他实用工具 -] \ No newline at end of file + "quick_presets", #快速分类 +] diff --git a/modules.d/100-quick_presets.toml b/modules.d/100-quick_presets.toml new file mode 100644 index 0000000..cf0ef41 --- /dev/null +++ b/modules.d/100-quick_presets.toml @@ -0,0 +1,75 @@ +[scripts] +# 系统快捷脚本 +ssh_key_helper = "bash <(curl -sL raw.githubusercontent.com/NodeSeekDev/NodeScriptKit/refs/heads/main/shell_scripts/system_manage/ssh_key_helper.sh)" +swap_manager = "bash <(curl -sL raw.githubusercontent.com/NodeSeekDev/NodeScriptKit/refs/heads/main/shell_scripts/system_manage/swap_manager.sh)" + +# 检测类脚本 +comprehensive_probe = "bash <(curl -sL https://run.NodeQuality.com)" +ip_quality_probe = "bash <(curl -Ls https://IP.Check.Place)" +streaming_unlock_probe = "bash <(curl -L -s check.unlock.media)" + +# 工具类脚本 +quick_docker_install = "bash <(curl -sL https://get.docker.com)" + +[[menus]] +id = "quick_presets" +title = "快速分类" +sub_menus = [ + "system_shortcuts", + "diagnostic_suite", + "tool_installers", +] + +[[menus]] +id = "system_shortcuts" +title = "系统类" +sub_menus = [ + "ssh_key_helper", + "swap_manager", +] + +[[menus]] +id = "diagnostic_suite" +title = "检测类" +sub_menus = [ + "comprehensive_probe", + "ip_quality_probe", + "streaming_unlock_probe", +] + +[[menus]] +id = "tool_installers" +title = "工具类" +sub_menus = [ + "quick_docker_install", +] + +[[menus]] +id = "ssh_key_helper" +title = "SSH 密钥助手" +script = "ssh_key_helper" + +[[menus]] +id = "swap_manager" +title = "Swap 管理" +script = "swap_manager" + +[[menus]] +id = "comprehensive_probe" +title = "综合检测" +script = "comprehensive_probe" + +[[menus]] +id = "ip_quality_probe" +title = "IP 质量检测" +script = "ip_quality_probe" + +[[menus]] +id = "streaming_unlock_probe" +title = "流媒体解锁检测" +script = "streaming_unlock_probe" + +[[menus]] +id = "quick_docker_install" +title = "Docker 安装" +script = "quick_docker_install" diff --git a/self_hosting/README.md b/self_hosting/README.md new file mode 100644 index 0000000..8bcf9d9 --- /dev/null +++ b/self_hosting/README.md @@ -0,0 +1,49 @@ +# 自建交互式脚本仓库模板 + +这个示例帮助你把 NodeScriptKit 变成"自己的脚本仓库",并允许使用者通过 `bash <(curl -sL https://your-domain/install.sh)` 一键安装、运行你的交互式菜单。 + +## 思路总览 +1. **准备自建发行包**:把你修改好的仓库打包成 tar.gz,放到自己的域名或对象存储上提供直链下载。 +2. **发布安装脚本**:把 `install-selfhost.example.sh` 填好后部署为 `https://your-domain/install.sh`,供用户一键执行。 +3. **菜单/脚本收敛**:照常在 `modules.d` 与 `shell_scripts` 中写菜单和脚本,打包时会一并发布;运行入口仍是仓库自带的 `nsk.sh`。 + +## 快速使用步骤 +1. **打包你自己的分支/仓库** + ```bash + git archive --format=tar.gz -o /tmp/my-nsk.tar.gz main + # 或针对特定分支/标签 + git archive --format=tar.gz -o /tmp/my-nsk.tar.gz my-feature-branch + ``` + +2. **上传到自己的域名** + - 上传 `/tmp/my-nsk.tar.gz` 到你能提供 HTTPS 直链的存储,例如 `https://example.com/downloads/my-nsk.tar.gz`。 + - 记住最终直链地址,后面安装脚本要用到。 + +3. **定制安装脚本并发布** + - 复制 `self_hosting/install-selfhost.example.sh` 到你的服务器上,按需修改顶部变量: + - `SELFHOST_NAME`:安装目录和命令别名前缀,默认 `my-nsk`。 + - `ARCHIVE_URL`:上一步上传的 tar.gz 直链,例 `https://example.com/downloads/my-nsk.tar.gz`。 + - 如需更换安装目录、二进制名称或配置目录,可同步调整 `INSTALL_DIR`、`BIN_NAME`、`CONFIG_DIR`。 + - 将修改后的脚本暴露为 `https://your-domain/install.sh`。 + +4. **给使用者的安装命令** + ```bash + bash <(curl -sL https://your-domain/install.sh) + ``` + - 安装脚本会: + - 下载并解压你的发行包到 `/opt/`(可配置)。 + - 在 `/usr/local/bin/` 创建指向 `nsk.sh` 的软链接。 + - 准备 `/etc/nsk` 下的配置目录(默认位置,可改)。 + +5. **发布更新** + - 重新打包、上传新的 tar.gz,然后让用户再次执行安装命令即可完成自更新。 + +## 自定义菜单/脚本小贴士 +- 菜单文件放在 `modules.d`(以 3 位数字开头控制覆盖顺序),脚本放在 `shell_scripts`。 +- `menu.toml` 的入口 `entry` 可指向你的主菜单 id;新脚本可以基于 `shell_scripts/example.v0.0.1.0417.sh` 模板。 +- 如需在 `config.toml` 中声明自己的订阅或本地路径,请将示例配置一并打包,安装后用户可直接覆盖 `/etc/nsk`。 + +## 故障排查 +- 确认 `ARCHIVE_URL` 可被 `curl -fsSL` 直接访问。 +- 如果目标机器缺少 `curl`/`tar`,安装脚本会提示补装后重试。 +- 若命令无法运行,检查 `/usr/local/bin/` 是否存在且指向正确的 `nsk.sh`。 diff --git a/self_hosting/install-selfhost.example.sh b/self_hosting/install-selfhost.example.sh new file mode 100755 index 0000000..2c55d87 --- /dev/null +++ b/self_hosting/install-selfhost.example.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -euo pipefail + +SELFHOST_NAME="${SELFHOST_NAME:-my-nsk}" +INSTALL_DIR="${INSTALL_DIR:-/opt/${SELFHOST_NAME}}" +BIN_NAME="${BIN_NAME:-${SELFHOST_NAME}}" +ARCHIVE_URL="${ARCHIVE_URL:-https://example.com/downloads/${SELFHOST_NAME}.tar.gz}" +CONFIG_DIR="${CONFIG_DIR:-/etc/nsk}" + +info() { printf "033円[1;34m[INFO]033円[0m %s\n" "$*"; } +success() { printf "033円[1;32m[DONE]033円[0m %s\n" "$*"; } +error() { printf "033円[1;31m[ERR ]033円[0m %s\n" "$*">&2; } + +require_cmd() { + if ! command -v "1ドル">/dev/null 2>&1; then + error "缺少依赖: 1ドル。请先安装后重试。" + exit 1 + fi +} + +main() { + require_cmd curl + require_cmd tar + + local sudo_cmd="" + if [ "${EUID:-$(id -u)}" -ne 0 ]; then + sudo_cmd="sudo" + fi + + info "下载自建发行包: ${ARCHIVE_URL}" + local tmpfile + tmpfile="$(mktemp)" + curl -fsSL "${ARCHIVE_URL}" -o "${tmpfile}" + + info "准备安装目录: ${INSTALL_DIR}" + ${sudo_cmd} rm -rf "${INSTALL_DIR}" + ${sudo_cmd} mkdir -p "${INSTALL_DIR}" + + info "解压文件" + ${sudo_cmd} tar -xzf "${tmpfile}" -C "${INSTALL_DIR}" --strip-components=1 + rm -f "${tmpfile}" + + info "校验主入口脚本" + if [ ! -x "${INSTALL_DIR}/nsk.sh" ]; then + ${sudo_cmd} chmod +x "${INSTALL_DIR}/nsk.sh" + fi + + info "创建全局命令 /usr/local/bin/${BIN_NAME}" + ${sudo_cmd} ln -sf "${INSTALL_DIR}/nsk.sh" "/usr/local/bin/${BIN_NAME}" + + info "确保配置目录存在: ${CONFIG_DIR}" + ${sudo_cmd} mkdir -p "${CONFIG_DIR}/modules.d/default" + ${sudo_cmd} mkdir -p "${CONFIG_DIR}/modules.d/extend" + ${sudo_cmd} mkdir -p "${CONFIG_DIR}/backup" + + success "安装完成。现在可以运行: ${BIN_NAME}" + cat </dev/null; then + error "未找到依赖: $bin,请先安装后再试。" + exit 1 + fi +} + +prompt_default() { + local prompt="1ドル" + local default="2ドル" + local value + read -r -p "${prompt} [默认: ${default}]: " value + echo "${value:-$default}" +} + +print_summary() { + local private_key="1ドル" + local public_key="2ドル" + echo + info "密钥已生成!" + echo "私钥路径: $private_key" + echo "公钥路径: $public_key" + echo "公钥内容如下,可复制到目标服务器的 authorized_keys:" + echo "---------------------------------------------" + cat "$public_key" + echo "\n---------------------------------------------" +} + +main() { + require_binary "ssh-keygen" + + local default_type="ed25519" + local key_type + key_type=$(prompt_default "选择密钥类型 (ed25519/rsa)" "$default_type") + if [[ "$key_type" != "ed25519" && "$key_type" != "rsa" ]]; then + warn "不支持的类型,已切换为 ${default_type}。" + key_type="$default_type" + fi + + local default_path="$HOME/.ssh/id_${key_type}" + local key_path + key_path=$(prompt_default "输入密钥保存路径" "$default_path") + local comment + comment=$(prompt_default "为密钥添加备注 (如邮箱)" "nsk@local") + + mkdir -p "$(dirname "$key_path")" + chmod 700 "$(dirname "$key_path")" + + local passphrase + read -r -s -p "设置密钥密码(可留空): " passphrase + echo + + if [[ -f "$key_path" ]]; then + warn "检测到已存在的密钥文件: $key_path" + read -r -p "是否覆盖?(y/N): " choice + if [[ ! "$choice" =~ ^[Yy]$ ]]; then + info "已取消操作。" + exit 0 + fi + fi + + if [[ -n "$passphrase" ]]; then + ssh-keygen -t "$key_type" -f "$key_path" -C "$comment" -N "$passphrase" + else + ssh-keygen -t "$key_type" -f "$key_path" -C "$comment" -N "" + fi + + chmod 600 "$key_path" + chmod 644 "${key_path}.pub" + + print_summary "$key_path" "${key_path}.pub" +} + +main "$@" diff --git a/shell_scripts/system_manage/swap_manager.sh b/shell_scripts/system_manage/swap_manager.sh new file mode 100644 index 0000000..2c63d18 --- /dev/null +++ b/shell_scripts/system_manage/swap_manager.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +### === 脚本描述 === ### +# 名称: swap_manager.sh +# 功能: 交互式查看、创建或删除 Swap 文件 +# 作者: NodeSeek 社区 +# 创建日期: 2025年05月13日 +# 许可证: MIT + +set -euo pipefail + +GREEN='033円[0;32m' +YELLOW='033円[0;33m' +RED='033円[0;31m' +NC='033円[0m' + +info() { printf "${GREEN}%b${NC}\n" "1ドル"; } +warn() { printf "${YELLOW}%b${NC}\n" "1ドル"; } +error() { printf "${RED}%b${NC}\n" "1ドル"; } + +require_root() { + if [[ $EUID -ne 0 ]]; then + error "请以 root 权限运行本脚本。" + exit 1 + fi +} + +show_status() { + echo "当前 Swap 状态:" + swapon --show --bytes + echo +} + +add_fstab_entry() { + local swapfile="1ドル" + if ! grep -qE "^${swapfile}[[:space:]]+none[[:space:]]+swap" /etc/fstab; then + echo -e "${swapfile}\tnone\tswap\tdefaults\t0\t0">>/etc/fstab + info "已写入 /etc/fstab 以支持开机自动挂载。" + else + warn "fstab 已包含该 Swap 记录,未重复写入。" + fi +} + +create_swap() { + local swapfile size + read -r -p "输入 Swap 文件路径 [默认 /swapfile]: " swapfile + swapfile=${swapfile:-/swapfile} + + read -r -p "输入 Swap 大小 (例如 1G / 512M) [默认 1G]: " size + size=${size:-1G} + + if [[ -e "$swapfile" ]]; then + warn "已存在同名文件: $swapfile" + read -r -p "是否覆盖并重新创建?(y/N): " choice + [[ ! "$choice" =~ ^[Yy]$ ]] && { info "已取消操作。"; return; } + swapoff "$swapfile" 2>/dev/null || true + rm -f "$swapfile" + fi + + fallocate -l "$size" "$swapfile" + chmod 600 "$swapfile" + mkswap "$swapfile" + swapon "$swapfile" + + read -r -p "是否写入 /etc/fstab 以便重启后生效?(Y/n): " persist + if [[ "$persist" =~ ^[Nn]$ ]]; then + warn "已跳过 /etc/fstab 写入,重启后需手动启用。" + else + add_fstab_entry "$swapfile" + fi + + info "Swap 创建并启用了!" + show_status +} + +remove_swap() { + local swapfile + read -r -p "输入需要删除的 Swap 文件路径 [默认 /swapfile]: " swapfile + swapfile=${swapfile:-/swapfile} + + if ! grep -q "^${swapfile} " /proc/swaps && [[ ! -f "$swapfile" ]]; then + error "未找到目标 Swap 文件: $swapfile" + return + fi + + swapoff "$swapfile" 2>/dev/null || warn "该 Swap 可能未启用或已关闭。" + sed -i "\\#^${swapfile}[[:space:]]\+none[[:space:]]\+swap#d" /etc/fstab + rm -f "$swapfile" + info "Swap 已关闭并删除。" + show_status +} + +main() { + require_root + show_status + + cat <<'menu' +请选择操作: +1) 创建/更新 Swap +2) 删除 Swap +q) 退出 +MENU + read -r -p "输入选项: " choice + case "$choice" in + 1) create_swap ;; + 2) remove_swap ;; + q|Q) info "已退出。" ;; + *) warn "无效选项,已退出。" ;; + esac +} + +main "$@"

AltStyle によって変換されたページ (->オリジナル) /