PHP exec函数终端运行正常,Crontab执行时无法锁定系统用户
问题:Crontab执行PHP脚本仅终止进程,无法锁定系统用户
需求为批量暂停系统用户并终止其进程。在终端直接运行controller.php时,用户能成功锁定且进程被终止;但通过Crontab定时执行该脚本时,仅进程被终止,用户未被锁定。
相关代码与配置
PHP代码(controller.php)
foreach ($usernames as $key => $username) { $output = []; exec('/usr/sbin/usermod -L -e 1 ' . $key, $output); $usernames[$key]['timestamp'] = date('Y-m-d H:i:s'); $usernames[$key]['output'] = $output; killProccess($username['pids']); unset($usernames[$key]['pids']); }
Crontab配置
* * * * * /usr/bin/php /home/myuser/controller.php
执行结果对比
- 终端执行后用户状态:
Last password change : Feb 20, 2023 Password expires : never Password inactive : never Account expires : Jan 02, 1970 Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7
- Crontab执行后用户状态:
Last password change : Feb 20, 2023 Password expires : never Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7
问题原因分析
- 权限不足:
usermod命令需要root权限才能修改用户账户属性。终端执行时你可能以root身份运行,或通过sudo提升了权限;但Crontab默认以当前用户(myuser)权限执行,普通用户无权限执行usermod -L及修改账户过期时间。 - 错误未捕获:当前代码未记录
usermod的执行返回码和错误输出,无法直接确认命令执行失败的原因。
解决方案
1. 以root权限执行脚本
- 切换到root用户:
sudo su - 编辑root的Crontab:
crontab -e - 添加执行配置:
* * * * * /usr/bin/php /home/myuser/controller.php
或者在普通用户的Crontab中通过sudo执行(需配置sudo免密):
* * * * * sudo /usr/bin/php /home/myuser/controller.php
配置sudo免密:编辑
/etc/sudoers,添加myuser ALL=(ALL) NOPASSWD: /usr/bin/php /home/myuser/controller.php,最小化权限范围避免安全风险。
2. 完善错误捕获与参数安全
修改PHP代码,捕获命令执行的错误信息和返回码,同时用escapeshellarg()处理用户名,避免特殊字符导致命令异常:
foreach ($usernames as $key => $username) { $output = []; $returnVar = 0; // 重定向错误输出到标准输出,捕获所有执行信息 exec('/usr/sbin/usermod -L -e 1 ' . escapeshellarg($key) . ' 2>&1', $output, $returnVar); $usernames[$key]['timestamp'] = date('Y-m-d H:i:s'); $usernames[$key]['output'] = $output; $usernames[$key]['return_code'] = $returnVar; // 0为执行成功,非0为失败 killProccess($username['pids']); unset($usernames[$key]['pids']); }
3. 记录执行日志排查问题
修改Crontab配置,添加日志输出:
* * * * * /usr/bin/php /home/myuser/controller.php >> /var/log/user_lock.log 2>&1
查看/var/log/user_lock.log文件,可直接获取脚本执行的错误提示,辅助排查问题。
内容的提问来源于stack exchange,提问作者nader sky
相关产品推荐
相关产品推荐

