Golang Go语言中 exec 控制台直接运行执行命令正常,改成服务后不运行
centos7 检查目标 ip 是否在线的代码,直接运行是正常的,但是改成 service 运行, [Install] WantedBy=multi-user.target
正常运行时,目标 ip 不在线是打印 exit status 1
现在不管在线否都是直接打印出 exit status 2
func NetWorkStatus(host string) bool {
cmd := exec.Command("ping", host, "-c", "4", "-w", "5")
fmt.Println("NetWorkStatus Start:", time.Now().Unix())
err := cmd.Run()
fmt.Println("NetWorkStatus End :", time.Now().Unix())
if err != nil {
fmt.Println(err.Error())
return false
} else {
fmt.Println("Net Status , OK")
}
return true
}
看到部分文章提示用到 ICMP ,这需要以管理员身份运行。
service multi-user.target 这还不是管理员身份么?
Golang Go语言中 exec 控制台直接运行执行命令正常,改成服务后不运行
更多关于Golang Go语言中 exec 控制台直接运行执行命令正常,改成服务后不运行的实战教程也可以访问 https://www.itying.com/category-94-b0.html
是不是 path 环境变量问题,ping 命令找不到
更多关于Golang Go语言中 exec 控制台直接运行执行命令正常,改成服务后不运行的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 连个 ping 的包都没吗?一定要调用外部程序?
自己实现一个吧,也不难
是有的 而且还有 > 1k 的 star…
目测 99%概率是因为环境变量的问题。
另外同好奇为啥不用现成的包
go run main.go 是正常的,即使程序路径改成 /usr/bin/ping ,症状也一样
域名没办法解析吧
我遇到过一次类似的错误,systemd 服务配置加个 privilege 参数就可以了,不妨试试看
都用 go 了为啥不直接发 tcp 或者 http 。。。
可以用 systemd-run 来调试排查,ICMP 需要 cap_net_raw ,systemd unit 的编写可以多问问 chatgpt ,它很擅长
err.Error 打印出来是啥?
感觉和 service 运行时的环境有关
这个类似的做法,你指定用户试试 user, err := user.Lookup(“you user name”)go<br> c.clientCmd = exec.Command(name, args...)<br> // c.clientCmd.Stdin = os.Stdin<br> // c.clientCmd.Stdout = os.Stdout<br> // c.clientCmd.Stderr = os.Stderr<br> // c.clientCmd = exec.Command("sh")<br> fmt.Println(c.clientCmd.String())<br> var err error<br> user, err := user.Lookup("you user name")<br> if err != nil {<br> fmt.Println(err, "invalid user", name)<br> return<br> }<br><br> // var ids_s, _ = user.GroupIds()<br> // ids := make([]uint32, len(ids_s), len(ids_s))<br><br> // for k, _ := range ids_s {<br> // s, _ := strconv.Atoi(ids_s[k])<br> // ids[k] = uint32(s)<br> // }<br><br> // 获取用户 id<br> uid, err := strconv.ParseUint(user.Uid, 10, 32)<br> if err != nil {<br> fmt.Println(err)<br> }<br><br> // 获取用户组 id<br> gid, err := strconv.ParseUint(user.Gid, 10, 32)<br> if err != nil {<br> fmt.Println(err)<br> }<br> c.clientCmd.SysProcAttr = &syscall.SysProcAttr{<br> // Cloneflags: syscall.CLONE_NEWUTS |<br> // syscall.CLONE_NEWIPC |<br> // syscall.CLONE_NEWPID |<br> // syscall.CLONE_NEWNS |<br> // syscall.CLONE_NEWUSER |<br> // syscall.CLONE_NEWNET,<br><br> Pdeathsig: syscall.SIGKILL, // linux 下退出后杀死子孙进程 或者设置 {Setpgid: false}<br> }<br><br> //设置进程执行用户<br> c.clientCmd.SysProcAttr.Credential = &syscall.Credential{<br> Uid: uint32(uid),<br> Gid: uint32(gid),<br> }<br><br> // c.read()<br><br> time.Sleep(time.Second * 2)<br> fmt.Println("xxxx")<br> err = c.clientCmd.Start()<br> <br> if err != nil {<br> fmt.Printf("error start: -> %s ", err.Error())<br> return<br> }<br><br> err = c.clientCmd.Wait()<br> if err != nil {<br> fmt.Printf("error wait: -> %s ", err.Error())<br> return<br> }<br><br>
为啥不用 x net 里的 icmp ,非要调命令行
少用这种 cmd ,根本没有鲁棒性,而且不好处理。
https://github.com/prometheus-community/pro-bing
用了 pro-bing 库
centos7 下面 root 用户和服务启动
错误提示都是 socket: permission denied
关了 selinux 也不行
奇了怪 ///
centos ? selinux 没有关?
在Go语言中,使用exec
包执行系统命令时,从直接控制台运行改为服务运行后可能出现不执行的情况,这通常与权限、环境变量以及服务运行方式有关。
-
权限问题:服务通常以特定用户(如
systemd
服务下的nobody
)运行,该用户可能没有足够的权限执行某些命令。检查服务运行的用户权限,并尝试提升或修改命令执行所需的权限。 -
环境变量:服务运行时可能不加载与终端相同的环境变量。确保服务脚本中设置了所有必要的环境变量,特别是那些影响命令执行的变量,如
PATH
。 -
工作目录:
exec
命令可能依赖于当前工作目录。在服务中,默认工作目录可能与在终端中不同。显式设置命令的工作目录,例如使用cmd.Dir = "/desired/path"
。 -
日志与错误处理:增强服务的错误处理和日志记录,以便捕获
exec
命令执行失败的具体原因。检查cmd.Run()
或cmd.CombinedOutput()
返回的错误信息。 -
服务管理:确保服务管理器(如
systemd
、upstart
)正确配置且服务已正确启动。检查服务状态及其日志,看是否有启动失败或异常退出的记录。
通过上述步骤,通常可以定位并解决从控制台运行到服务运行后命令不执行的问题。如果问题依旧,可能需要更详细地检查服务配置或命令依赖的具体环境。