cut -cの標準出力ラインバッファリングがcut -bのバッファリングと異なるのはなぜですか?

cut -cの標準出力ラインバッファリングがcut -bのバッファリングと異なるのはなぜですか?

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

(観察-cvs -bfor 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回ですが、出力はバッファリングされます。

二つの質問、

  1. あるシステムが他のシステムと異なるのはなぜですか?
  2. 2つのcutの使用に対して出力バッファが異なるのはなぜですか?

ベストアンサー1

これはない標準出力実際、今回はバッファリングではありません。 (標準出力バッファリングのデフォルト設定は、ラインバッファ出力のみを端末に送信することです。)

まず第一に、これはアップストリームのcoreutils機能ではなく、Debianなどのシステムではこの問題は表示されません。マニュアルページと出力内容に関係なく、--help実際のアップストリームコードは同じと-c見なされます。たとえば、次のようになります。-bhttps://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システムでブロックされているとマークされますstracefread_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)'

おすすめ記事