<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Systemd on KnightLi的博客</title>
        <link>https://knightli.com/tags/systemd/</link>
        <description>Recent content in Systemd on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Tue, 23 Jun 2026 16:58:23 +0800</lastBuildDate><atom:link href="https://knightli.com/tags/systemd/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>OSC 3008 是什么：systemd 终端上下文信令和乱码排障</title>
        <link>https://knightli.com/2026/06/23/osc-3008-systemd-terminal-context-explained/</link>
        <pubDate>Tue, 23 Jun 2026 16:58:23 +0800</pubDate>
        
        <guid>https://knightli.com/2026/06/23/osc-3008-systemd-terminal-context-explained/</guid>
        <description>&lt;p&gt;OSC 3008，全名是 &lt;code&gt;Hierarchical Context Signalling&lt;/code&gt;，是 UAPI Group 规范中的 UAPI.15。它定义了一组新的终端控制序列，让程序可以把当前终端里的“上下文层级”告诉终端模拟器。&lt;/p&gt;
&lt;p&gt;简单说，它想解决的是一个现代 Linux 终端里越来越常见的问题：你到底在哪一层？&lt;/p&gt;
&lt;p&gt;比如你可能从本机 SSH 到服务器，再进入容器，随后用 &lt;code&gt;run0&lt;/code&gt; 或类似工具提权执行命令。对用户来说，这是一个连续的终端窗口；但对终端模拟器来说，如果没有额外信号，它很难准确知道当前输出来自本机、远端、容器，还是提权后的命令。&lt;/p&gt;
&lt;p&gt;OSC 3008 就是为这类场景设计的。UAPI 官方规范说明，它允许终端模拟器跟踪屏幕上当前内容的上下文层级。systemd 也已经提供了对应实现，脚本名通常是 &lt;code&gt;80-systemd-osc-context.sh&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;官方规范：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UAPI.15 OSC 3008: Hierarchical Context Signalling：https://uapi-group.org/specifications/specs/osc_context/&lt;/li&gt;
&lt;li&gt;systemd &lt;code&gt;80-systemd-osc-context.sh&lt;/code&gt;：https://github.com/systemd/systemd/blob/main/profile.d/80-systemd-osc-context.sh&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;为什么需要-osc-3008&#34;&gt;为什么需要 OSC 3008
&lt;/h2&gt;&lt;p&gt;传统终端只负责显示程序输出，最多通过标题、颜色、提示符来辅助区分环境。问题是，现代终端会话经常是多层嵌套的：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;本机 shell -&amp;gt; SSH 远程服务器 -&amp;gt; Docker/Podman/systemd-nspawn 容器 -&amp;gt; run0 提权命令
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果只靠 &lt;code&gt;PS1&lt;/code&gt; 提示符，很容易遇到几个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提示符只能表示当前 shell，很难完整表达嵌套层级。&lt;/li&gt;
&lt;li&gt;不同 shell、不同发行版、不同用户配置会互相覆盖。&lt;/li&gt;
&lt;li&gt;终端模拟器无法可靠知道哪些输出属于哪个上下文。&lt;/li&gt;
&lt;li&gt;某些控制序列在不兼容终端里会直接变成乱码。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OSC 3008 提供了一种更结构化的方式：由实际进入上下文的程序发送 &lt;code&gt;start&lt;/code&gt; 序列，由退出上下文的程序发送 &lt;code&gt;end&lt;/code&gt; 序列。终端模拟器解析后，就能知道当前输出属于哪个上下文节点。&lt;/p&gt;
&lt;h2 id=&#34;它传递哪些信息&#34;&gt;它传递哪些信息
&lt;/h2&gt;&lt;p&gt;OSC 3008 本质上是一组 OSC 转义序列。规范里定义了两类核心命令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OSC &amp;#34;3008;start=...&amp;#34; ST
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OSC &amp;#34;3008;end=...&amp;#34; ST
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;start&lt;/code&gt; 表示一个上下文开始、更新或重新成为当前上下文；&lt;code&gt;end&lt;/code&gt; 表示一个上下文结束。&lt;/p&gt;
&lt;p&gt;每个上下文可以带一些元数据字段。常见字段包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;type=&lt;/code&gt;：上下文类型，例如 &lt;code&gt;shell&lt;/code&gt;、&lt;code&gt;command&lt;/code&gt;、&lt;code&gt;remote&lt;/code&gt;、&lt;code&gt;container&lt;/code&gt;、&lt;code&gt;vm&lt;/code&gt;、&lt;code&gt;elevate&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user=&lt;/code&gt;：发出序列的 UNIX 用户名。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hostname=&lt;/code&gt;：主机名。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;machineid=&lt;/code&gt;：来自 &lt;code&gt;/etc/machine-id&lt;/code&gt; 的机器 ID。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bootid=&lt;/code&gt;：来自 &lt;code&gt;/proc/sys/kernel/random/boot_id&lt;/code&gt; 的启动 ID。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pid=&lt;/code&gt;：发出序列的进程 PID。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;comm=&lt;/code&gt;：进程名。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cwd=&lt;/code&gt;：当前工作目录，主要用于 &lt;code&gt;shell&lt;/code&gt; 或 &lt;code&gt;command&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cmdline=&lt;/code&gt;：被交互式调用的命令行。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;container=&lt;/code&gt;、&lt;code&gt;vm=&lt;/code&gt;：容器或虚拟机名称。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;targetuser=&lt;/code&gt;、&lt;code&gt;targethost=&lt;/code&gt;：目标用户或远程目标主机。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些字段不是为了给用户直接看，而是给终端模拟器解析。支持得好的终端会“吃掉”这些控制序列，并用它们改善界面体验。&lt;/p&gt;
&lt;h2 id=&#34;能带来什么好处&#34;&gt;能带来什么好处
&lt;/h2&gt;&lt;p&gt;如果终端模拟器支持 OSC 3008，它可以做不少更聪明的事情。&lt;/p&gt;
&lt;p&gt;第一，标记不同上下文的输出。比如容器内输出、提权命令输出、远程 SSH 输出，可以有不同的背景、边框或提示。&lt;/p&gt;
&lt;p&gt;第二，显示层级面包屑。终端可以知道当前大致处于：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;本机 -&amp;gt; 远程主机 -&amp;gt; 容器 -&amp;gt; root 命令
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这比单靠窗口标题或 &lt;code&gt;PS1&lt;/code&gt; 更稳定。&lt;/p&gt;
&lt;p&gt;第三，辅助窗口标题、标签页和右键菜单。终端可以根据当前上下文更新标签页标题，也可以在某段输出上提供“在同一目录打开 shell”之类操作。&lt;/p&gt;
&lt;p&gt;第四，减少误操作。比如当前已经进入生产环境容器并切到 root，终端可以做更醒目的提示，降低在错误环境执行危险命令的概率。&lt;/p&gt;
&lt;h2 id=&#34;systemd-是怎么接入的&#34;&gt;systemd 是怎么接入的
&lt;/h2&gt;&lt;p&gt;systemd 的实现主要在 &lt;code&gt;80-systemd-osc-context.sh&lt;/code&gt; 里。这个脚本会通过 profile 机制加载，并在 Bash 交互环境里设置相关函数和提示符钩子。&lt;/p&gt;
&lt;p&gt;常见路径可能是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/etc/profile.d/80-systemd-osc-context.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/usr/lib/systemd/profile.d/80-systemd-osc-context.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;不同发行版的实际位置可能不同。systemd 源码中的注释说明，这个文件会通过 &lt;code&gt;systemd-tmpfiles&lt;/code&gt; 激活，把它链接到 &lt;code&gt;/etc/profile.d/&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;在 Bash 里，它会使用类似这些函数名：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_escape
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_common
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_precmdline
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;同时还会影响 &lt;code&gt;PROMPT_COMMAND&lt;/code&gt; 和 &lt;code&gt;PS0&lt;/code&gt;。其中 &lt;code&gt;PS0&lt;/code&gt; 会在 Bash 读取命令后、执行命令前展开，这也是为什么有些不兼容终端会在每次执行命令前看到一串很长的 &lt;code&gt;3008;start=...&lt;/code&gt; 文本。&lt;/p&gt;
&lt;h2 id=&#34;为什么有些终端会显示乱码&#34;&gt;为什么有些终端会显示乱码
&lt;/h2&gt;&lt;p&gt;正常情况下，终端模拟器应该把 OSC 3008 当作控制序列解析掉，不直接显示。&lt;/p&gt;
&lt;p&gt;但如果终端不认识 OSC 3008，或者中间层把控制字符过滤、转义、打散了，就可能把原始内容显示出来。常见场景包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;旧版终端模拟器。&lt;/li&gt;
&lt;li&gt;尚未适配 OSC 3008 的 SSH 客户端。&lt;/li&gt;
&lt;li&gt;Web 堡垒机或浏览器终端，例如某些 Apache Guacamole 环境。&lt;/li&gt;
&lt;li&gt;Emacs &lt;code&gt;term.el&lt;/code&gt;、串口终端、&lt;code&gt;minicom&lt;/code&gt; 等对 OSC 支持有限的环境。&lt;/li&gt;
&lt;li&gt;多层转发后控制序列被中间层破坏。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这时你可能会看到类似下面的内容：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;]3008;start=...;type=command;cwd=...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者看到包含 &lt;code&gt;machineid=&lt;/code&gt;、&lt;code&gt;bootid=&lt;/code&gt;、&lt;code&gt;pid=&lt;/code&gt;、&lt;code&gt;comm=&lt;/code&gt;、&lt;code&gt;cwd=&lt;/code&gt; 的长字符串。它们不是普通程序输出，而是本来应该由终端处理的上下文信号。&lt;/p&gt;
&lt;h2 id=&#34;怎么判断是不是-osc-3008&#34;&gt;怎么判断是不是 OSC 3008
&lt;/h2&gt;&lt;p&gt;可以先看三个线索。&lt;/p&gt;
&lt;p&gt;第一，乱码里是否有 &lt;code&gt;3008;start=&lt;/code&gt; 或 &lt;code&gt;3008;end=&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;第二，乱码是否经常出现在命令执行前后，尤其是每次按回车执行命令时都出现。&lt;/p&gt;
&lt;p&gt;第三，当前系统是否加载了 systemd 的 OSC 函数：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f __systemd_osc_context_precmdline
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果能看到函数定义，说明当前 shell 里确实加载了相关逻辑。&lt;/p&gt;
&lt;p&gt;还可以检查 profile 文件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ls -l /etc/profile.d/80-systemd-osc-context.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果这个路径存在，并且你的终端正好不支持 OSC 3008，乱码大概率就来自这里。&lt;/p&gt;
&lt;h2 id=&#34;临时规避办法&#34;&gt;临时规避办法
&lt;/h2&gt;&lt;p&gt;如果只是当前会话看着难受，可以先在 shell 里把相关函数覆盖掉，并清空 &lt;code&gt;PS0&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果想只在 SSH 会话中自动处理，可以放到 &lt;code&gt;~/.bashrc&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CLIENT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_TTY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CONNECTION&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f __systemd_osc_context_precmdline &amp;gt;/dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这种方式影响范围比较小，不会动系统级 profile 文件，也方便随时删除。&lt;/p&gt;
&lt;h2 id=&#34;系统级禁用方法&#34;&gt;系统级禁用方法
&lt;/h2&gt;&lt;p&gt;如果你确认这台机器的终端环境普遍不兼容 OSC 3008，可以考虑系统级禁用。但这一步要谨慎，因为它会影响所有用户和所有登录会话。&lt;/p&gt;
&lt;p&gt;systemd 脚本注释里给出的思路是：移除 &lt;code&gt;/etc/profile.d/80-systemd-osc-context.sh&lt;/code&gt; 符号链接，并 mask 对应的 tmpfiles 片段，避免之后被重新创建。&lt;/p&gt;
&lt;p&gt;可以参考这样的命令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; -h /etc/profile.d/80-systemd-osc-context.sh &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm -v /etc/profile.d/80-systemd-osc-context.sh &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ln -s /dev/null /etc/tmpfiles.d/20-systemd-osc-context.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意，这比只改 &lt;code&gt;~/.bashrc&lt;/code&gt; 更重。建议先用临时方案确认问题确实由 OSC 3008 引起，再决定是否做系统级禁用。&lt;/p&gt;
&lt;p&gt;如果只是个人 SSH 客户端不兼容，不建议直接改系统级配置。优先改自己的 &lt;code&gt;~/.bashrc&lt;/code&gt;，或者在 SSH 客户端里设置登录后执行清理命令。&lt;/p&gt;
&lt;h2 id=&#34;应该升级终端还是禁用-osc-3008&#34;&gt;应该升级终端还是禁用 OSC 3008
&lt;/h2&gt;&lt;p&gt;如果你使用的是现代终端，并且它已经支持 OSC 3008，最好保留这个能力。它未来可能会让远程 shell、容器、虚拟机和提权命令的上下文展示更清晰。&lt;/p&gt;
&lt;p&gt;如果你的实际环境是堡垒机、串口、老旧终端或 Web SSH，而且短期内没法升级客户端，那么屏蔽它更实际。毕竟对大多数运维场景来说，干净可读的终端输出比上下文增强更重要。&lt;/p&gt;
&lt;p&gt;可以按这个顺序处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;能升级终端模拟器，就先升级。&lt;/li&gt;
&lt;li&gt;不能升级，但只影响自己，就在 &lt;code&gt;~/.bashrc&lt;/code&gt; 或客户端登录后命令里屏蔽。&lt;/li&gt;
&lt;li&gt;全机器都受影响，再考虑移除 &lt;code&gt;/etc/profile.d/80-systemd-osc-context.sh&lt;/code&gt; 链接并 mask tmpfiles 片段。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;简短结论&#34;&gt;简短结论
&lt;/h2&gt;&lt;p&gt;OSC 3008 不是病毒，也不是普通程序乱输出。它是 UAPI.15 定义的终端上下文信令，目标是让终端理解 shell、SSH、容器、虚拟机、提权命令之间的层级关系。&lt;/p&gt;
&lt;p&gt;真正的问题通常出在兼容性：支持它的终端会自动解析，不支持的终端就可能把控制序列当成乱码显示。&lt;/p&gt;
&lt;p&gt;如果你看到 &lt;code&gt;3008;start=&lt;/code&gt;、&lt;code&gt;machineid=&lt;/code&gt;、&lt;code&gt;bootid=&lt;/code&gt;、&lt;code&gt;cwd=&lt;/code&gt; 之类内容，先判断是否由 systemd 的 &lt;code&gt;80-systemd-osc-context.sh&lt;/code&gt; 注入。确认后，再按影响范围选择临时屏蔽、个人 &lt;code&gt;.bashrc&lt;/code&gt; 屏蔽，或系统级禁用。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>SSH 终端出现 systemd OSC 3008 乱码：两种简单处理办法</title>
        <link>https://knightli.com/2026/06/23/ssh-terminal-systemd-osc-3008-fix/</link>
        <pubDate>Tue, 23 Jun 2026 16:30:26 +0800</pubDate>
        
        <guid>https://knightli.com/2026/06/23/ssh-terminal-systemd-osc-3008-fix/</guid>
        <description>&lt;p&gt;用 SSH 连接 Ubuntu、Kubuntu 或其他 systemd 较新的 Linux 系统时，有时会在命令提示符附近看到一串奇怪的控制字符，常见关键词包括 OSC 3008、systemd context、&lt;code&gt;__systemd_osc_context_*&lt;/code&gt;。它通常不影响命令执行，但会污染终端显示，复制日志时也容易夹带乱码。&lt;/p&gt;
&lt;p&gt;这个问题不一定只和某一个 SSH 客户端有关。WindTerm、某些嵌入式终端、旧版本终端模拟器，或者对 OSC 序列支持不完整的客户端，都可能把本该被终端解释的控制序列直接显示出来。&lt;/p&gt;
&lt;p&gt;根因通常是：远端系统在 Bash 环境里加载了 systemd 的 OSC 上下文钩子，而当前 SSH 客户端没有正确处理这些序列。处理思路也很直接：确认这些钩子函数存在后，把它们覆盖成空函数，并清空 &lt;code&gt;PS0&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;下面给两个办法。第一个写在远端 &lt;code&gt;~/.bashrc&lt;/code&gt;，适合想一劳永逸处理 SSH 会话的服务器；第二个写在 SSH 客户端的“登录后执行命令”里，适合只想对某个客户端或某个会话生效的场景。&lt;/p&gt;
&lt;h2 id=&#34;方案一在-bashrc-里按-ssh-会话拦截&#34;&gt;方案一：在 .bashrc 里按 SSH 会话拦截
&lt;/h2&gt;&lt;p&gt;这个方案的逻辑是：只要检测到当前是 SSH 远程会话，并且系统里确实存在 systemd 注入的 OSC 钩子函数，就把相关函数覆盖成空函数，同时清空 &lt;code&gt;PS0&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;把下面这段加到远端服务器的 &lt;code&gt;~/.bashrc&lt;/code&gt; 末尾：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 检测到 SSH 连接时，拦截 systemd OSC 3008 等终端控制序列乱码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CLIENT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_TTY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CONNECTION&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 仅当系统确实加载了 systemd 的 OSC 函数时才重写，避免污染正常环境&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f __systemd_osc_context_precmdline &amp;gt;/dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;保存后重新登录 SSH，或者在当前 shell 里执行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果乱码来自 systemd 的 OSC 钩子，重新进入 shell 后通常就会消失。&lt;/p&gt;
&lt;h2 id=&#34;如果还想兼容特定客户端&#34;&gt;如果还想兼容特定客户端
&lt;/h2&gt;&lt;p&gt;有些客户端会设置自己的环境变量，比如 WindTerm 可能有 &lt;code&gt;TERM_PROGRAM=WindTerm&lt;/code&gt;。如果你想保留这个判断，也可以写成更宽一点的版本：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 检测到 WindTerm 或 SSH 连接时，拦截 systemd OSC 3008 等终端控制序列乱码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TERM_PROGRAM&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;WindTerm&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CLIENT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_TTY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CONNECTION&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 仅当系统确实加载了 systemd 的 OSC 函数时才重写，避免污染正常环境&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f __systemd_osc_context_precmdline &amp;gt;/dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        __systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;普通 SSH 场景下，单纯判断 &lt;code&gt;SSH_CLIENT&lt;/code&gt;、&lt;code&gt;SSH_TTY&lt;/code&gt;、&lt;code&gt;SSH_CONNECTION&lt;/code&gt; 已经够用。加上 &lt;code&gt;TERM_PROGRAM&lt;/code&gt; 只是为了覆盖某些客户端自己的识别方式。&lt;/p&gt;
&lt;h2 id=&#34;为什么这个写法相对安全&#34;&gt;为什么这个写法相对安全
&lt;/h2&gt;&lt;p&gt;这段配置有两层限制。&lt;/p&gt;
&lt;p&gt;第一层是会话判断：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CLIENT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_TTY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SSH_CONNECTION&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这些变量通常只在 SSH 登录会话里出现，所以它主要影响远程登录，不会随便改动本地桌面终端。&lt;/p&gt;
&lt;p&gt;第二层是函数存在性判断：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f __systemd_osc_context_precmdline &amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这是一道保险。只有当前 shell 已经加载了 &lt;code&gt;__systemd_osc_context_precmdline&lt;/code&gt; 这个函数，才会继续覆盖相关函数。如果系统没有这套 systemd OSC 逻辑，这段配置不会做多余动作。&lt;/p&gt;
&lt;p&gt;真正被覆盖的是这几个函数：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它们的作用是让相关钩子不再输出内容。&lt;code&gt;PS0&lt;/code&gt; 是 Bash 在读取命令后、执行命令前展开的提示符变量，某些 OSC 序列正是通过它或类似机制插进去的，所以这里也一起清空。&lt;/p&gt;
&lt;h2 id=&#34;方案二放到-ssh-客户端的登录后命令里&#34;&gt;方案二：放到 SSH 客户端的登录后命令里
&lt;/h2&gt;&lt;p&gt;如果你不想改远端服务器的 &lt;code&gt;~/.bashrc&lt;/code&gt;，可以把修复动作放到 SSH 客户端的“登录后执行命令”里。很多终端或 SSH 客户端都有类似功能，名字可能叫：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Command executed after authentication&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Post-login command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Remote command after login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;登录后执行命令&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;填入下面这一行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; __systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; __systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果客户端要求自动执行后换到新的提示行，可以在末尾按它的语法追加换行。例如 WindTerm 的 &lt;code&gt;Command executed after authentication&lt;/code&gt; 里，可以使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__systemd_osc_context_precmdline&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; __systemd_osc_context_common&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; __systemd_osc_context_escape&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; :&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PS0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的两个 &lt;code&gt;\n&lt;/code&gt; 用来让客户端执行清理命令后再进入新的提示行。这个写法适合 WindTerm 这类支持认证后自动执行命令的客户端，在 Kubuntu 24.04 环境里测试可用。&lt;/p&gt;
&lt;p&gt;这种方案的好处是影响范围小：只有使用该客户端、该会话连接时才会执行清理命令，服务器上的 shell 配置不需要改。&lt;/p&gt;
&lt;h2 id=&#34;两种方案怎么选&#34;&gt;两种方案怎么选
&lt;/h2&gt;&lt;p&gt;如果这台服务器主要是你自己用，或者你希望所有 SSH 客户端连进来都不再看到这类乱码，推荐用方案一。写进 &lt;code&gt;~/.bashrc&lt;/code&gt; 后，换 WindTerm、Windows Terminal、Tabby、Xshell 或其他 SSH 客户端，都能统一处理。&lt;/p&gt;
&lt;p&gt;如果服务器是多人共用，或者你只想让某个客户端规避这个问题，推荐方案二。它不改远端配置，也不会影响其他人的 shell 环境。&lt;/p&gt;
&lt;p&gt;也可以先用方案二验证问题确实能解决，再决定要不要把方案一写进服务器的 &lt;code&gt;~/.bashrc&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;注意事项&#34;&gt;注意事项
&lt;/h2&gt;&lt;p&gt;这两个方案只是屏蔽 systemd 的 OSC 输出钩子，不会修改 systemd 服务，也不会影响 SSH 登录本身。&lt;/p&gt;
&lt;p&gt;不过，如果你正在使用支持 OSC 3008 的现代终端，并且依赖它显示命令上下文、工作目录或系统状态，那么屏蔽后这些增强提示可能会消失。普通 SSH 运维、开发机登录、服务器管理场景通常不受影响。&lt;/p&gt;
&lt;p&gt;另外，不建议一上来就把这类函数覆盖写到全局 &lt;code&gt;/etc/bash.bashrc&lt;/code&gt;。除非你确认整台机器所有用户都需要这个行为，否则个人环境优先放 &lt;code&gt;~/.bashrc&lt;/code&gt;，客户端定向修复优先放 SSH 客户端的登录后命令。&lt;/p&gt;
&lt;h2 id=&#34;简短结论&#34;&gt;简短结论
&lt;/h2&gt;&lt;p&gt;如果 SSH 连接 Linux 后出现 systemd OSC 3008 乱码，可以按这个顺序处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;不想改服务器：在 SSH 客户端里设置登录后执行清理命令。&lt;/li&gt;
&lt;li&gt;自己的服务器：把 SSH 会话拦截逻辑写进 &lt;code&gt;~/.bashrc&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;多人共用服务器：先用客户端方案验证，再决定是否推广到 shell 配置。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;核心就是一句话：只在 SSH 会话里检查 systemd 的 OSC 钩子函数，存在就覆盖为空函数，并清空 &lt;code&gt;PS0&lt;/code&gt;。这样能压住乱码，又尽量不影响正常终端环境。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
