启动终端上 stdout 和 stderr 的混淆

启动终端上 stdout 和 stderr 的混淆

我有一个嵌入式 Linux 系统,其中从启动时就运行着不同的程序。其中一些程序使用 printf() 写入 stdout 和 stderr。

当我第一次通过 SSH 登录系统时,我可以看到所有这些消息都出现在终端上。

但是,当我在此之后打开另一个 SSH 会话时,进程当然仍在运行,但没有任何内容写入该终端。这让我对 stdout 和 stderr 的实际工作原理感到困惑。我以为他们会写信给所有打开的终端?

答案1

如果您使用第一次 SSH 登录来连接到“串行调试接口”,正如您在评论中提到的,那么您的嵌入式设备只是将串行端口用作控制台设备。这是根本没有视频显示设备的 Linux 系统上的常见解决方案,实际上也是经典 Unix 计算机默认的工作方式。

启动时,启动消息会输出到 上/dev/console,并且某些已启动的程序不会完全脱离其启动的终端设备,而是继续向其发送消息。

从技术上讲,如果不需要应用程序消息,这将是应用程序部分的“完全守护进程失败”,或者如果消息有用并且系统管理员应该写入 start ,则这将是“实现应用程序日志记录的半途而废的方法” -up 脚本将消息定向到日志文件或其他有用的目的地。可悲的是,这种情况相对常见。应用程序消息使控制台设备变得混乱,可能会使系统管理员难以使用控制台来解决导致网络连接失败的任何问题。


(下面的部分是在提到第一个 SSH 会话中涉及串行调试接口这一事实之前编写的......)

标准输入、输出和错误流通常仅连接到一台终端设备。唯一明显的特殊情况是/dev/console,这应该会导致所有物理控制台设备上的输出...但不包括伪 TTY,并且 SSH 连接将始终使用伪 TTY(或根本不使用 TTY),从来都不是“真正的”TTY 设备。

如果您的“从启动时运行的程序”确实在启动时启动,而不是在您第一次登录时启动,那么这是一个有趣的难题。

如果您的嵌入式系统使用旧版(BSD 风格)伪 TTY 设备,那么我想我知道这是如何可能的。 (换句话说,您的系统是否具有分别名为/dev/pty??和的设备节点/tty??对,或者是否具有现代 Unix98 风格的 PTY 设备,例如/dev/ptmx/dev/pts/<number>?)

在启动时,无论管理启动过程的脚本或系统都可能将所有服务的标准输出和错误分配给第一个伪 TTY,其中某种形式的启动日志过程将捕获它们以进行记录,然后将它们传递给实际的控制台 TTY 设备。当引导过程完成时,引导日志过程结束并释放伪TTY主端。但某些启动程序可能不会释放其伪 TTY 一​​侧,并继续向其发送输出。

当您的第一个 SSH 会话建立时,sshd守护进程会获取第一个未分配的伪 TTY 主设备用于连接...但是对于 BSD 样式的伪 TTY 设备,它将与在启动日志记录。因此,第一个 SSH 会话将获得一个伪 TTY 设备,该设备已将启动程序附加到其从属端,因此这些程序的输出将出现在 SSH 会话中。其他 SSH 会话将获得“干净的”伪 TTY 设备,因此它们不会出现问题。

对于现代 Unix98 风格的伪 TTY 设备,PTY 设备的每个新用户都将获得保证唯一的 PTY 设备对,因此这种事情只会发生在 BSD 风格的 PTY 设备上。

相关内容