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

19 回复

是不是 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 运行时的环境有关

还是跑 docker ,自启动方便啊

这个类似的做法,你指定用户试试 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 = &amp;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 = &amp;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: -&gt; %s ", err.Error())<br> return<br> }<br><br> err = c.clientCmd.Wait()<br> if err != nil {<br> fmt.Printf("error wait: -&gt; %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包执行系统命令时,从直接控制台运行改为服务运行后可能出现不执行的情况,这通常与权限、环境变量以及服务运行方式有关。

  1. 权限问题:服务通常以特定用户(如systemd服务下的nobody)运行,该用户可能没有足够的权限执行某些命令。检查服务运行的用户权限,并尝试提升或修改命令执行所需的权限。

  2. 环境变量:服务运行时可能不加载与终端相同的环境变量。确保服务脚本中设置了所有必要的环境变量,特别是那些影响命令执行的变量,如PATH

  3. 工作目录exec命令可能依赖于当前工作目录。在服务中,默认工作目录可能与在终端中不同。显式设置命令的工作目录,例如使用cmd.Dir = "/desired/path"

  4. 日志与错误处理:增强服务的错误处理和日志记录,以便捕获exec命令执行失败的具体原因。检查cmd.Run()cmd.CombinedOutput()返回的错误信息。

  5. 服务管理:确保服务管理器(如systemdupstart)正确配置且服务已正确启动。检查服务状态及其日志,看是否有启动失败或异常退出的记录。

通过上述步骤,通常可以定位并解决从控制台运行到服务运行后命令不执行的问题。如果问题依旧,可能需要更详细地检查服务配置或命令依赖的具体环境。

回到顶部