问题描述
我需要在hudson中运行一个shell脚本。该脚本需要用户的回答。为了给出自动答案,我执行了以下命令行:
yes | ./MyScript.sh
这在Ubuntu终端中运行良好。但是当我在Hudson作业中使用相同的命令时,脚本将自动化并完成所有必需的工作,但最后,我得到以下两行错误:
yes: standard output: Broken pipe
yes: write error
这导致我的哈德森工作失败。
我应该如何更改命令行才能在Hudson中正常工作?
最佳解决思路
But how would you explain that I dont get this error while running the script locally, but I get the error when running it remotely from a Hudson job?
当你在终端(本地)运行它时; yes
被SIGPIPE
信号杀死,该信号在MyScript.sh
已经退出时尝试写入管道时生成。
无论在Hudson中运行命令(远程)捕获该信号(将其处理程序设置为SIG_IGN
,您可以通过运行trap
命令并在输出中搜索SIGPIPE来测试它)并且它不会恢复新子进程的信号(yes
和无论如何运行MyScript.sh
,例如你的sh
)。它导致写入错误(EPIPE
)而不是信号。 yes
检测写入错误并报告。
您可以简单地忽略错误消息:
yes 2>/dev/null | ./MyScript.sh
您还可以针对运行管道的组件报告错误。该错误是在子分叉后不将SIGPIPE恢复到默认处理程序。这是程序在POSIX系统上的终端中运行时所期望的。虽然我不知道是否有一种标准方法可以用于java-based程序。 jvm
可能会引发每个写入错误的异常,因此SIGPIPE上的not-dying对于java程序来说不是问题。
像哈德森过程这样的守护进程通常忽略SIGPIPE信号。您不希望您的守护程序死亡只是因为您正在与之通信的进程死亡,并且您无论如何都会检查写入错误。
编写为在终端中运行的普通程序不会检查每个printf()
的状态是否有错误,但是如果程序在管道中死亡,您希望它们死掉,例如,如果您运行source | sink
管道;通常,如果sink
退出,您希望source
进程尽快退出。
如果SIGPIPE
信号被禁用(在hudson的情况下看起来像),或者如果程序在接收时不死,则返回EPIPE
写入错误(yes
程序没有为SIGPIPE
定义任何处理程序,因此它应该在接收到信号时死亡)。
I don’t want to ignore the error, I want to do the right command or fix to get rid of the error.
如果yes
进程被终止或遇到写入错误,它就会停止。如果SIGPIPE
信号被设置为忽略(由父级),并且没有其他信号终止该过程,则yes
在./MyScript.sh
出口处收到写入错误。如果您使用yes
程序,则没有其他选项。
SIGPIPE
信号和EPIPE
错误传达完全相同的信息 – 管道坏了。如果为yes
进程启用了SIGPIPE
,那么您将看不到错误。只因为你看到它;什么都不会发生。它只是意味着./MyScript.sh
退出(成功或失败 – 无所谓)。