Cron 执行发送给它的任何程序,其方式是写入 STDERR 的任何内容都会导致内核(或我不确定的 cron)接收 SIGPIPE。这个功能是如何工作的?是 cron 发送 SIGPIPE 还是内核发送?我怎样才能获得同样的效果,而不需要在 cron 中运行某些东西?有人可以告诉我如何运行 Perl 脚本吗
#!/usr/bin/env perl
warn 'foo';
print "bar;
当它尝试将“foo”写入 STDERR 且从不写入“bar”时收到 SIGPIPE?我想看到 Perl 终止和 shell 变量$?
返回255
。
答案1
您可以通过将 STDERR 重定向到管道的写入端,然后关闭读取端来做到这一点:
#!/usr/bin/env perl
pipe R,STDERR;
close R;
warn 'foo';
print "bar";
答案2
“这个功能如何运作?”
您所描述的并不是真正的功能,而是由误解引起的功能障碍。发送 SIGPIPE 的不是 cron,而是因为您使用它的方式。
默认情况下,cron 将进程的 stdout 和 stderr 通过电子邮件发送给 crontab 的所有者发送邮件(请参阅man cron
;如果您没有安装 MTA,则输出将被丢弃),除非它们被重定向。为此,必须等待该过程完成。但是,如果您使用以下命令将流程置于后台&
:
* * * * * /bin/someprogram &
它不会等待,如果程序现在尝试写入 stdout 或 stderr,它将收到 SIGPIPE,因为管道已损坏(读取端已关闭)。[如果您的 MTA 丢失并且您有大量输出,则旧 cron 上的非后台进程也可能会发生这种情况]
所以我猜你的 crontab 中有这样的东西:
* * * * * /bin/someprogram > log.file &
这意味着 stdout 被重定向到文件,但 stderr 管道仍然损坏。这导致您得出错误的结论:“cron 执行发送给它的任何程序,其方式是写入 STDERR 的任何内容都会导致......SIGPIPE”。
您也可以通过删除后台&
或重定向 stderr 来修复 crontab:
* * * * * /bin/someprogram 1>&2&> log.file &
如果你想。 WRT 自己复制这个,正如 qqx 所说,只需关闭管道的一端,然后写入即可。