goで外部コマンド(デフォルトのコマンドやshellスクリプト)を実行するCLIツールを作ったのでその触りをまとめます。
内容は、goでCLIツール書く時の実装方法について。
やったこと
- shellスクリプトを外部コマンドとして叩く
- goの
os/exec
パッケージを利用してコマンドをひたすら記述していく
ディレクトリ構成
-- |- app.go |- test.sh
shellスクリプトを外部コマンドとして叩く
使ったシェルスクリプトはとりあえず Hello
を表示するだけ
#!bin/shell echo "Hello"
goのスクリプトはこちら
package main import ( "fmt" "os" "os/exec" ) func main() { // カレントディレクトリを移動 os.Chdir("./cmds") // コマンドを実行 .(ピリオド)は使えずにちゃんと sh コマンドを使う out, err := exec.Command("sh", "./test.sh").Output() if err != nil { fmt.Println(err.Error()) os.Exit(1) } fmt.Println(string(out)) }
実行結果
$ go run app.go Hello
できた。
パッケージを利用してコマンドをひたすら記述していく
使用パッケージ: os/exec
外部コマンド実行に際してとく使うインターフェイス
exec.Command(cmd, args).Run()
結果を出力せずに実行。戻り値はerrorexec.Command(cmd, args).Output()
実行結果で何かしら出力される場合はこちら。戻り値はoutput結果([]byte型)とerror
package main import ( "fmt" "os.exec" ) func main(){ out, err := exec.Command("ls", "-la").Output() if err != nil { fmt.Println(err.Error()) os.Exit(1) } }
引数が複数ある時
git add XXXX
等など...
この場合、exec.Command(cmd, args)
のargs に git 以下を入れるんですが、argsはslice型で取らないければなりません。
そこで git を例に取るならば add XXXX
がargsの中身なり、これはargsは配列でする必要がある。
import ( // 追加 "strings" ) func main (){ // スペースごとに区切って配列化 args := Strings.Filelds("add XXXX") // => ["add", "XXXX"] out, err := exec.Command("git", args...).Output() if err != nil { fmt.Println(err.Error()) os.Exit(1) } fmt.Pringln(string(out)) }
exec.Command は第一引数にコマンドを取り、それ以外は第2引数に入れなければならない。
goで実際にコマンドをつらつら書きながら進める場合、上記実装のようにひたすらコマンドの実行と成功の可否(outputとエラー内容)を愚直に確認しながら書いていきます。
もし処理が止まったら必ずexitしましょう。
goからshを呼ぶのはただたんにshellを書いているだけ。むしろそちらよりもgoにコマンドを実行してもらう方法の方がgoでCLIツールを書くには向いているような気がする。