出于教育目的,我正在查看连接到终端的正在运行的 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 默认启动脚本中的那个。里面有这样的东西:它设置
PROMPT_COMMAND
如果运行xterm
orrxvt
,它应该支持该转义序列。