2018-08-02 Go 调用 shell 脚本如何传递参数

来源:《Go 夜读》微信群 时间:2018-08-02

问题:Go 调用 shell 脚本如何传递参数?

答:

package main

import (
    "fmt"
    "os/exec"
)

func main(){
    command := "./dir_size.sh" //脚本的路径
    cmd := exec.Command("/bin/bash", "-c", command)

    output, err := cmd.Output()
    if err != nil {
	fmt.Printf("Execute Shell:%s failed with error:%s", command, err.Error())
	return
    }
    fmt.Printf("Execute Shell:%s finished with output:\n%s", command, string(output))
}

其中 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
}

其中 name 是执行的命令,args是参数,所以传递参数可以直接写 cmd := exec.Command("/bin/bash", "-c", "参数1","参数","参数") 这样就可以,arg... 为可变参数。

要理解为什么要这么传参,就要理解 bash -c 的用法

bash -c 传参的方法: 用法: bash -c "cmd string" 通常使用 shell 去运行脚本,两种方法 bash xxx.sh,另外一种就是 bash -c "cmd string" 。 对于 bash xxx.sh,首先 bash 会在当前目录去寻找 xxx.sh ,如果找到,就直接运行,找不到则按照环境变量 $PATH 的指定路径,按顺序去找,如果找到,则执行,找不到则报错。 shell 脚本的参数 $0 就是要执行的 shell 脚本 xxx.sh, $1 就是后面紧跟 xxx.sh 的参数,$2 $3依次类推。

而对于 bash -c "cmd string"

-c If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, they are assigned to the positional parameters, starting with $0.

大致意思就是,如果用 -c 那么 bash 会从第一个非选项参数后面的字符串中读取命令,如果字符串有多个空格,第一个空格前面的字符串是要执行的命令,也就是 $0,后面的是参数,即 $1, $2…

参考

  1. bash -c 注意事项