main.go
package main
import (
"log"
"time"
"os/exec"
)
func main() {
//実行するコマンドを設定
cmd := exec.Command("コマンド", "オプション")
//コマンドを実行するときのカレントディレクトリを設定
cmd.Dir = "コマンドを実行するときのカレントディレクトリ"
//コマンドを実行開始
if err := cmd.Start(); err != nil {
log.Printf("err: %s", err)
}
//タイマーを設定
ticker := *time.NewTicker(XXX * time.Second) //強制終了までの時間を設定
//並行処理間とステータスを共有するチャンネルを設定
exit := make(chan bool, 2)
//並行処理1:タイマーに設定された時間が経過した際に、プロセスを強制終了し、ステータスにTRUEを送信
go func() {
//無限ループでタイマーの時間経過をキャッチ
for {
select {
//タイマーに設定された時間が経過した
case <-ticker.C:
//タイマーを終了
ticker.Stop()
//cmd.ProcessStateは、cmd.Wait()するまでnil
if cmd.ProcessState == nil || !cmd.ProcessState.Exited() {
//プロセスを強制終了
if err := cmd.Process.Kill(); err != nil {
log.Printf("err: %s", err)
}
//ステータスにTRUEを送信
exit <-true
}
return
}
}
}()
//並行処理2:コマンドが実行終了するまで待ち、終了したらステータスにFALSEを送信
go func() {
//処理の終了時にステータスにFALSEを送信することを強制する
defer func() {exit <-false}()
//コマンドが実行終了するまで待つ
if err := cmd.Wait(); err != nil {
log.Printf("err: %s", err)
}
}()
//チャンネルにステータスが送信するまで待つ
isKilled := <-exit
//受信したステータスに応じて処理を分岐
if isKilled {
//プロセスが強制終了した際の処理
log.Print("killed")
} else if cmd.ProcessState.Success() {
//コマンドが正常終了した際の処理
log.Print("success")
} else {
//コマンドがエラー終了した際の処理
log.Print("fail")
}
}
参考ページ
コマンドの各種リファレンス:https://golang.org/pkg/os/exec/
タイマーのリファレンス:https://golang.org/pkg/time/#Ticker
チャンネルあれこれ:https://qiita.com/najeira/items/47539ab346fa0c00dc62
変更履歴
2017/11/07
コマンドを実行するカレントディレクトリの指定方法を、os.Chdir()からcmd.Dirの指定へ変更しました。