记一次服务器排错
1.背影
最近, 公司一台服务器动不动就瘫, 从监控上看, 基本都是内存枯竭。在间隙中查看了服务器进程后, 发现了罪魁祸首……
可以看到, 我们的服务器被大量的sshd进程塞得满满当当(当时比500还要多一些, 达到了恐怖的830+), 服务器发出不堪重负的呻吟:我已经……一滴都没有了……
和开发小姐姐沟通后了解到, 这些sshd进程是业务里需要用到的进程, 不能取消。后面的故事大家都知道了, 据说服务器走的时候, 脸上是带着笑的, 很是安详。
到这里, 业务自然也跟着一起死了, 所有服务全挂变砖, 根本无法访问。就这样,服务器把我一个人晾在那边, 自己买橘子去了。
2. 抉择
经过一通胡乱分析, 摆在面前有两条路:
等待占用进程执行完毕, 内存被释放后, 服务器一夜好梦, 自然苏醒, 事实上第二天中午服务器确实苏醒了, 然而不不到半个小时, 又被塞得满满当当, 翻起白眼来。
在所有服务都死了的情况下, 不指望服务器能死者苏生, 俗话说得好, 运维有三宝:重启重装换电脑。毕竟内存这东西就和夫妻吵架不过夜一样, 一重启自然就回到了梦开始的地方。
说实话, 这台服务器我并不敢随便重启, 究其原因, 是自己刚接手这台服务器, 接手时也没有具体文档, 其上组件应用和业务逻辑均不可知, 一旦重启, 服务是否齐全、如何去恢复均是未知。
但让业务瘫着总不是个办法, 本着事在人为的探索精神, 对着翻白眼的服务器使用了大招:究极薅电源。
3. 梦魇
就在自己盘算着缺服务少配置的时候怎么去向开发请教的时候,真正的噩梦不知不觉的来到了。
在我还没缓过气来的时候, 屏幕上一个大大的"初始化实例"出现, 本来, 云主机在开启的过程中必然会经历这样一个过程, 但这个时间实在是太漫长了, 以至于甚至打开QQ群吹了十分钟水它还在初始化实例。
这宛如当年碰到的小机灵鬼瞎改fstab的熟悉气息, 感谢天感谢地, 启动失败这种事都被我遇上了。机子启动老不好, 多半是废了挂载问题。于是我新建一台云主机, 将老机子的硬盘挂载到了新机子下, 准备看看到底是哪里出了问题。然鹅我不知道的是, 前面不是一个解密的过程, 而是一个接一个的连环坑……
首先, 多年来的经验驱使我直奔老硬盘上的etc/fstab, 打开一看, 里面只有一个形单影只的根目录——很明显, 没有额外的存储设备挂载, 自然也不会存在挂载失败的问题, 第一条pass。
那么, 还有没有哪里能够找到蛛丝马迹呢?稍加思索后, 我决定从启动日志里寻找报错信息。于是我进入了var/log/开始寻找boot.log……
¿等等……我的boot.log呢?!几秒钟之后, 我的表情发生了微妙的变化……在log目录下, 我没有看到任何与boot相关的日志, 盯着电脑屏幕陷入了
呆滞沉思
4. 巧合
回过神来的我, 只好拿去GHS的精神去各个地方查阅相关资料。
因为系统是Debian, 且是较老的8.0, 国内百度几乎没有我需要的资料, /var/log下没有启动日志, 哪怕是dmesg文件在访问时也显示为空。
在将近两个小时的寻找无果后, 我已经准备放弃时, 角落里一个dmesg这个命令引起了我的注意。抱着死马当成活马医的心态, 输入了次此命令, 成功的看到了启动日志, 可喜可贺可喜可贺。
这里值得一提的是, 如果是在另一个系统中的话, 是没法使用dmesg命令查看的, 因此我是在原系统中使用的dmesg命令。那么问题来了, 既然系统没法启动, 我又是怎么进入的原系统呢?
这里应该有一张图:优质解答——我不知道.jpg, 因为进入系统的方法更像是巧合。下面来看一下我是怎么进入系统的……
我们知道, 为了查看问题所在, 我们建了一个新的系统, 而我为了测试"是不是debian都是一关机就再也起不来的"这种无聊的问题, 为什么我会有这样的想法, 因为前两天刚装了一下debian, 想保留原本的win的情况下安装的debian给我的体验非常之差, 关机各种grub引导报错, 一会儿能开一会不能开, 无限接近于"一关机就起不来"。
而在这种想法的引导下, 我将两个盘来回挂载和卸载, 然后在某次挂载后, 我惊讶的发现:
在控制台中的硬盘是这样的:
而在机器中的硬盘是这样的:
可以看到, 趁着亚马逊服务器不注意, 我们悄悄把挂载的硬盘进行了一个偷梁换柱, 实现了开机……个鬼。此处显示的根分区挂载明显对不上, 但这种错误的挂载反而能够开机, 这一定是amazon的问题.jpg
而dmesg日志中有两处报红:
有了报错信息, 就能将问题逐渐定位了, 这时候我感觉自己信心十足, 嗯, 事实证明了感觉终究只是感觉。
5. 吃瓜
那么真相只有一个, 那就是autofs!毕竟, 它的报错长一些(好吧, 其实是因为一开始并没有使用dmesg -T, 因此看不到报错时间, 时间那里显示的是 7.855319这样的数字), 于是我顺着/dev/autofs去查起来, 度娘依然跟个惹不起一样靠不住, 万般无奈一下挂了SOCKS5去谷歌看资料, 然后我查到了一个东西:
https://github.com/systemd/systemd/issues/9501
作为吃瓜群众, 我看完了这群人的争论, 翻译一下大概就是:在内核3-4版本的中间, 内核编写人员决定去掉autofs4这么个模块, 但debian系统好像并没有跟上, 于是系统去调用了内核中不存在的模块导致报错, 而服务器因为这个挂载失败, 系统无法启动。看着和林纳斯一起编内核的哥们和别人争论的亚子, 这瓜吃的贼开心。
但吃瓜归吃瓜, 问题总要去着手解决, 我花了一定的时间去分析这个问题是如何产生的, 并研究这个问题该如何解决。
首先, 从那哥们的发言来看, 内核中应该是删除了autofs的相关文件, 事实上, 我确实没有在磁盘中找到autofs4文件, 但令我十分不解的是, /dev下莫名地多出了一个/dev/autofs。而启动日志中我们很明显的可以看到"systemd[1]: Failed to open /dev/autofs: No such file or directory"。是我瞎了还是服务器瞎了?
我只能认为这是服务器"打了个盹"的产物——还记得上面提到的那奇葩的根分区挂载吗?因此我提出一个猜想:/dev下的autofs是原本应该挂在根目录下的新盘(xvda)中的东西, 而服务器在启动时由于Amazon控制台出现了bug反倒将autofs作为老硬盘(xvdf)中的文件挂载上了, 因此启动成功。当然, 这是胡乱猜测, 没有特别实锤的依据。
而顺着这个思路往下, 我们可以看到是什么导致/dev/autofs文件消失的呢?因为聊天中我们有看到, 编写内核的时候, 那哥们将autofs4做了别名做成了autofs, 正好和/dev中的东西一样, 而报错中我们也确实能看到/dev/autofs的相关报错是由autofs4的导入失败而导致的。于是, 我将新硬盘挂载到一个目录下, 在其上寻找autofs相关文件, 发现一个问题:新的系统中/lib/modules/3.16.0-4-amd64中有一个kernel目录, 其下有一个fs/autofs4/autofs4.ko文件, 而老硬盘中整个kernel目录不翼而飞……我想这大概就是为什么挂载不上吧……
于是我将新硬盘的/lib/modules/3.16.0-4-amd64/kernel目录整个拷回老硬盘中,具体有没有用, 说实话我不知道。因为这台服务器上跑着业务, 我不可能为了测试一下问题有没有解决就去重启着玩儿, 万一没解决起不来那场面还是算了吧……
6. 回到原点
在那之后, 我又查了一些资料, 并且man了一下dmesg命令, 发现可以使用-T选项去查看具体时间。于是就有了上面的两张图。
新的问题出现了, 我没记错的话, 那天我是搞到1点35左右睡的觉, 然后1点20左右服务器可能已经起来了。如果是这样的话, 那么后面的报错并不是服务器启动失败的报错, 而前面那个1:15的才是, 如果是这样的话, 前面那么多东西方向都是错的, 没啥卵用, 而1:15的报错非常简洁:
"[Fri Dec 20 01:01:14 2019] Cannot get hvm parameter CONSOLE_EVTCHN (18): -22!"
如果有大佬知道这方面的报错怎么处理的话欢迎联系……最近准备考试实在没精力再在这里折腾了……