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=
を見ましたが、何も役に立ちませんでした。
そうではありません。バッファリングは、スクリプト言語がさまざまな程度の制御を提供する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