BlueXIII's Blog

热爱技术,持续学习

0%

记一次root用户su报错的处理过程

现象

  1. 直接使用foobar用户SSH登录正常
  2. 在root用户下,执行su - foobar,报错:
1
su: cannot set user id: Resource temporarily unavailable

只有su的时候报错,虽然不影响foobar用户正常的SSH远程登录,但这种资源受限的错误,一般都是系统崩溃的前兆,必须要较点真。

系统:RHEL 6.5

排查过程

先按套路出牌

首先直接一通free -mtopvmstat等等,试试运气
不过也不出所料,并没有什么收获。但这也算是个好消息,至少说明不像是系统级别的资源问题了。

感觉八成是线程数或者文件打开数搞的鬼了,懒得监控日志,接着排查。

查看线程数

1
2
cat /proc/sys/kernel/threads-max
254529

最大线程数254529,没有问题

1
2
ps -u foobar -L | wc -l
1045

用户当前线程数1045,虽然挺高了,但这个用户下部署的应用也非常多,算是正常吧。

检查ulimit

  1. 先用ulimit看一下设置的最大文件打开数
    用foobar直接登录,然后执行:

    1
    2
    ulimit -n
    655360

    显示655360,没有问题

  2. 然后用lsof统计一下当前的文件打开数

    1
    2
    lsof | grep foobar | wc -l
    1690

    1690,大于1024有点多了,接下来仔细看一下。

  3. lsof大概的逐条分析一下

    1
    2
    3
    4
    lsof | grep foobar
    blablabla...
    blablabla...
    blablabla...

    既有文件,也有网络连接。不像是那种同时发起了大量网络连接造成的故障。这里算是PASS了。

检查limits.conf配置

走到这里,还没查出问题,就有点意外了,索性再检查一下limits.conf

1
2
3
4
5
6
7
8
cat /etc/security/limits.conf

* soft nofile 655360
* hard nofile 655360
* soft noproc 655360
* hard noproc 655360
* soft core 0
* hard core 0

都是655360,一眼看上去没有问题(但这里有个坑,稍后会提到)

检查各个profile配置

再检查各个profile的配置,例如.bash_profile里是不是手工设置了过小的ulimit,导致登录失败。

1
2
cat /etc/profile
cat /foobar/.bash_profile

都很正常,并没有添加多余的东西进去

监控系统secure日志

到这时都没发现出问题,只能监控系统日志/var/log/secure了。
一边监控,一边执行su - foobar

1
2
3
4
5
6
tail -f /var/log/secure
blablabla...

Mar 30 12:08:02 localhost crond[29226]: pam_limits(crond:session): unknown limit item 'noproc'

blablabla...

终于抓到一个问题:noproc参数是个什么鬼,应该是nproc才对吧,估计管理员当时是直接手撸的,没有复制粘帖。

于是赶紧修改limits.conf

1
vi /etc/security/limits.conf

1
2
*    soft    noproc    655360
* hard noproc 655360

改为

1
2
*    soft    nproc    655360
* hard nproc 655360

山穷水尽

解决完上面那个问题,以为这下可以su成功了吧,然而并没有,报错依旧。

于是继续监控/var/log/secure日志。现在报错变成了:

1
2
Mar 30 12:10:25 localhost su: pam_unix(su-l:session): session opened for user foobar by monitor(uid=0)
Mar 30 12:10:25 localhost su: pam_unix(su-l:session): session closed for user foobar

这种报错,相当于什么也没说啊。看来接下来,想要解决问题,只能靠猜了。

一通google之后,找到了这么一句话:

In Red Hat Enterprise Linux 6, there’s a default setting in /etc/security/limits.d/90-nproc.conf. Change the default limit for all users or add a new limit for the affected user.

这个limits.d/90-nproc.conf之前从没有注意过,难道它会覆盖 limits.conf 吗?

1
2
3
cat /etc/security/limits.d/90-nproc.conf
* soft nproc 1024
root soft nproc unlimited

这里的值是1024,尝试改大一点,碰碰运气:

1
2
3
vi /etc/security/limits.d/90-nproc.conf
* soft nproc 10240
root soft nproc unlimited

然后su - foobar ,竟然成功了。

经验值+3

到此为止,两个坑都已经被填上了。耗时15分钟,经验值+3:

  1. 遇到类似问题,直接监控/var/log/secure,可以少走些弯路
  2. 注意/etc/security/limits.conf的参数拼写
  3. 竟然还有/etc/security/limits.d/90-nproc.conf这么个东西,且生效的时机诡异(只影响su,直接登录不受影响)