X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=run.go;h=fe78a87e68198abb8f63d20383394a3f50c37121;hb=7492a39768035abafa55be738649a8dd035a89bd;hp=57401ce627a54c83d6bfac2320c00a1ccc06a655;hpb=a1394bc35f4473f55d6e56afa720c490d3e7f6bd;p=goredo.git diff --git a/run.go b/run.go index 57401ce..fe78a87 100644 --- a/run.go +++ b/run.go @@ -29,6 +29,7 @@ import ( "os/exec" "path" "path/filepath" + "strconv" "strings" "sync" "syscall" @@ -64,14 +65,28 @@ var ( StderrPrefix string Jobs sync.WaitGroup - flagTrace = flag.Bool("x", false, "trace (sh -x) current targets") - flagTraceAll = flag.Bool("xx", false, fmt.Sprintf("trace (sh -x) all targets (%s=1)", EnvTrace)) - flagStderrKeep = flag.Bool("logs", false, fmt.Sprintf("keep job's stderr (%s=1)", EnvStderrKeep)) - flagStderrSilent = flag.Bool("silent", false, fmt.Sprintf("do not print job's stderr (%s=1)", EnvStderrSilent)) + flagTrace *bool + flagTraceAll *bool + flagStderrKeep *bool + flagStderrSilent *bool TracedAll bool ) +func init() { + cmdName := CmdName() + if !(cmdName == CmdNameRedo || cmdName == CmdNameRedoIfchange) { + return + } + flagTrace = flag.Bool("x", false, "trace (sh -x) current targets") + flagTraceAll = flag.Bool("xx", false, + fmt.Sprintf("trace (sh -x) all targets (%s=1)", EnvTrace)) + flagStderrKeep = flag.Bool("k", false, + fmt.Sprintf("keep job's stderr (%s=1)", EnvStderrKeep)) + flagStderrSilent = flag.Bool("s", false, + fmt.Sprintf("silent, do not print job's stderr (%s=1)", EnvStderrSilent)) +} + type RunErr struct { Tgt string DoFile string @@ -404,6 +419,8 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { FdStatus.Write([]byte{StatusRun}) } + var finished time.Time + var exitErr *exec.ExitError started := time.Now() runErr.Started = &started fdStdout, err = os.OpenFile(stdoutPath, os.O_RDWR, os.FileMode(0666)) @@ -426,12 +443,58 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { defer func() { jsRelease(shCtx, jsToken) - lockRelease() fdDep.Close() fdStdout.Close() if fdStderr != nil { fdStderr.Close() + logRecPath := path.Join(redoDir, tgt+LogSuffix+DepSuffix) + if fdStderr, err = os.OpenFile( + logRecPath, + os.O_WRONLY|os.O_CREATE, + os.FileMode(0666), + ); err == nil { + fdStderr.Truncate(0) + fields := []recfile.Field{ + {Name: "Build", Value: BuildUUID}, + {Name: "PID", Value: strconv.Itoa(cmd.Process.Pid)}, + {Name: "PPID", Value: strconv.Itoa(os.Getpid())}, + {Name: "Cwd", Value: cwd}, + } + ts := new(tai64n.TAI64N) + ts.FromTime(started) + fields = append(fields, + recfile.Field{Name: "Started", Value: tai64n.Encode(ts[:])}, + ) + ts.FromTime(finished) + fields = append(fields, + recfile.Field{Name: "Finished", Value: tai64n.Encode(ts[:])}) + fields = append(fields, recfile.Field{ + Name: "Duration", + Value: strconv.FormatInt(finished.Sub(started).Nanoseconds(), 10), + }) + fields = append(fields, recfile.Field{Name: "Cmd", Value: cmdName}) + for _, arg := range args { + fields = append(fields, recfile.Field{Name: "Cmd", Value: arg}) + } + for _, e := range cmd.Env { + fields = append(fields, recfile.Field{Name: "Env", Value: e}) + } + if exitErr != nil { + fields = append(fields, recfile.Field{ + Name: "ExitCode", + Value: strconv.Itoa(exitErr.ProcessState.ExitCode()), + }) + } + w := bufio.NewWriter(fdStderr) + _, err = recfile.NewWriter(w).WriteFields(fields...) + w.Flush() + fdStderr.Close() + if err != nil { + os.Remove(logRecPath) + } + } } + lockRelease() os.Remove(fdDep.Name()) os.Remove(fdStdout.Name()) os.Remove(tmpPath) @@ -490,9 +553,19 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { // Wait for job completion <-stderrTerm err = cmd.Wait() - finished := time.Now() + finished = time.Now() runErr.Finished = &finished if err != nil { + // Try to commit .rec anyway + if !NoSync { + fdDep.Sync() + } + os.Rename(fdDep.Name(), path.Join(redoDir, tgt+DepSuffix)) + if !NoSync { + err = syncDir(redoDir) + } + + exitErr = err.(*exec.ExitError) runErr.Err = err errs <- runErr return