我在Go程序上遇到了麻烦,该程序本应捕获SIGTERM并正常关闭。我可以看到它启动了关闭过程,但是随后突然退出而没有完成关闭过程。我在各个地方放置了一些日志记录,可以看到它们没有在stdout中打印任何内容。这是一个代码段和结果:
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
select {
case <-sigs:
signal.Stop(sigs)
log.Info().Msg("runsomething: SIGTERM caught")
close(stopC)
cancel()
log.Info().Msg("Stopping all goroutines")
// This sleep doesn't have any effect when shutdown via SIGTERM
time.Sleep(time.Second * 2)
log.Info().Msg("THIS SHOULD PRINT, WHY DOESNT IT?")
case <-doneC:
}
// This sleep doesn't have any effect when shutdown via SIGTERM nor
// does the following log print
time.Sleep(time.Second * 2)
log.Info().Msg("runsomething: DONE")
这是正常完成的结果:
./runsomething
May 5 09:46:35.000 INF runsomething started
May 5 09:46:37.000 INF Summarizing results and exiting
May 5 09:46:37.000 INF Run results COMPLETED
May 5 09:46:39.000INF runsomething: DONE
以下是带有中断的结果:
May 5 09:39:48.000 INF runsomething started
^CMay 5 09:39:50.000 INF runsomething: SIGTERM caught
May 5 09:39:50.000 INF Stopping all goroutines
May 5 09:39:50.000 INF GracefulShutdown: Started
缺少几条输出线。鉴于上面的代码段,我希望看到:
...continued from above...
May 5 09:39:50.000 INF THIS SHOULD PRINT, WHY DOESNT IT? The sleep below also isn't run?
May 5 09:39:50.000 INF GracefulShutdown: Completed
May 5 09:39:50.000 INF runsomething: DONE
time.Sleep()
呼叫似乎不起作用。初始日志显示为GracefulShutdown: Started
后,程序无提示退出之前没有暂停。我尝试用一个更小的示例来重现该问题,该示例模仿上面的代码,但是它按预期工作。我将不胜感激,也可以尝试其他疑难解答步骤。
编辑:最后执行的语句是调试日志记录语句。当我注释掉其后的fmt.Printf
时,程序将按预期工作。注意:它与上面的log语句打印相同的[]byte
。
rsjson, err := json.Marshal(runSummary)
if err != nil {
log.Error().Err(err).Msgf("error marshaling RunSummary into string: %+v.\n")
return
}
// TODO: debug stuff, only the printf should remain
log.Info().Msgf("Run results: \n\n%s\n", rsjson)
// TODO Removed Printf to see if it makes a difference
// fmt.Printf("%s\n", string(rsjson))
log.Info().Msgf("Run results COMPLETED")
我了解我做错了。事实证明代码正在运行。尽管我使用的命令与我最初提出的问题不完全相同。如果我按照上面最初发布的命令运行命令:
./runsomething
它在被中断(^C
)时可以正常工作。
但是,实际的命令像这样通过管道传递输出:
./runsomething | jq .
这表现出上述行为,未打印输出。令我感到困惑的是,日志记录将进入stderr,因此看起来似乎所有工作都在最后fmt.Printf
之外。再考虑一下,我取消了整个管道,即runsomething
和jq
,而不仅仅是runsomething
。 h!