19.12 用旧版SecureCRT登录Ubuntu遭遇OSC控制序列 https://scz.617.cn/unix/202606162238.txt Q: 用旧版SecureCRT SSH登录Ubuntu 26后,bash中总能看到类似下面这种信息 08; start=2fca083b-a593-404c-8570-0dabd6441acf; machineid=ebc7387fc82944d6ba9dbe5b8470e471; user=scz; hostname=Ubuntu-26; bootid=bc81f634-419d-4443-a6c5-927297e02283; pid=00000000000000007613; type=command; cwd=/home/scz 这是哪来的? A: scz 2026-06-16 这不是PS1提示符内容,而是终端Shell Integration的OSC控制序列被错误地显示出 来。这些OSC(Operating System Command)控制序列,用于告诉支持OSC的终端某些信 息,比如 . 用户 . 主机名 . 当前目录 新版Ubuntu(24.04以后)默认启用了这套机制,某些SSH客户端或终端模拟器不支持这 些OSC序列,就将原始内容直接显示出来。 正经解决办法是升级客户端、终端模拟器,使之支持OSC序列。但会遇上不想、不便 升级的情形,此时只能从服务端解决,即不要发送OSC序列。 先找出发送OSC序列的源头 $ echo $VTE_VERSION (空) $ grep -Hn -R "PROMPT_COMMAND" /etc/profile* /etc/bash* ~/.bash* /src/etc/profile.d/80-systemd-osc-context.sh:68: # Skip if PROMPT_COMMAND= is cleared manually or by other profiles. /etc/profile.d/80-systemd-osc-context.sh:75: # Legacy bashrc will assign PROMPT_COMMAND=, which is equivalent to assigning /etc/profile.d/80-systemd-osc-context.sh:77: [ -n "$(declare -p PROMPT_COMMAND 2>/dev/null)" ] || PROMPT_COMMAND+=('') /etc/profile.d/80-systemd-osc-context.sh:80: PROMPT_COMMAND+=(__systemd_osc_context_precmdline) /etc/profile.d/vte-2.91.sh:76: # Newer bash versions support PROMPT_COMMAND as an array. In this case /etc/profile.d/vte-2.91.sh:79: # On older bash, we can only overwrite the whole PROMPT_COMMAND, so must /etc/profile.d/vte-2.91.sh:82: if [[ "$(declare -p PROMPT_COMMAND 2>&1)" =~ "declare -a" ]]; then /etc/profile.d/vte-2.91.sh:83: PROMPT_COMMAND+=(__vte_precmd) /etc/profile.d/vte-2.91.sh:84: PROMPT_COMMAND+=(__vte_osc7) /etc/profile.d/vte-2.91.sh:86: PROMPT_COMMAND="__vte_prompt_command" /etc/bash.bashrc:35: #PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' $ grep -Hn -R "VTE_VERSION" /etc/profile* /etc/bash* ~/.bash* /src/etc/profile.d/vte.csh:19:if ( ! $?prompt | ! $?tcsh | ! $?TERM | ! $?VTE_VERSION ) exit /etc/profile.d/vte-2.91.sh:23:[ "${VTE_VERSION:-0}" -ge 3405 ] || return 0 $ grep -Hn -R ";type=" /etc/profile* /etc/bash* ~/.bash* /etc/profile.d/80-systemd-osc-context.sh:61: printf "\033]3008;start=%.64s%s;type=shell;cwd=%.255s\033\\" "$systemd_osc_context_shell_id" "$(__systemd_osc_context_common)" "$(__systemd_osc_context_escape "$PWD")" /etc/profile.d/80-systemd-osc-context.sh:71: printf "\033]3008;start=%.64s%s;type=command;cwd=%.255s\033\\" "$systemd_osc_context_cmd_id" "$(__systemd_osc_context_common)" "$(__systemd_osc_context_escape "$PWD")" $ declare -p PROMPT_COMMAND declare -a PROMPT_COMMAND=([0]="" [1]="__systemd_osc_context_precmdline") $ declare -p PS0 declare -- PS0="\$(__systemd_osc_context_ps0)" 罪魁祸首应该是80-systemd-osc-context.sh,而非vte-2.91.sh。 解决办法之一 vi ~/.bashrc (针对普通用户) 在尾部增加 if [[ -n "$SSH_CONNECTION" ]]; then PROMPT_COMMAND=( "${PROMPT_COMMAND[@]/__systemd_osc_context_precmdline}" ) PS0= fi 之后,SSH登录时不再发送OSC序列,同时不影响XWindow桌面里的终端模拟器。上例 也可检查"$SSH_TTY"变量。但这样对付不了"su -"情形,原因很显然。 若确实不需要OSC序列,全局禁用最省事。比如 vi /etc/profile.d/99-disable-osc3008.sh PROMPT_COMMAND=( "${PROMPT_COMMAND[@]/__systemd_osc_context_precmdline}" ) PS0= 创建99-disable-osc3008.sh,它将在80-systemd-osc-context.sh之后执行,会清理 两个环境变量。这样做,将极大减少OSC序列,但未彻底解决。"su -"进去的一瞬间, 仍有一次OSC;exit离开"su -"时,也有一次OSC。 $ su - Password: 08;start=275368b7e16e43eeb5d78f9b8f93c233;user=scz;hostname=Ubuntu-26;machineid=ebc7387fc82944d6ba9dbe5b8470e471;bootid=bc81f634419d4443a6c5927297e02283;pid=12539;pidfdid=10420;comm=su;targetuser=root;type=session # exit logout 08;end=275368b7e16e43eeb5d78f9b8f93c233 这两次OSC不是bash发送的,而是pam_systemd.so发送的,没有配置文件改变此行为。 $ strings /usr/lib/x86_64-linux-gnu/security/pam_systemd.so | grep ";type=session" ;type=session 可以 vi /etc/pam.d/common-session 注释掉下面这行 #session optional pam_systemd.so 这将消除";type=session"所属的OSC序列,但有其他隐患,不细说。若只是自己的虚 拟测试环境,问题不大。 若不想动pam_systemd.so,另一种临时解决办法是 export TERM=dumb sudo su - su - 或 TERM=dumb sudo su - TERM=dumb su - 将TERM从vt100或其他值改成dumb,可消除所有OSC序列,但对vi之类的工具有影响, 临时应急可以,非长久之计。可以 vi ~/.bashrc (针对普通用户) alias sudo='TERM=dumb sudo' alias su='TERM=dumb su' vi /root/.bashrc if [ "$TERM" = "dumb" ]; then export TERM=vt100 fi