如何使用 client-go 在 Pod 的容器中执行多个命令?
How to execute multiple commands in a Pod's container with client-go?
所以我尝试使用 client-go
在 Pod 的容器上执行一个链,即多个命令,它似乎只适用于某些命令,如 ls
.
这是我试过的方法:
req := client.CoreV1().RESTClient().Post().Resource("pods").Name(pod.Name).Namespace(pod.ObjectMeta.Namespace).SubResource("exec") // .Param("container", containerName)
scheme := runtime.NewScheme()
if err := _v1.AddToScheme(scheme); err != nil {
panic(err.Error())
}
parameterCodec := runtime.NewParameterCodec(scheme)
req.VersionedParams(&_v1.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: containerName,
Command: strings.Fields("/bin/sh -c " + command),
}, parameterCodec)
exec, err := remotecommand.NewSPDYExecutor(restConfig, "POST", req.URL())
if err != nil {
panic(err.Error())
}
var stdout, stderr bytes.Buffer
err = exec.Stream(remotecommand.StreamOptions{
Stdin: nil,
Stdout: &stdout,
Stderr: &stderr,
Tty: false,
})
if err != nil {
panic(err.Error())
}
log.Printf("Output from pod: %v", stdout.String())
log.Printf("Error from pod: %v", stderr.String())
当 command
变量只是一个简单的 ls -l
时,我得到了所需的输出。但是当我尝试做类似 'ls -l && echo hello'
的事情时,它会产生错误 command terminated with exit code 2
。
如果我只输入 echo hello
,它不会输出任何内容。但是,如果我删除 Bourne Shell
前缀 /bin/sh -c
并且 Command
属性等于 string.Fields("echo hello")
,它确实会产生所需的输出 hello
,但这种方法不会让我连锁命令。
总而言之,我要做的是在 Pod 的容器上执行一系列命令。
corev1.PodExecOptions.Command
接受 []string
类型的值。
req.VersionedParams(&_v1.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: containerName,
Command: cmds,
}, parameterCodec)
其中,cmds
可以是:
cmds := []string{
"sh",
"-c",
"echo $HOME; ls -l && echo hello",
}
输出:
/root
total 68
drwxr-xr-x 2 root root 4096 Feb 24 00:00 bin
drwxr-xr-x 2 root root 4096 Feb 1 17:09 boot
drwxr-xr-x 2 root root 4096 Feb 24 00:00 mnt
drwxr-xr-x 2 root root 4096 Feb 24 00:00 opt
dr-xr-xr-x 396 root root 0 Mar 19 11:47 proc
drwx------ 2 root root 4096 Feb 24 00:00 root
.
.
hello
解释:
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]
命令 ["/bin/sh", "-c"]
表示 "run a shell, and execute the following instructions"。然后将参数作为命令传递给 shell。在 shell 脚本中,semicolon
分隔命令,如果第一个成功,&&
有条件地运行以下命令。在上面的示例中,它始终运行命令 one
,然后运行命令 two
,并且仅在命令 two
成功时才运行命令 three
。
N.B.:
对于 bash,它将类似于以下内容:
cmds := []string{
"bash",
"-c",
`export MYSQL_PWD=${MYSQL_ROOT_PASSWORD}
mysql -h localhost -nsLNE -e "select 1;" 2>/dev/null | grep -v "*"`,
},
所以我尝试使用 client-go
在 Pod 的容器上执行一个链,即多个命令,它似乎只适用于某些命令,如 ls
.
这是我试过的方法:
req := client.CoreV1().RESTClient().Post().Resource("pods").Name(pod.Name).Namespace(pod.ObjectMeta.Namespace).SubResource("exec") // .Param("container", containerName)
scheme := runtime.NewScheme()
if err := _v1.AddToScheme(scheme); err != nil {
panic(err.Error())
}
parameterCodec := runtime.NewParameterCodec(scheme)
req.VersionedParams(&_v1.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: containerName,
Command: strings.Fields("/bin/sh -c " + command),
}, parameterCodec)
exec, err := remotecommand.NewSPDYExecutor(restConfig, "POST", req.URL())
if err != nil {
panic(err.Error())
}
var stdout, stderr bytes.Buffer
err = exec.Stream(remotecommand.StreamOptions{
Stdin: nil,
Stdout: &stdout,
Stderr: &stderr,
Tty: false,
})
if err != nil {
panic(err.Error())
}
log.Printf("Output from pod: %v", stdout.String())
log.Printf("Error from pod: %v", stderr.String())
当 command
变量只是一个简单的 ls -l
时,我得到了所需的输出。但是当我尝试做类似 'ls -l && echo hello'
的事情时,它会产生错误 command terminated with exit code 2
。
如果我只输入 echo hello
,它不会输出任何内容。但是,如果我删除 Bourne Shell
前缀 /bin/sh -c
并且 Command
属性等于 string.Fields("echo hello")
,它确实会产生所需的输出 hello
,但这种方法不会让我连锁命令。
总而言之,我要做的是在 Pod 的容器上执行一系列命令。
corev1.PodExecOptions.Command
接受 []string
类型的值。
req.VersionedParams(&_v1.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: containerName,
Command: cmds,
}, parameterCodec)
其中,cmds
可以是:
cmds := []string{
"sh",
"-c",
"echo $HOME; ls -l && echo hello",
}
输出:
/root
total 68
drwxr-xr-x 2 root root 4096 Feb 24 00:00 bin
drwxr-xr-x 2 root root 4096 Feb 1 17:09 boot
drwxr-xr-x 2 root root 4096 Feb 24 00:00 mnt
drwxr-xr-x 2 root root 4096 Feb 24 00:00 opt
dr-xr-xr-x 396 root root 0 Mar 19 11:47 proc
drwx------ 2 root root 4096 Feb 24 00:00 root
.
.
hello
解释:
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]
命令 ["/bin/sh", "-c"]
表示 "run a shell, and execute the following instructions"。然后将参数作为命令传递给 shell。在 shell 脚本中,semicolon
分隔命令,如果第一个成功,&&
有条件地运行以下命令。在上面的示例中,它始终运行命令 one
,然后运行命令 two
,并且仅在命令 two
成功时才运行命令 three
。
N.B.: 对于 bash,它将类似于以下内容:
cmds := []string{
"bash",
"-c",
`export MYSQL_PWD=${MYSQL_ROOT_PASSWORD}
mysql -h localhost -nsLNE -e "select 1;" 2>/dev/null | grep -v "*"`,
},