Segfaultの直前の出力が必要なため、segfaultingプログラムのデバッグに問題がありますが、出力をファイルにパイプすると、これは失われます。この回答によると: https://unix.stackexchange.com/a/17339/22615 、これは、プログラムの出力バッファがターミナルに接続されたときにすぐにフラッシュするためですが、特定の時点でのみパイプに接続されています。ここでいくつかの質問:
プログラムはどのようにstdoutが接続されているかを決定しますか?
「スクリプト」コマンドは、プログラムが端末に書き込むときと同じ動作をどのように生成しますか?
これはスクリプトコマンドなしで実現できますか?
プログラムは isatty()
標準C関数を使用して、ファイル記述子がttyデバイスに関連付けられているかどうかを確認できます(これは通常、無害なtty固有のioctl()
システムを実行します) fdがttyデバイスを指さない場合、エラーで戻る呼び出し。
[
/test
ユーティリティは、-t
演算子を使用して実行できます。
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
GNU/Linuxシステムでのlibc関数呼び出しのトレース:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
システムコールの追跡:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Fdがpipe/fifoに関連付けられているかどうかを判別するには、 fstat()
システムコール を使用できます。これは、st_mode
フィールドに次のタイプと権限が含まれる構造体を返しますそのfdで開かれたファイル。 S_ISFIFO()
標準Cマクロ をそのst_mode
フィールドで使用して、fdがpipe/fifoであるかどうかを判別できます。
fstat()
を実行できる標準ユーティリティはありませんが、これを実行できるstat
コマンドの互換性のない実装がいくつかあります。 zsh
のstat
組み込みstat -sf "$fd" +mode
を組み込み、最初の文字がタイプを表す文字列表現としてモードを返します(パイプの場合はp
)。 GNU stat
はstat -c %A - <&"$fd"
でも同じことができますが、タイプを報告するstat -c %F - <&"$fd"
もあります単独。BSDの場合stat
:stat -f %St <&"$fd"
またはstat -f %HT <&"$fd"
。
ただし、アプリケーションは通常、stdoutがパイプであるかどうかを気にしません。彼らはそれがシーク可能であることを気にするかもしれません(ただし、一般的にバッファするかどうかを決定することはありません)。
Fdがシーク可能かどうかをテストするには(パイプ、ソケット、ttyデバイスはシークできず、通常のファイルとほとんどのブロックデバイスは通常はそうです)、相対 lseek()
システムコール オフセット0(無害)。 dd
はlseek()
へのインターフェイスである標準ユーティリティですが、オフセットを要求すると実装がlseek()
をまったく呼び出さないため、このテストには使用できません。の0。
zsh
およびksh93
シェルには、組み込みのシーク演算子があります。
$ strace -e lseek ksh -c ': 1>#((CUR))' | cat
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
ksh: 1: not seekable
$ strace -e lseek zsh -c 'zmodload zsh/system; sysseek -w current -u 1 0 || syserror'
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
Illegal seek
script
コマンドは疑似端末ペアを使用してプログラムの出力をキャプチャするため、プログラムのstdout(およびstdinとstderr)は疑似端末デバイスになります。
Stdoutが端末デバイスに対するものである場合、一般的には依然としていくらかのバッファリングがありますが、それは行ベースです。 printf
/puts
およびcoは、改行文字が出力されるまで何も書き込みません。他のタイプのファイルの場合、バッファリングはブロック(数キロバイトの)によるものです。
バッファリングを無効にするいくつかのオプションがあります。ここではいくつかのQ&Aで説明されています( nbuffer または stdbuf を検索して、 カット出力をリダイレクトできません =いくつかのアプローチを提供します)socat
/script
/expect
/unbuffer
(an expect
script)/ zsh
's zpty
または、GNUまたはFreeBSDのstdbuf
のように、実行可能ファイルにコードを挿入してバッファリングを無効にします。