记一次登录提示bash错误处理
问题背景
系统:centos 7.9
现象:有个用户反馈服务器后台执行安全加固后,从普通用户切换到root账户时会出现以下bash报错(嗯,系统加固脚本我写的),于是开始着手排查。
[root@nsds4-3-1 ydsoc]# sudo su- root
Last login: Tue Jun 4 11:04:48 CST 2024 on pts/1
bash: alias:-r:invalid option
alias: usage: alias [-p][name[=value]
-bash: alias:-r:invalid option
alias:usage: alias [-p] [name[=value]
-bash: alias:-r:invalid option
alias: usage: alias [-p][name[=value]
-bash: alias:-r:invalid option
alias: usage: alias [-p][name[=value]
-bash: alias:-r:invalid option
...
问题排查
- 从报错提示来看,其实提示也很直接,就是在加载root环境变量过程中,有个alias别名 -r 加载失败了,属于环境变量加载问题;
- 因为是系统自动加载,所以我判断是在环境配置文件中,于是就从 /root 和 /etc 目录下开始查找,使用 grep 命令递归检查是否带 alias 关键字的配置;
# 检查用户家目录配置
grep "^alias" -r ~/*
# 检查全局配置
grep "^alias" -r /etc/*
- 步骤2 检查下来没找到,于是开始检查用户环境变量加载相关配置,从家目录回溯到 /etc 目录,都没找到有 -r 的alias配置,也没有引用其他目录下的配置,到这有点被卡住了,如果不是在配置里写死,怎么能够在每次创建用户shell时自动加载?
- 重新梳理思路,这个报错是和alias相关,所以从alias使用上入手,首先是检查下系统在用的alias别名都有哪些,结果意外发现系统好多在用的alias别名,至少几十个,也不是常见的用法,直觉不是人为手动设置的,更像是程序自动创建的。
# 执行以下命令,查看系统在用的alias别名
alias
# 检查结果如下
...
alias ptd.web cve info.restart='systemctl restart ptd.web cve info.service
alias ptd.web cve info.start='systemctl start ptd.web cve info.service'
alias ptd.web cve info.status='systemctl status ptd.web cve info.service'
alias ptd.web cve info.stop='systemctl stop ptd.web cve info.service'
alias ptd.web update server.log='journalctl -u ptd.web update server.service'
alias ptd.web update server.restart='systemctl restart ptd.web update server.service
alias ptd.web update server.start='systemctl start ptd.web update server.service'
alias ptd.web update server.status='systemctl status ptd.web update server.service
alias ptd.web update server.stop='systemctl stop ptd.web update server.service'
alias ptd.webshark.log='journalctl -u ptd.webshark.service'
alias ptd.webshark.restart='systemctl restart ptd.webshark.service
alias ptd.webshark.start='systemctl start ptd.webshark.service'
alias ptd.webshark.status='systemctl status ptd.webshark.service
alias ptd.webshark.stop='systemctl stop ptd.webshark.service'
alias ptd.write cache.log='journalctl -u ptd.write cache.service
alias ptd.write cache.restart='systemctl restart ptd.write cache.service
alias ptd.write cache.start='systemctl start ptd.write cache.service'
alias ptd.write cache.status='systemctl status ptd.write cache.service
alias ptd.write cache.stop='systemctl stop ptd.write cache.service
alias rm='rm -i'
alias root.log='journalctl -u root'
...
- 从上步检查结果看,这些别名都有ptd的关键字,判断和这个服务有关,于是顺藤摸瓜找到了这个服务的安装目录 /opt/ptd20g,虽然不知道具体是什么服务,但内心比较明确异常和这个服务有关。
- 于是在 /opt/ptd20g 目录下检查是否有 alias 的相关配置,有找到一些类似的服务配置参数,但参数和 -r 也没什么关系,到这里又有点卡住了。
- 重新梳理思路,报错是出现在登入root账户时,即是系统登录报错,而这些报错一般在系统日志中都会有记录,认证相关一般在 /var/log/messages 和 /var/log/secure 文件中,于是查看对应日志是否有相关报错,结果检查发现root登入时都很成功,没出现任何报错,到这里又是卡住了,不过也证明一点,首先shell会话创建是没问题的,问题应该是出现在登录会话创建之后。
- 顺着上一步的思路,既然系统日志没有捕捉到错误,那就想办法把环境变量详细加载过程给打印出来,里面肯定会包含出错的步骤,首先是使用比较常见的 strace 命令,执行 strace sudo -i 后看打印,这个命令虽然打印比较详细,包括底层lib库的调用也会输出,但依旧没有找到和bash报错相关的记录。
- 到网上查找,发现在交互式shell里,其实也可以像调试shell脚本错误那样,以调试模式开启一个新shell,而登录root账户过程,其实也是开启一个新shell,于是尝试执行
sudo bash -c "bash -xv"试试看,果然可行,这里解释一下,该命令作用是以超管权限开启一个新shell,-x 为开启调试模式,-v是显示原始命令输入。 - 在新会话的调试模式下,很容易就找到这个bash报错,是在执行 /etc/profile.d/ptd.alias.sh 后产生的(具体报错的脚本命令示例如下),至此,原因终于定位到了。
...
+++ for ptdsrv in '$(ls ptd.*.service)'
+++ curr=-rw-rw-rw-.
+++ alias '-rw-rw-rw-..start=systemctl start -rw-rw-rw-.'
bash: alias: -r: invalid option
alias: usage: alias [-p] [name[=value] ... ]
+++ alias '-rw-rw-rw-..stop=systemctl stop -rw-rw-rw-.'
bash: alias: -r: invalid option
alias: usage: alias [-p] [name[=value] ... ]
+++ alias '-rw-rw-rw-..restart=systemctl restart -rw-rw-rw-.'
bash: alias: -r: invalid option
alias: usage: alias [-p] [name[=value] ... ]
+++ alias '-rw-rw-rw-..status=systemctl status -rw-rw-rw-.'
bash: alias: -r: invalid option
alias: usage: alias [-p] [name[=value] ... ]
+++ alias '-rw-rw-rw-..log=journalctl -u -rw-rw-rw-.'
bash: alias: -r: invalid option
alias: usage: alias [-p] [name[=value] ... ]
+++ start_items+=' -rw-rw-rw-..start; '
+++ stop_items+=' -rw-rw-rw-..stop;
...
原因分析
安全加固内容有一项是增加了系统别名 ls='ls -alF',该加固项改变了ls的系统默认行为,然后ptd服务使用的别名,是脚本 /etc/profile.d/ptd.alias.sh 通过定时执行方式自动创建的,然后别名内容又根据 ls ptd.*.service 执行结果获取,因为 ls 默认行为被安全加固改变了(打印详细结果),导致该命令输出结果带了像 -rw-rw-rw- 这种非命令关键字,所以就发生别名创建失败错误,而这种创建别名的方式比较隐晦,是在创建登录会话后通过定时任务触发的,所以按常规查找配置的方式,还是检查系统日志都找不到相关报错记录。
问题修复
调整 ls 别名参数,从 ls -alF 改为 ls --color=auto,即只添加匹配高亮,但不改变命令的默认显示结果。
比较曲折,特此记录。

浙公网安备 33010602011771号