背景:最近接到一个工单,客户说系统打开终端后不显示主机名和用户名,而且不能执行Linux指令,按回车也无济于事。客户傻了,我懵了!
分析问题:
1 对于运维来讲,突然出现的客户问题首先问客户是否有对系统、应用、硬件等做过变更。答:没有变更。
2 分析日志呗。至关重要的一步。打开终端konsole后,messages日志显示如下:
QcoreApplication::arguments.please instantiate the QcoreApplication object first
can't open a pseudo teletype
unable to get flow control status,terminal not connected
Qmetamethod::invoke unable to handle unregistered datatype 'KWin::EffectWindow*'
Could not stat
拿到日志后,我一看,这家伙怎么说不能打开伪终端,不能获得一个流控制状态,终端不能连接。
查资料后,没有一个给我具体的解决方案。净说什么排查下文件的权限。纳尼,什么文件,查看权限查看可读、可写、可执行说的是模糊不清。让我检查环境变量文件,让我查看/etc/profile、/root/.bashrc、/root/.bash_profile文件内容。结果一看客户没有撒谎,什么都没有变。
复现问题:
我虽然看了日志,但是日志显示的内容给我一脸懵,查了资料也没给我说出一个所以然。
复现思路:
1 既然是用户名和主机名无法显示。那就在我本地环境中测试下呗。echo $PS1指令输出正常,看着也没啥问题。
2 又是修改配置文件、又是注释konsole的配置文件来复现问题。结果排查一天,没啥用,终端都是非常ok,除过注释掉系统环境变量文件后,再次打开终端显示bash4.3#这类问题外。
3 最后我只能返回来再次从日志入手来复现问题。既然是伪终端不能打开,那就执行tty,修改掉tty文件后发现还是可以登录。
然后我就查找伪终端设备,说是/dev/ptmx文件,然后我直接把ptmx文件给修改名字后,发现大功告成。
mv /dev/ptmx /dev/ptmx.bak
再次打开终端,复现了。。。so easy,原来如此。
问题复现了,但是问题并未解决。我将ptmx字符设备文件删除后,重新启动系统,发现又可以打开终端,而客户的问题是重启后仍然不能打开终端。问题还在研究中。
排查不出来问题,找了系统大佬,排查思路如下:
1 系统可以登录,在控制端输入tty查看有返回。file /dev/ptmx文件正常,显示正常/dev/ptmx: character special (5/2) 是正常的。且该文件的权限为666,一切正常。
2 日志显示无法打开伪终端,但ptmx文件的权限和文件类型都正常。
3 执行mount | grep pts后,发现挂载/dev/pts的mode为600,而正常系统是620。异常
4 于是,尝试将mode=600修改为620。mount -o remount,gid=5,mode=620 /dev/pts发现终端还是打不开。问题还是没有解决。
5 于是将重新挂载选项写入开机自启动文件中。
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid5,mode=620 0 0
重新启动系统,发现系统启动后挂载/dev/pts的mode仍然为600.这俨然说明了一个问题,/dev/pts文件被挂载了两次,加载开机自动挂载文件的时候执行一次,后来又被挂载了一次,正是由于后来挂载的这一次导致打开konsole终端不显示主机名和用户名且日志显示不能打开伪终端。
6 既然知道是重新挂载了/dev/pts,那就可以复现问题。将/dev/pts重新挂载一次看是否可以复现问题。mount -t devpts devpts /dev/pts 执行后,发现mount | grep pts 显示的mode=600.再重新挂载一次/dev/pts.执行mount -o remount,gid=5,mode=620 /dev/pts执行后发现mode已经改为620.再次查看konsole发现终端用户名和主机名已经正常。
排查结果:是由于/dev/pts被挂载两次,导致konsole用户名主机名无法显示。
解决方案:将重新挂载/dev/pts目录的命令在系统打印用户名和密码前在执行一次即可。既然之前加入开机自启动文件不可行。那就将这条命令写成一个服务。开机自启动服务即可。
1 写服务的执行文件并赋予权限
vim /usr/bin/fixpts.sh
#!/bin/bash
mount -o remount,gid=5,mode=620 /dev/pts
chmod +x /usr/bin/fixpts.sh
2 写服务的配置文件
vim /usr/lib/systemd/system/fixpts.service
[Uint]
Description=Fix pts mount error
After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service
[Service]
ExecStart=/usr/bin/fixpts.sh
[Install]
WantedBy=graphical.target
最后执行开机自启动该服务即可
systemctl daemon-reload && systemctl enable fixpts
daemon-reload: 重新加载某个服务的配置文件,如果新安装了一个服务,归属于 systemctl 管理,要是新服务的服务程序配置文件生效,需重新加载。
测试可行,问题解决。
就先了解一下伪终端是个什么东西。
了解内容:
在Linux中,/dev/ptmx 文件是由内核在启动时自动创建的,而不是由某个特定的服务生成的。
/dev/ptmx 是一个伪终端主设备文件,用于创建伪终端对(master-slave pair)。伪终端常常用于实现终端仿真,比如SSH、telnet等远程登录服务。
当程序打开 /dev/ptmx 文件时,内核会动态地在 /dev/pts/ 目录下创建一个新的伪终端从设备文件(例如 /dev/pts/0),并返回主设备的文件描述符给打开它的进程。
这样,进程就可以通过这个主设备文件描述符与对应的从设备文件进行通信,模拟一个终端会话。
所以,/dev/ptmx 文件的生成是Linux内核的一部分功能,而不是由某个用户空间的服务或程序来创建的。它是内核提供的用于支持伪终端机制的一个接口。
pty tty ptmx三者的关系:
pty是pseudo terminal的缩写,中文意思为“伪终端”。伪终端是一种虚拟的终端设备,用于在客户端和服务器之间建立一个虚拟的终端会话。
伪终端由两个部分组成:主设备即ptmx(master)和从设备即pts(slave)。主设备负责接收和发送数据,而从设备则负责将数据传递给应用程序或从应用程序接收数据。
找了一张图,供大家深入了解。原文链接https://www.cnblogs.com/jeson-lbb/p/9724710.html
pty包含tty和ptmx,ptmx和pts是用于实现伪终端的设备。
伪终端是一种特殊的设备,它提供了一个类似于物理终端的接口,可以用于在用户空间和内核空间之间进行交互。它通常用于实现终端仿真器(如xterm、gnome-terminal等)或远程登录工具(如ssh)。
ptmx是伪终端的主设备(master),它用于创建新的伪终端设备。当应用程序需要创建一个新的伪终端时,它可以通过打开/dev/ptmx设备文件来获取一个文件描述符。
然后,应用程序可以使用ioctl系统调用来获取与该文件描述符关联的从设备文件路径(/dev/pts/N,其中N是一个数字)。
pts是伪终端的从设备(slave),每个从设备对应一个打开的ptmx设备。应用程序可以通过打开/dev/pts/N设备文件来与伪终端进行交互。
例如,应用程序可以通过读写/dev/pts/N设备文件来向终端发送输入和接收输出。
通过使用ptmx和pts设备,应用程序可以实现与终端类似的交互体验,包括输入、输出、控制终端大小等功能。
伪终端(pseudoterminal): ptmx, pts (伪终端master和伪终端slave).
/dev/ptmx用于创建伪终端主从设备对.当我们用open打开/dev/ptmx设备后, 返回主设备的文件描述符,并且在/dev/pts/目录下创建一个伪终端从设备.
tty这个东西,我对它的理解就是每次使用ssh root@ip地址后,都会在/dev/pts/目录下生成一个数字,来表示打开这个终端。