systemd.service :使用 pty 强制刷新标准输出?

systemd.service :使用 pty 强制刷新标准输出?

我有一个服务想要在 systemd 下运行。它是用 perl 编写的,如果STDOUT连接到终端,默认情况下输出是行缓冲的。 (这似乎类似于 蟒蛇

结果是journalctl -f -u my.service当缓冲区满时,输出一次到达许多行的块。

我知道我可以将服务源修改为自动刷新STDOUT$|=1在 perl 中)。

我知道我也可以使用unbuffer从期望:

-ExecStart=/my/program.pl
+ExecStart=/usr/bin/unbuffer /my/program.pl

但随后我又涉及到另一个过程,这样的“解决方案”对我来说有一种难闻的味道。 (例如“Main PID”是 的unbuffer,而不是 的/my/program.pl)。 systemd 的全部意义就是避免像这样奇怪的 shell 解决方法。

那么有什么方法可以让这些服务不加改变地运行,让它们认为它们已连接到终端,从而刷新它们的服务STDOUT?我看过StandardOutput=但没有发现任何有用的东西。

答案1

不完全是,不。缓冲是通过setbuf(3)调用为每个进程设置的,脚本语言提供不同程度的控制(TCL:完整,Perl|Python|Ruby:不完整,Shell:根本不)。您需要使用伪造终端的包装器(unbuffer、expect、tmux)或尝试不可移植的系统调用猴子修补(stdbuf)来尝试影响输出的完成方式,或向每个应用程序添加代码,以便可以输出设置为无缓冲、行缓冲或块缓冲(或语言提供的任何子集,如果有)。一些应用程序已经有相应的标志,例如-lof tcpdump,或者添加这样的代码并不难:

#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long qw(GetOptions);

GetOptions( 'l' => \my $Flag_Unbuffer ) or exit 64;

STDOUT->autoflush(1) if $Flag_Unbuffer;

print "hi\n" for 1..4;
sleep 10;

如果将其保存为lflag可执行文件,则可以通过运行以下命令来观察行为差异:

$ ./lflag | cat

或者

$ ./lflag -l | cat

相关内容