2025-02-05 10:53:26 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Daemon 函数用于将程序转换为守护进程模式(简易实现)
|
|
|
|
|
// 注意:这不是 POSIX 标准的完整守护进程实现,缺少以下标准步骤:
|
|
|
|
|
// 1. 未创建新会话(setsid)
|
|
|
|
|
// 2. 未重置文件权限掩码
|
|
|
|
|
// 3. 未改变工作目录
|
|
|
|
|
// 4. 未关闭/重定向标准输入输出
|
|
|
|
|
// 适用于简单后台需求,生产环境建议使用专业库
|
|
|
|
|
func Daemon() {
|
|
|
|
|
// 构建新的命令行参数(过滤掉 -d 参数)
|
|
|
|
|
args := make([]string, 0)
|
|
|
|
|
for _, arg := range os.Args[1:] { // 遍历原始参数(跳过第一个程序路径参数)
|
|
|
|
|
if arg != "-d" { // 过滤掉用于触发守护进程的 -d 标志
|
|
|
|
|
args = append(args, arg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新的进程命令
|
|
|
|
|
// os.Args[0] 是当前程序的执行路径
|
|
|
|
|
// args 是过滤后的新参数列表(不包含 -d)
|
|
|
|
|
cmd := exec.Command(os.Args[0], args...)
|
|
|
|
|
|
|
|
|
|
// 配置标准输入输出(注意:真正的守护进程通常需要重定向这些)
|
|
|
|
|
// 这里继承父进程的标准输入输出,实际使用时可能需要:
|
|
|
|
|
// 1. 重定向到文件
|
|
|
|
|
// 2. 指向 /dev/null
|
|
|
|
|
// 3. 使用日志系统
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
|
|
|
|
|
// 异步启动新进程(Start 而非 Run)
|
|
|
|
|
// 注意:此处未设置新进程组或会话,可能导致子进程随终端关闭
|
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
|
|
|
log.Fatalf("无法启动新实例: %v", err) // 启动失败时终止父进程
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 输出提示信息(调试用,正式版可删除)
|
2025-02-18 14:16:13 +08:00
|
|
|
|
log.Println("新实例已启动,当前进程将退出")
|
2025-02-05 10:53:26 +08:00
|
|
|
|
|
|
|
|
|
// 退出父进程,让子进程继续运行
|
|
|
|
|
// 注意:此时子进程的父进程变为 init 进程(PID 1)
|
|
|
|
|
os.Exit(0)
|
|
|
|
|
}
|