哈德森:“是的:标准输出:断pipe”

我需要在哈德森运行一个shell脚本。 该脚本需要用户的答案。 为了给出自动答案,我做了下面的命令行:

yes | ./MyScript.sh 

这在Ubuntuterminal中运行良好。 但是当我在Hudson工作中使用相同的命令时,脚本将自动完成所有需要的工作,但是最后我得到了这两行错误:

 yes: standard output: Broken pipe yes: write error 

这导致我的哈德森工作失败。

我应该如何改变我的命令行,以便在Hudson中正常工作?

谢谢。

但是,你怎么解释,我没有得到这个错误,而本地运行脚本,但我从哈德森工作远程运行时得到错误?

当你在终端( 本地 )运行它; 当MyScript.sh已经退出时,会被SIGPIPE信号杀死,当它试图写入管道时会被杀死。

无论在Hudson陷阱中( 远程 )如何运行命令(将其处理程序设置为SIG_IGN ,可以通过运行trap命令并在输出中搜索SIGPIPE来测试它),并且不会为新的子进程恢复信号( yes和无论什么运行MyScript.sh例如, sh在你的情况)。 它会导致写入错误( EPIPE )而不是信号。 yes检测写入错误并报告。

您可以简单地忽略错误消息:

 yes 2>/dev/null | ./MyScript.sh 

您也可以针对运行管道的组件报告该错误。 在分叉子之后,缺陷是SIGPIPE不能恢复到缺省的处理程序。 当它们在POSIX系统的终端上运行时,这是程序所期望的。 虽然我不知道是否有一个标准的方法来做一个基于Java的程序。 jvm可能会引发每个写入错误的异常,所以在SIGPIPE上不会死掉对于java程序来说不是问题。

守护进程(如哈德森进程)忽略SIGPIPE信号是很常见的。 你不希望你的守护进程死掉,只是因为你正在与之通信的进程死亡,无论如何你都会检查写入错误。

在终端中运行的普通程序不会检查每个printf()的错误状态,但是如果程序关闭了管道,就会让它们死掉,例如,如果运行source | sink source | sink管道; 通常如果sink退出,你希望source进程尽快退出。

如果禁止SIGPIPE信号(如在哈德逊案例中那样),或者程序没有在接收到时死掉( yes程序没有为SIGPIPE定义任何处理程序,所以它应该在接收信号时死掉),则返回EPIPE写入错误。

我不想忽略这个错误,我想要做正确的命令或修复来摆脱错误。

如果被杀死或遇到写入错误,则进程停止 的唯一方法。 如果SIGPIPE信号被设置为忽略(由父级),并且没有其他信号杀死该进程,则yes./MyScript.sh退出时收到写入错误。 如果您使用yes程序,则没有其他选项。

SIGPIPE信号和EPIPE错误传达完全相同的信息 – 管道损坏 。 如果SIGPIPE启用了yes过程,那么你不会看到错误。 只因为你看到了; 没有新事发生。 这只是意味着./MyScript.sh退出(成功或失败 – 无所谓)。

您正试图使用​​yes程序来管道脚本? 或回声是脚本? 如果该过程通过jenkins进行,则在shell命令的末尾添加“; true”。

由于yes./MyScript.sh都可以在明确的子shell中运行,所以可以使用yes命令,将yespid发送给./MyScript.sh子shell,然后在EXIT上执行一个陷阱来手动终止yes命令。 ( EXIT上的陷阱应该始终在管道命令序列的最后一个命令的子shell中实现)。

 # avoid hangup or "broken pipe" error message when parent process set SIGPIPE to be ignored # sleep 0 or cat /dev/null: do nothing but with external command (for a shell builtin command see: help :) ( trap "" PIPE ( (sleep 0; exec yes) & echo ${!}; wait ${!} ) | ( trap 'trap - EXIT; kill "$yespid"; exit 0' EXIT yespid="$(head -n 1)" head -n 10 # replacement for ./MyScript.sh ) echo ${PIPESTATUS[*]} ) 

如果你想退出代码为0yes子shell,你也可以这样做:

 # avoid hangup or "broken pipe" error message when parent process set SIGPIPE to be ignored # set exit code of yes subshell to 0 ( trap "" PIPE ( trap 'trap - TERM; echo "kill from yes subshell ..." 1>&2; kill "${!}"; exit 0' TERM subshell_pid="$(bash -c 'echo "$PPID"')" (sleep 0; exec yes) & echo "${subshell_pid}"; wait ${!} ) | ( trap 'trap - EXIT; kill -s TERM "$subshell_pid"; exit' EXIT subshell_pid="$(head -n 1)" head -n 10 # replacement for ./MyScript.sh ) echo ${PIPESTATUS[*]} ) 

我有这个错误,我的问题不是它输出yes: standard output: Broken pipe ,而不是它返回一个错误代码。

因为我用bash严格模式运行我的脚本,包括-o pipefail ,当是“错误”时,它会导致我的脚本出错。

如何避免错误

我避免这种情况的方式是这样的:

 bash -c "yes || true" | my-script.sh 

命令是在无限循环中运行我认为这可能是解决方案:

 yes | head -1 | ./MyScript.sh #only one "Y" would be output of the command yes 

但是,我得到了同样的错误。

我们可以根据@JF Sebastian的建议将错误重定向到/ dev / null,或者通过以下命令强制执行该命令:

 yes | head -1 | ./MyScript.sh || yes 

但是,这个建议不值得赞赏。 所以,我必须创建我自己的命名管道,如下所示:

 mkfifo /tmp/my_fifo #to create the named pipe exec 3<>/tmp/my_fifo #to make the named pipe in read and write mode by assigning it to a file descriptor echo "Y" >/tmp/my_fifo #to write into the named pipe, "Y" is the default value of yes ./MyScript.sh </tmp/my_fifo #to read from the named pipe rm /tmp/my_fifo #remove the named pipe 

我期待更多有价值的解决方案和更多的解释。

这里是linux中文件描述符的解释。

谢谢