Bash
Bash 嘗試編寫兩個 shell 提示?
出於教育目的,我正在查看連接到終端的正在執行的 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 ...
我對最後兩行感到困惑。看來 bash 正在嘗試編寫兩個 shell 提示?這裡發生了什麼?
該
*<ESC>*]0;
序列(顯示為\33]0;
strace)是設置終端視窗標題的轉義序列。它以 BEL 字元 (\7
) 結束,因此第一個write
設置視窗標題。第二個列印實際提示。請注意,即使除了轉義序列之外,它們也不完全相同。提示有周圍[..]
,而視窗標題沒有。我們還可以看到,第一次寫入到 stdout(fd 1,第一個參數到
write()
),第二次寫入到 stderr。Bash 將提示列印到 stderr,因此第一次寫入來自其他地方。這可能是某個地方PROMPT_COMMAND
,就像 Debian 的 Bash 預設啟動腳本中的那個。裡面有這樣的東西:case "$TERM" in xterm*|rxvt*) PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' ;; *) ;; esac
它設置
PROMPT_COMMAND
如果執行xterm
orrxvt
,它應該支持該轉義序列。