在 Go 中,当 运行 exec.Command 和 /usr/bin/script 前一个命令时,会抛出一个错误: /usr/bin/script: invalid option -- 'P'
In Go, when running exec.Command with /usr/bin/script before a command, an error is thrown: /usr/bin/script: invalid option -- 'P'
我正在使用 Go 来自动执行 IBM Aspera 上传。我想在发生这种情况时捕获 stdout/stderr 百分比进度。
我运行在 ubuntu:latest
docker 图像上 运行 宁此
这是我在 go 中尝试 运行 的完整命令。
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
这就是我在 Go 项目中调用此命令的方式
cmd := exec.Command("/usr/bin/script", "-e", "-c", "'ascp", "-P <port>", "-m 3g", "-l 3g", "-i <secret>", "local_folder", "<user>@<host>:<remote-folder>'", "> percentage.txt", "2>&1")
我发现我有使用/usr/bin/script来捕获ascp命令的输出,否则我无法从[=59]捕获上传百分比=].我只能捕获成功消息和传输的总字节数。
示例 percentage.txt
输出不使用 /usr/bin/script:
Completed: 2389K bytes transferred in 1 seconds
(10275K bits/sec), in 3 files, 1 directory.
示例 percentage.txt
使用 /usr/bin/script 输出 WITH。如您所见,我能够保留上传百分比:
Script started, output log file is 'typescript'.
<sample_file> 100% 2194KB 13.3Mb/s 00:01
<sample_file> 100% 192KB 13.3Mb/s 00:01
<sample_file> 100% 3329 13.3Mb/s 00:01
Completed: 2389K bytes transferred in 1 seconds
(12268K bits/sec), in 3 files, 1 directory.
Script done.
当我直接在我的 docker 实例的 cli 上使用上面的原始命令 运行 时,我没有遇到任何问题,它按预期工作。
但是,当我尝试通过 exec.Command()
函数 运行 命令时,我收到此输出
/usr/bin/script: invalid option -- 'P'
Try 'script --help' for more information.
exit status 1
panic: exit status 1
goroutine 1 [running]:
main.main()
/project_dir/main.go:40 +0x3e7
exit status 2
当我 运行 println(cmd.String())
这是我的输出:
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
如果我将 cmd.string
输出的命令字符串复制并粘贴到我的终端,而不是 运行 通过 exec.Command()
将其粘贴,它就可以工作并且 percentage.txt
捕获上传状态。
我在这里做错了什么?为什么go的exec.Command()
不能运行这个,而我的shell提示是?
完整代码:
func main() {
f, err := os.OpenFile("percentage.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
mwriter := io.MultiWriter(f, os.Stdout)
err = os.Setenv("SHELL", "bash")
if err != nil {
return
}
cmd := exec.Command("/usr/bin/script", "-e", "-c", "'ascp", "-P <port>", "-m 3g", "-l 3g", "-i <secret>", "local_folder", "<user>@<host>:<remote-folder>'", "> percentage.txt", "2>&1")
println(cmd.String())
cmd.Stderr = mwriter
cmd.Stdout = mwriter
err = cmd.Run()
if err != nil {
println("\n\n" + err.Error() + "\n\n")
panic(err)
}
}
您有 mis-tokenized 命令行。如果这是 shell 命令:
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
那么对应的exec.Command
差不多就是:
cmd := exec.Command("/usr/bin/script", "-e", "-c", "ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>")
也就是说,命令行中用单引号括起来的所有内容都是一个参数。
使用此版本的命令,您需要自己处理输出重定向(通过读取命令的输出并将其写入文件)。
如果你真的不想处理读取命令的输出,你可以显式调用 shell:
cmd := exec.Command("/bin/sh", "-c", "/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1")
...但这通常效率较低且鲁棒性较差,因为现在您需要注意对 shell 具有特殊含义的字符(如 >
)并且您需要小心正确引用所有内容。
直接使用ascp
会带来复杂性,您将尝试解析随时可能发生变化的日志。
此SDK提供GRPC接口和Go存根。
SDK提供auto-resume个失败转账,进度监控,multi-session等...
SDK 是免费的,可以从 IBM 开发者网站下载。
我正在使用 Go 来自动执行 IBM Aspera 上传。我想在发生这种情况时捕获 stdout/stderr 百分比进度。
我运行在 ubuntu:latest
docker 图像上 运行 宁此
这是我在 go 中尝试 运行 的完整命令。
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
这就是我在 Go 项目中调用此命令的方式
cmd := exec.Command("/usr/bin/script", "-e", "-c", "'ascp", "-P <port>", "-m 3g", "-l 3g", "-i <secret>", "local_folder", "<user>@<host>:<remote-folder>'", "> percentage.txt", "2>&1")
我发现我有使用/usr/bin/script来捕获ascp命令的输出,否则我无法从[=59]捕获上传百分比=].我只能捕获成功消息和传输的总字节数。
示例 percentage.txt
输出不使用 /usr/bin/script:
Completed: 2389K bytes transferred in 1 seconds
(10275K bits/sec), in 3 files, 1 directory.
示例 percentage.txt
使用 /usr/bin/script 输出 WITH。如您所见,我能够保留上传百分比:
Script started, output log file is 'typescript'.
<sample_file> 100% 2194KB 13.3Mb/s 00:01
<sample_file> 100% 192KB 13.3Mb/s 00:01
<sample_file> 100% 3329 13.3Mb/s 00:01
Completed: 2389K bytes transferred in 1 seconds
(12268K bits/sec), in 3 files, 1 directory.
Script done.
当我直接在我的 docker 实例的 cli 上使用上面的原始命令 运行 时,我没有遇到任何问题,它按预期工作。
但是,当我尝试通过 exec.Command()
函数 运行 命令时,我收到此输出
/usr/bin/script: invalid option -- 'P'
Try 'script --help' for more information.
exit status 1
panic: exit status 1
goroutine 1 [running]:
main.main()
/project_dir/main.go:40 +0x3e7
exit status 2
当我 运行 println(cmd.String())
这是我的输出:
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
如果我将 cmd.string
输出的命令字符串复制并粘贴到我的终端,而不是 运行 通过 exec.Command()
将其粘贴,它就可以工作并且 percentage.txt
捕获上传状态。
我在这里做错了什么?为什么go的exec.Command()
不能运行这个,而我的shell提示是?
完整代码:
func main() {
f, err := os.OpenFile("percentage.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
mwriter := io.MultiWriter(f, os.Stdout)
err = os.Setenv("SHELL", "bash")
if err != nil {
return
}
cmd := exec.Command("/usr/bin/script", "-e", "-c", "'ascp", "-P <port>", "-m 3g", "-l 3g", "-i <secret>", "local_folder", "<user>@<host>:<remote-folder>'", "> percentage.txt", "2>&1")
println(cmd.String())
cmd.Stderr = mwriter
cmd.Stdout = mwriter
err = cmd.Run()
if err != nil {
println("\n\n" + err.Error() + "\n\n")
panic(err)
}
}
您有 mis-tokenized 命令行。如果这是 shell 命令:
/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1
那么对应的exec.Command
差不多就是:
cmd := exec.Command("/usr/bin/script", "-e", "-c", "ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>")
也就是说,命令行中用单引号括起来的所有内容都是一个参数。
使用此版本的命令,您需要自己处理输出重定向(通过读取命令的输出并将其写入文件)。
如果你真的不想处理读取命令的输出,你可以显式调用 shell:
cmd := exec.Command("/bin/sh", "-c", "/usr/bin/script -e -c 'ascp -P <port> -m 3g -l 3g -i <secret> local_folder <user>@<host>:<remote-folder>' > percentage.txt 2>&1")
...但这通常效率较低且鲁棒性较差,因为现在您需要注意对 shell 具有特殊含义的字符(如 >
)并且您需要小心正确引用所有内容。
直接使用ascp
会带来复杂性,您将尝试解析随时可能发生变化的日志。
此SDK提供GRPC接口和Go存根。
SDK提供auto-resume个失败转账,进度监控,multi-session等...
SDK 是免费的,可以从 IBM 开发者网站下载。