go - Go 如何编写代码并执行系统命令以启动新终端?
问题描述
当我在Go代码中执行一个普通的命令时,例如ls -ls
,它可以正常执行并返回结果:
// Error handling is omitted, in fact there is error handling in my code
func main() {
for {
var stdout bytes.Buffer
cmd := exec.Command("sh","-c","ls -ls")
cmd.Stdout = &stdout
cmd.Run()
fmt.Println(stdout.String())
}
}
执行结果如下:</p>
[root@10-x-x-xx /root]# go run main.go
/usr/bin/sh -c ls -ls
stdout: total 8
4 -rw-r--r-- 1 root root 358 Aug 14 23:09 main.go
4 -rw-r--r-- 1 root root 167 Aug 14 16:07 temp.yaml
但是当我执行一个命令启动一个新终端时(不确定我的理解是否正确),程序正常返回,没有错误,没有输出,也没有跳转到新终端。
例如:nsenter -n --target PID
。这是进入网络命名空间的命令。正常情况下,它会返回一个“#”并输入成功。
// Error handling is omitted, in fact there is error handling in my code
func main() {
for {
var stdout bytes.Buffer
cmd := exec.Command("sh","-c","nsenter -n --target 123")
cmd.Stdout = &stdout
cmd.Run()
fmt.Println(stdout.String())
}
}
程序执行完成后退出,但并没有真正进入网络命名空间。
但是当我使用python时,没有这个问题,它是可执行的。
import os
os.system("nsenter -n --target 24347")
或者另一个问题,如何在Go中编写代码,以便我可以执行这段代码来ssh到其他主机,我觉得这似乎是同样的问题。
解决方案
你有几个问题。
首先,您尝试生成一个交互式命令(nsenter
默认情况下将在目标命名空间中启动一个 shell),但您还将stdout连接到一个变量,这意味着即使它有效,您也看不到任何输出直到命令退出后,这可能不是你想要的。
其次,您没有将标准输入连接到任何有用的东西,这意味着大多数交互式命令将简单地退出。
要在 Go 中启动交互式子命令,您可以编写如下内容:
package main
import (
"os"
"os/exec"
)
func main() {
cmd := exec.Command("bash", "--norc")
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "PS1=example$ ")
cmd.Run()
}
(这bash
会使用提示符启动一个 shell example$
)
这里的关键是我们将stdin、stdout和stderr连接 到父进程的相应描述符,这允许我们与子进程交互。
如果您不尝试启动交互式外壳,那么您现在拥有的就可以了。也就是说,你可以写:
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
var stdout bytes.Buffer
cmd := exec.Command("sudo", "nsenter", "-n", "--target", "2399896", "ip", "addr")
cmd.Stdout = &stdout
cmd.Run()
fmt.Println(stdout.String())
}
以上工作正常,并显示在ip addr
目标网络命名空间内运行的结果。
请注意,您可能更通常使用模块中的Output
方法
exec
:
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("sudo", "nsenter", "-n", "--target", "2399896", "ip", "addr")
stdout, err := cmd.Output()
if err != nil {
panic(err)
}
fmt.Println(string(stdout))
}
推荐阅读
- java - 如何在 JavaFx TableView 中显示值
- c# - 列表集合已修改 - 尝试使用 foreach 循环时出错
- python - MacOS:运行代码时对 IDE 和终端的不同处理?
- react-native - npm install -g expo-cli 未完成安装
- android - 如何按房间持久性库中的列总和排序?
- angular - 路由到子组件时隐藏 sidenav
- python - 根据另一列 pandas 的 300 个相邻行中的值创建新列
- reactjs - 使用钩子从数组中删除对象(useState)
- c# - 实现自定义对象的行为类似于 System.Threading.Thread.CurrentThread.CurrentCulture 中的cultureInfo
- python - 如何允许用户只编辑自己创建的对象?