web-dev-qa-db-ja.com

systemd.service:ptyを使用して、stdoutのフラッシュを強制しますか?

Systemdで実行したいサービスがあります。これはPerlで書かれており、STDOUTが端末に接続されている場合、デフォルトで出力はラインバッファリングされます。 (これは pythonに似ています

その結果、バッファがいっぱいになると、一度に多くの行のチャンクで出力がjournalctl -f -u my.serviceに到着します。

サービスソースを変更してSTDOUT(Perlでは$|=1)を自動フラッシュできることはわかっています。

unbuffer from expect :も使用できることを知っています。

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

しかし、その後、別のプロセスが必要になり、そのような「解決策」は私にとって悪臭を放ちます。 (たとえば、「メインPID」はunbufferのものであり、/my/program.plのものではありません)。そして、systemdの要点は、このような奇妙なシェルの回避策を回避することです。

それで、そのようなサービスを変更せずに実行して、端末に接続されていると思わせ、STDOUTをフラッシュする方法はありますか? StandardOutput= を見ましたが、何も役に立ちませんでした。

1
Peter V. Mørch

そうではありません。バッファリングは、スクリプト言語がさまざまな程度の制御を提供するsetbuf(3)呼び出しを介してプロセスごとに設定されます(TCL:完全、Perl | Python | Ruby:不完全、シェル:まったくない)。ターミナルを偽造するラッパー(unbuffer、expect、tmux)を使用するか、移植不可能なシステムコールモンキーパッチ(stdbuf)を試して、出力の実行方法に影響を与えたり、それぞれにコードを追加したりする必要があります。出力をバッファなし、行バッファ、またはブロックバッファ(または言語が提供するサブセットがある場合)に設定できるようなアプリケーション。一部のアプリケーションには、このためのフラグがすでにあります。 -l of 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
2
thrig