bash(プロンプト、ユーザー入力、結果)のすべての出力をファイルにリダイレクトしようとしています。
例:
/bin/bash > file.txt 2>&1
私はこれがうまくいくと思いましたが、プロンプトを得ませんでした。誰かが私が間違っていることを教えてもらえますか?
答え1
Bashはインタラクティブモードでのみプロンプトを出力します。つまり、通常はターミナル(Linuxの場合/ dev / tty)に出力されます。 /dev/stdoutでも/dev/stdinでもありません:)
今はわかりませんが、完全な機能を備えたttyが利用できない場合、bashは制限された対話モードを許可すると想像できます。それから私は予想される標準出力に書き込むメッセージを表示します。まだテストしていません。
優れた概念証明:
(for a in some set of words; do echo $a > /dev/tty; done) 2>&1 > /dev/null
リダイレクトがないかのように1..10のみ出力されます。プロンプトと同様に、出力を端末に直接送信します(ターミナルがないと失敗します)。
Tip: みんな集めてみたいなら確認してみてください。
- スクリプト(1)スクリプトで再生(SSHクライアントから実行ログをキャプチャしますか?またはスクリプトシェル録音再生- FAQのようです)
- これPROMPT_COMMAND変数これにより、プロンプト表示の副作用としてコンテンツをstdoutとして印刷できます。
set -o xtrace
(別名set -x
などbash -x
)一般ロギング用氏名
答え2
最も簡単な方法は
bash -i >/tmp/logfile 2>&1
コマンドを入力すると、Bashはすべてを書き、/tmp/logfile
コマンドを実行し続けますが、端末には何も表示されません。終了時にCtrl+を押すDか、を入力してターミナルセッションを終了できますexit
。
リダイレクトなしで同じタスクを実行すると、stderr
helloメッセージのみがファイルに書き込まれ、他のすべての内容は現在の端末で実行されます。したがって、bashがプロンプトストリーム(および次のコマンドの両方)を出力することに関する質問に対する答えは次のとおりです。標準エラー。
ああ、そうです。この-i
パラメータは、bashが対話型モードで実行されるように強制します。その人の言葉を聞かないでください。これを行うために魔法は必要ありません。
答え3
プロンプトはtruss(Solarisの場合)に示すようにstderrに書き込まれます。
$ truss -ft write -p 10501
10501: write(2, " d", 1) = 1
10501: write(2, " a", 1) = 1
10501: write(2, " t", 1) = 1
10501: write(2, " e", 1) = 1
10501: write(2, "\n", 1) = 1
10521: write(1, " S a t u r d a y , S e".., 46) = 46
10501: Received signal #18, SIGCLD [caught]
10501: siginfo: SIGCLD CLD_EXITED pid=10521 status=0x0000
10501: write(2, " $ ", 2) = 2
答え4
対話型モードでは、bashはプロンプトをstderrに出力します。次のstraceコマンドはこれを示しています(--norc
別のプロンプトを設定する〜/ .bashrcのオプションが私のカスタムプロンプトをオーバーライドすると解釈されないことを確認してください)。
$ export PS1="MYPROMPT> "
MYPROMPT> strace -f -- bash --norc
execve("/usr/bin/bash", ["bash"], 0x7ffcd83805b0 /* 59 vars */) = 0
[...]
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3
[...]
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
[...]
write(2, "MYPROMPT> ", 10MYPROMPT> ) = 10 <----- prompt written into stderr (fd = 2)
pselect6(1, [0], NULL, NULL, NULL, {[], 8}
stdoutとstderrをファイルにリダイレクトするのと同じコマンドは、プロンプトは印刷されませんが、シェルがコマンドを受け入れることを示します。
MYPROMPT> strace -f -- bash --norc > /tmp/shout 2> /tmp/sherr
date
別の端末でファイルを表示します。内容は呼ぶ例:
$ cat /tmp/shout
dim. 04 sept. 2022 16:19:24 CEST <------- Result of the date command entered above
内容はシェル例:
$ cat /tmp/sherr
execve("/usr/bin/bash", ["bash", "--norc"], 0x7ffe73ea5da8 /* 59 vars */) = 0
[...]
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3
[...]
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, 0x7ffc43496b30) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
read(0, <-------- No prompt is displayed
しかし、-i
bashコマンドラインにオプションを追加するのと同じことをする場合:
MYPROMPT> strace -f -- bash --norc -i > /tmp/shout 2> /tmp/sherr
stderrにプロンプトを表示する:
$ cat /tmp/sherr
execve("/usr/bin/bash", ["bash", "--norc", "-i"], 0x7ffd8c1fa520 /* 59 vars */) = 0
[...]
ioctl(2, TCGETS, 0x7ffe1a8465f0) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
ioctl(0, TIOCGWINSZ, {ws_row=37, ws_col=155, ws_xpixel=0, ws_ypixel=0}) = 0
[...]
write(2, "MYPROMPT> ", 10MYPROMPT> ) = 10 <------ Prompt displayed on stderr (fd = 2)
pselect6(1, [0], NULL, NULL, NULL, {[], 8}