在 NBU 備份 I2000 數據庫、ideploy 自動升級環境檢查等場景中,腳本通過 su - user -c "command" 執行命令,命令本身成功(如 ls 正常輸出),但緊隨其後的 echo $? 返回 1 而非預期的 0,導致上層邏輯判定失敗、流程中斷。
NDMC21:~ # su - sshusr -c "ls";echo $?
bin breeze check.sh Documents ideploy_file_history nohup.out public_html
1
ls 明顯成功輸出。/var/log/messages、secure、su 相關日志,無明顯報錯。strace -f su - sshusr -c "ls" 系統調用跟蹤,發現 su 進程在讀取 /etc/security/ 目錄下文件時返回 EACCES(權限拒絕)。/etc/security 目錄權限被安全加固腳本從 755 (drwxr-xr-x) 改為 600 (drw-------),導致非 root 用戶無法遍歷該目錄,su 內部 PAM 模塊讀取 access.conf、limits.conf 等配置失敗,最終導致 su 返回非零退出碼。su 命令在切換用戶上下文時,會調用 PAM(Pluggable Authentication Modules)堆疊。pam_access.so、pam_limits.so 等模塊需要讀取 /etc/security/ 下的配置文件。若目錄權限為 600(無執行位 x),非 root 用戶無法 cd 進入或 stat 目錄內文件,PAM 模塊報錯,導致 su 整體返回失敗碼,即使用戶命令實際執行成功。
# 確認異常權限
ls -ld /etc/security/
# drw------- 2 root root 368 Jul 12 00:24 /etc/security/
# 修復權限(恢復標準 755)
chmod 755 /etc/security
# 再次測試
su - sshusr -c "ls";echo $?
# bin breeze check.sh Documents ideploy_file_history nohup.out public_html
# 0 <-- 返回碼歸零,問題解決
/etc、/var、/usr、/lib、/bin、/sbin)權限前,必須在測試環境全流程驗證 su、sudo、ssh、cron、systemd 服務啟動等核心功能。x 權限控制「能否進入目錄(cd)、能否訪問目錄內文件元數據」。600 只允許 root 讀寫目錄條目,普通用戶完全不可見。$? 反映的是上一條命令(此處為 su)的退出狀態,而非 su -c 內部命令的退出碼。若需獲取內部命令退出碼,需在 -c 字符串內處理或通過文件傳遞。strace 定位系統調用失敗點,再結合權限、SELinux、PAM、審計日志綜合分析。參考鏈接: 原文博客 | 作者:Bosco (QQ: 375612082)