Skip to content

Instantly share code, notes, and snippets.

@Regentag
Created December 2, 2018 11:26
Show Gist options
  • Save Regentag/823b037d8906b11835baba84107e34d2 to your computer and use it in GitHub Desktop.
Save Regentag/823b037d8906b11835baba84107e34d2 to your computer and use it in GitHub Desktop.
Save console output and replay.
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
)
// Console Recorder
// 저장 : conrec save [filename] [process] [args...]
// 재생 : conrec play [filename]
func main() {
// check args
if len(os.Args) < 3 {
fmt.Println("잘못된 인자")
return
}
switch os.Args[1] {
case "save":
save()
case "play":
play()
default:
fmt.Println("잘못된 명령", os.Args[2])
}
}
func save() {
saveFile := os.Args[2]
execPath := os.Args[3]
// 저장 파일 준비
f, fe := os.Create(saveFile)
if fe != nil {
fmt.Println("파일을 저장하기 위해 준비할 수 없습니다.")
return
}
defer f.Close()
w := bufio.NewWriter(f)
// Execute command
cmd := exec.Command(execPath, os.Args[4:]...)
stdout, e := cmd.StdoutPipe()
if e != nil {
fmt.Println("오류: ", e)
return
}
if err := cmd.Start(); err != nil {
fmt.Println("오류: ", err)
return
}
fmt.Println("저장이 시작됩니다. 중지하려면 Ctrl+C를 누르십시오.")
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
// Install signal handler
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
// 실행된 명령의 출력 저장 처리
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
str := fmt.Sprintf("%d\t%s\n", makeTimestamp(), line)
w.WriteString(str)
fmt.Print(str)
}
cmd.Wait()
// 명령이 종료되면 저장 중지를 위해 시그널 전송.
sigs <- syscall.SIGTERM
}()
<-done
cmd.Process.Kill()
w.Flush()
fmt.Println("저장이 중지되었습니다.")
}
func play() {
dataFile := os.Args[2]
f, fe := os.Open(dataFile)
if fe != nil {
return
}
defer f.Close()
var firstLine int64
var beg int64
var nextBuff string
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if len(nextBuff) > 0 {
fmt.Println(nextBuff)
}
now := makeTimestamp()
line := scanner.Text()
msec, text, _ := splitTime(line)
if firstLine == 0 {
firstLine = msec
beg = now
}
if (now - beg) == (msec - firstLine) {
fmt.Println(text)
nextBuff = ""
} else {
nextBuff = text
}
stopMsecs := time.Duration((msec-firstLine)-(now-beg)) * time.Millisecond
time.Sleep(stopMsecs)
}
if len(nextBuff) > 0 {
fmt.Println(nextBuff)
}
}
func splitTime(line string) (int64, string, error) {
// find first tab
tab := strings.Index(line, "\t")
if tab < 1 {
return 0, line, fmt.Errorf("")
}
msecStr := line[0:tab]
msec, e := strconv.ParseInt(msecStr, 10, 64)
return msec, line[tab+1:], e
}
func makeTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment