From 5c869d5bd301b932acbd66bffebb28ef668b57cb Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 7 Feb 2020 10:34:55 +0000 Subject: [PATCH] cmd: make stats be printed on non-zero exit code This also rationalises the exit sequence so that dumping goroutines/open files happens regardless of exit error state. See: https://forum.rclone.org/t/transfer-stats-on-non-0-exit/14211 --- cmd/cmd.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 62d7de55d..01f0426db 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -226,7 +226,7 @@ func ShowStats() bool { // Run the function with stats and retries if required func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { - var err error + var cmdErr error stopStats := func() {} if !showStats && ShowStats() { showStats = true @@ -238,11 +238,11 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { } SigInfoHandler() for try := 1; try <= *retries; try++ { - err = f() - err = fs.CountError(err) + cmdErr = f() + cmdErr = fs.CountError(cmdErr) lastErr := accounting.GlobalStats().GetLastError() - if err == nil { - err = lastErr + if cmdErr == nil { + cmdErr = lastErr } if !Retry || !accounting.GlobalStats().Errored() { if try > 1 { @@ -278,15 +278,6 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { } } stopStats() - if err != nil { - nerrs := accounting.GlobalStats().GetErrors() - if nerrs <= 1 { - log.Printf("Failed to %s: %v", cmd.Name(), err) - } else { - log.Printf("Failed to %s with %d errors: last error was: %v", cmd.Name(), nerrs, err) - } - resolveExitCode(err) - } if showStats && (accounting.GlobalStats().Errored() || *statsInterval > 0) { accounting.GlobalStats().Log() } @@ -294,7 +285,7 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { // dump all running go-routines if fs.Config.Dump&fs.DumpGoRoutines != 0 { - err = pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) + err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) if err != nil { fs.Errorf(nil, "Failed to dump goroutines: %v", err) } @@ -305,15 +296,22 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { c := exec.Command("lsof", "-p", strconv.Itoa(os.Getpid())) c.Stdout = os.Stdout c.Stderr = os.Stderr - err = c.Run() + err := c.Run() if err != nil { fs.Errorf(nil, "Failed to list open files: %v", err) } } - if accounting.GlobalStats().Errored() { - resolveExitCode(accounting.GlobalStats().GetLastError()) + // Log the final error message and exit + if cmdErr != nil { + nerrs := accounting.GlobalStats().GetErrors() + if nerrs <= 1 { + log.Printf("Failed to %s: %v", cmd.Name(), cmdErr) + } else { + log.Printf("Failed to %s with %d errors: last error was: %v", cmd.Name(), nerrs, cmdErr) + } } + resolveExitCode(cmdErr) } // CheckArgs checks there are enough arguments and prints a message if not