cmd 脚本编写 go执行脚本命令示例及源码分析
简介在开发中我们可能会遇到需要在程序中调用脚本的需求卡盟,或者涉及到两个语言之间的交互cmd 脚本编写,笔者之前就遇到了需要在go中调用python的需求,然后在代码中应用了go-python3这个库,实际上在go中调用python的脚本也是一个解决之法。这片文章将介绍在go中运行shell脚本的方法以及对其源码的相应解析。程序用例
test_command.go
package learn
import (
"fmt"
"os/exec"
"testing"
)
func TestCmd(t *testing.T) {
if o, e := exec.Command("./test.sh", "1", "2").Output(); e != nil {
fmt.Println(e)
} else {
fmt.Println(string(o))
}
}
test.sh
#!/bin/bash
a=$1
b=$2
echo $a
echo $b
上面这个例子的意思是要运行test.sh这个脚本,并且入参是1,2。脚本里面写的东西相对就比较简单了,就是打印这两个入参。其实问题的关键在于exec.Command()这个方法,下面我们来刨根问底,一探究竟。源码解析
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
Path: name,
Args: append([]string{name}, arg...),
}
if filepath.Base(name) == name {
if lp, err := LookPath(name); err != nil {
cmd.lookPathErr = err
} else {
cmd.Path = lp
}
}
return cmd
}
// Base返回path的最后一个元素。
// 在提取最后一个元素之前,将删除尾部的路径分隔符。
// 如果路径为空,Base返回"."。
// 如果路径完全由分隔符组成,Base返回单个分隔符。
func Base(path string) string {
if path == "" {
return "."
}
// Strip trailing slashes.
for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
path = path[0 : len(path)-1]
}
// Throw away volume name
path = path[len(VolumeName(path)):]
// Find the last element
i := len(path) - 1
for i >= 0 && !os.IsPathSeparator(path[i]) {
i--
}
if i >= 0 {
path = path[i+1:]
}
// If empty now, it had only slashes.
if path == "" {
return string(Separator)
}
return path
}
//LookPath在由PATH环境变量命名的目录中搜索一个名为file入参的可执行文件。如果文件包含一个斜线,就会直接尝试,而不参考PATH。其结果可能是一个绝对路径或相对于当前目录的路径。
func LookPath(file string) (string, error) {