RHEL 7システムには非常に長いログファイルがあり、カットバッファリングについて問い合わせました。これ質問。問題はまだ存在しますが、いくつかの実験では他の問題が現れます。
私は文字単位で分割するのではなく、バイト単位で分割を使用することにしました。
1つのマシンには2つのループがあります。
for ((ii=0;ii<5;ii++)); do date; usleep 500000 ; done | cut -b 1-99
for ((ii=0;ii<5;ii++)); do date; usleep 500000 ; done | cut -c 1-99
(観察-c
vs -b
for cut
)両方ともループが進むにつれて日付を5回表示します。
他のマシンでは、このループはバイト単位で切り捨てられます。
for ((ii=0;ii<5;ii++)); do date; usleep 500000 ; done | cut -b 1-99
ループが進行中の時間を表示します。
for ((ii=0;ii<5;ii++)); do date; usleep 500000 ; done | cut -c 1-99
ループが完了するまで出力を保持します。永久に実行するように設定すると、8192バイトの出力ごとに一連の回数が表示されます。予想どおり、毎秒2回ですが、出力はバッファリングされます。
二つの質問、
- あるシステムが他のシステムと異なるのはなぜですか?
- 2つのcutの使用に対して出力バッファが異なるのはなぜですか?
ベストアンサー1
これはない標準出力実際、今回はバッファリングではありません。 (標準出力バッファリングのデフォルト設定は、ラインバッファ出力のみを端末に送信することです。)
まず第一に、これはアップストリームのcoreutils機能ではなく、Debianなどのシステムではこの問題は表示されません。マニュアルページと出力内容に関係なく、--help
実際のアップストリームコードは同じと-c
見なされます。たとえば、次のようになります。-b
https://github.com/coreutils/coreutils/blob/v9.1/src/cut.c#L483
coreutils-i18n
しかし、ロケールベースのマルチバイト文字をサポートする国際化パッチがあり、Red Hatはそのパッチを提供しているようです。
パッチは、ここで使用する別々の入力バッファリングマクロも提供しますcut -c
。
+/* Refill the buffer BUF to get a multibyte character. */
+#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM) \
+ do \
+ { \
+ if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM)) \
+ { \
+ memmove (BUF, BUFPOS, BUFLEN); \
+ BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \
+ BUFPOS = BUF; \
+ } \
+ }
+ while (0)
これはループではありませんが、fread()
EOFまで、またはバッファがいっぱいになるまでブロックされます。 (not)でプログラムを実行すると、ltrace
私が試したCentOSシステムでブロックされているとマークされますstrace
。fread_unlocked()
これについてあなたができることは何もありません。実装はstdioにBUFLEN
バイトが欲しいと伝え、それがすべてです。いいえ、入力バッファリングを無効にすると、アプリケーションに必要なものよりも先にstdio読み取りにのみ影響するため、役に立ちません。
少なくとも過去にはi18nパッチにも他の問題があるようです。https://lwn.net/Articles/535735/そしてhttps://bugzilla.redhat.com/show_bug.cgi?id=499220
ASCII文字しかない場合は、他のLinuxシステムとcut -b
同じ方法で切り替えることができます。cut -c
またはperl -C -ne 'print substr($_, 0,99)'
。