なんかするコマンド
- 一定の間隔でなんかしたいときは time.Ticker が便利
ticker.go
package main
import (
"flag"
"fmt"
"os/exec"
"strings"
"time"
)
var (
s = flag.Int("s", 1, "unit seconds")
c = flag.Int("c", 1, "unit count")
d = flag.Int("d", 1, "duration seconds")
e = flag.String("e", "", "execute command")
)
func main() {
flag.Parse()
ticker := time.NewTicker(time.Second * time.Duration(*s) / time.Duration(*c))
defer ticker.Stop()
done := make(chan bool)
go func() {
time.Sleep(time.Second * time.Duration(*d))
done <- true
}()
e := strings.Split(*e, " ")
for {
select {
case <-done:
return
case <-ticker.C:
if out, err := exec.Command(e[0], e[1:]...).Output(); err != nil {
panic(err)
} else {
fmt.Printf("%s", out)
}
}
}
}
やる
# 1 秒に 10 回のペースで 5 秒間 echo hello world する
$ go run ticker.go -s 1 -c 10 -e "echo hello world" -d 5
# 1 秒に 1000 回ペースを指定するが exec が遅いので自分の環境だと秒間 360 回程度しか実行できない
$ go run ticker.go -s 1 -c 1000 -e "echo hello world" -d 5 | wc
1837 3674 22044
Go でなんかする
- コマンド実行だと遅いので実処理部分を Go で実装する
- ここでは任意のファイルに任意の長さのログを書き出すスクリプトを作る
ticker2.go
package main
import (
"bytes"
"flag"
"os"
"time"
)
var (
s = flag.Int("s", 1, "unit seconds")
c = flag.Int("c", 1, "unit count")
d = flag.Int("d", 1, "duration seconds")
f = flag.String("f", "", "log filename")
l = flag.Int("l", 1, "log length")
)
func main() {
flag.Parse()
ticker := time.NewTicker(time.Second * time.Duration(*s) / time.Duration(*c))
defer ticker.Stop()
fd, err := os.OpenFile(*f, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer fd.Close()
txt := append(bytes.Repeat([]byte("0"), *l), []byte("\n")...)
done := make(chan bool)
go func() {
time.Sleep(time.Second * time.Duration(*d))
done <- true
}()
for {
select {
case <-done:
return
case <-ticker.C:
if _, err := fd.Write(txt); err != nil {
panic(err)
}
}
}
}
Go でやる
# 1000 件/秒で 1 秒間 500(499 + 改行) バイトのログを out.log ファイルに出力する
$ go run ticker.go -s 1 -c 1000 -d 1 -f out.log -l 499
# 毎秒 1000 件程度は楽勝
$ wc out.log
1000 1000 500000 out.log
# 100000 件/秒で 1 秒間 500 バイトのログを out.log ファイルに出力する
$ go run ticker.go -s 1 -c 100000 -d 1 -f out2.log -l 499
# 自分の環境だと毎秒 7, 8 万件程度まで実行できた
$ wc out2.log
72853 72853 36426500 out2.log
どっかでなんかやる
- Go なので Docker や Kubernetes 環境とかの Linux 向けにポータブルにビルドして実行するのが楽
# Linux 向けにビルド
GOOS=linux GOARCH=amd64 go build ticker.go
# Docker で実行
docker cp ticker $CONTAINER_ID:/path/to/ticker
docker exec $CONTAINER_ID sh -c '/path/to/ticker -s 1 -c 10 -e "echo hello world" -d 5'
# Kubernetes で実行
kubectl cp ./ticker $POD_NAME:/path/to/ticker
kubectl exec $POD_NAME -- /path/to/ticker -s 1 -c 10 -e "echo hello world" -d 5