package main import ( "encoding/json" "errors" "io" "log" "os" "os/exec" "path" "strconv" "time" ) func copy(src, dst string) error { fi, err := os.Stat(src) if err != nil { return err } inmode := fi.Mode() in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.Create(dst) if err != nil { return err } defer out.Close() copied, err := io.Copy(out, in) if err != nil { return err } if copied < fi.Size() { return errors.New("copy not completed") } if err := out.Sync(); err != nil { return err } if err := out.Chmod(inmode); err != nil { return err } return nil } func main() { logfile, _ := os.OpenFile("replacer.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) defer logfile.Close() stdlog := log.New(logfile, "", log.LstdFlags) args := os.Args // args[1] : 나를 시작한 pid. pid가 종료될 때 까지 기다림 // args[2] : target 폴더 // args[3:] : 다시 시작할 때 넘겨줄 arguments(프로세스 이름 포함) stdlog.Println(args) pid, err := strconv.Atoi(args[1]) if err != nil { stdlog.Fatal(err) } for { stdlog.Println("wait for terminating of", args[3]) proc, err := os.FindProcess(pid) if err != nil { stdlog.Fatal(err) } state, _ := proc.Wait() if state == nil { break } time.Sleep(time.Second) } selfext, _ := os.Executable() selfext = path.Base(selfext) nextArgs := args[4:] entries, _ := os.ReadDir(args[2]) for _, ent := range entries { if ent.Name() == selfext { continue } if ent.IsDir() { if err := os.MkdirAll(ent.Name(), 0775); err != nil { stdlog.Fatal(err) } } else { if ent.Name() == "@args" { var tempArgs []string argfile, _ := os.Open(path.Join(args[2], ent.Name())) dec := json.NewDecoder(argfile) if dec.Decode(&tempArgs) == nil { nextArgs = tempArgs } } else if err := copy(path.Join(args[2], ent.Name()), ent.Name()); err != nil { stdlog.Println("copy failed :", path.Join(args[2], ent.Name()), ent.Name()) stdlog.Fatal(err) } } } err = os.RemoveAll(args[2]) if err != nil { stdlog.Println("os.RemoveAll failed :", args[2], err) } err = os.Chmod(args[3], 0775) if err != nil { stdlog.Println("os.Chmod failed :", err) } stdlog.Println("exec.Command :", args) cmd := exec.Command(args[3], nextArgs...) cmd.Start() }