web-dev-qa-db-ja.com

Bashは2つのシェルプロンプトを書き込もうとしますか?

教育目的で、ターミナルに接続された実行中のbashプロセスのstrace出力を調べています。

私のbashプロセスのPIDは2883です。

私はタイプする

[OP@localhost ~]$ strace -e trace=openat,read,write,fork,vfork,clone,execve -p 2883 2> bash.strace

端末に。次に、bashプロセスに入り、次のやり取りを行います。

[OP@localhost ~]$ ls

出力を見ると、

strace: Process 2883 attached
read(0, "l", 1)                         = 1
write(2, "l", 1)                        = 1
read(0, "s", 1)                         = 1
write(2, "s", 1)                        = 1
read(0, "\r", 1)                        = 1
write(2, "\n", 1)                       = 1
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fec6b1d8e50) = 3917
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
write(1, "\33]0;OP@localhost:~\7", 23) = 23
write(2, "[OP@localhost ~]$ ", 22)  = 22
...

最後の2行で混乱しています。 bashが2つのシェルプロンプトを書こうとしているようです?何が起きてる?

11
extremeaxe5

_<ESC>]0;_シーケンス(straceでは_\33]0;_として表示)は、ターミナルウィンドウのタイトルを設定するためのエスケープシーケンスです。 BEL文字(_\7_)で終了しているため、最初のwriteがウィンドウタイトルを設定します。 2番目は実際のプロンプトを出力します。エスケープシーケンスは別としても、まったく同じではないことに注意してください。プロンプトには_[..]_が含まれていますが、ウィンドウタイトルにはありません。

また、最初の書き込みはstdout(fd 1、write()の最初の引数)、2番目の書き込みはstderrに行われることもわかります。 Bashはプロンプトをstderrに出力するため、最初の書き込みは別の場所から行われます。これはおそらく、Bash用のDebianのデフォルトの起動スクリプトにあるような_Prompt_COMMAND_です。そこにこのようなものがあります:

_case "$TERM" in
xterm*|rxvt*)
    Prompt_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
    ;;
*)
    ;;
esac
_

xtermまたはrxvtを実行している場合は、その_Prompt_COMMAND_を設定します。これにより、そのエスケープシーケンスがサポートされます。

24
ilkkachu