PHP向Bash脚本传递变量失败问题求助
排查PHP到Bash脚本的变量传递问题
我来帮你梳理下这个问题的核心原因,其实主要是参数顺序不匹配加上权限和安全处理的小问题,咱们一步步解决:
1. 最关键的问题:Bash脚本参数顺序完全颠倒了
你在PHP里传递的参数顺序是:$USERNAME $PASSWORD $NEWPASS,也就是Bash脚本的$1是用户名,$2是原密码,$3是新密码。但你的Bash脚本里写的是:
PASSWORD=$1 NEWPASS=$2 USERNAME=$3
这直接把三个变量的对应关系搞反了!脚本拿到的完全是错误的参数,自然没法正常执行。
2. 额外的坑:sudo权限与原密码验证
- 默认web服务器用户(比如
www-data)没有sudo执行脚本的权限,需要配置免密sudo; - root用户执行
passwd时不需要验证原密码,这会导致任何知道用户名的人都能改密码,非常不安全,得先验证原密码的正确性。
修正后的代码与配置
修正后的Bash脚本(chngpass.sh)
#!/bin/bash # 修正参数顺序:$1=用户名,$2=原密码,$3=新密码 USERNAME="$1" OLD_PASSWORD="$2" NEW_PASSWORD="$3" # 先验证原密码是否正确(用su模拟用户登录验证) echo "$OLD_PASSWORD" | su - "$USERNAME" -c "echo '原密码验证通过'" 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: 原密码不正确" exit 1 fi # 用--stdin传递新密码,避免交互问题 echo -e "$NEW_PASSWORD\n$NEW_PASSWORD" | passwd --stdin "$USERNAME" if [ $? -eq 0 ]; then echo "SUCCESS: 密码修改成功" else echo "ERROR: 密码修改失败" exit 1 fi
修正后的PHP代码
<html> <title> New VPN password</title> <h1> Your New VPN login details are</h1> </html> <?php // 用空合并运算符处理POST参数,避免未定义索引警告 $USERNAME = $_POST['USERNAME'] ?? ''; $PASSWORD = $_POST['PASSWORD'] ?? ''; $NEWPASS = $_POST['NEWPASS'] ?? ''; // 检查所有字段是否填写 if(empty($USERNAME) || empty($PASSWORD) || empty($NEWPASS)) { echo "<h2>You must fill in all fields</h2>"; die ("Click Back to start again."); } // 输出内容转义,防止XSS攻击 echo "<b>User Name:</b><br><br>"; echo htmlspecialchars($USERNAME); echo "<br><br><b>New Password:</b><br><br>"; echo htmlspecialchars($NEWPASS); // 转义shell参数,防止命令注入攻击 $escaped_user = escapeshellarg($USERNAME); $escaped_old_pass = escapeshellarg($PASSWORD); $escaped_new_pass = escapeshellarg($NEWPASS); // 执行脚本并获取输出(包含错误信息) $output = shell_exec("sudo /var/www/html/chngpass.sh $escaped_user $escaped_old_pass $escaped_new_pass 2>&1"); // 显示执行结果 echo "<br><br><b>Execution Result:</b><br><br>"; echo htmlspecialchars($output); ?> <html> <br> <br> <br> <script> function goBack() { window.history.back() } </script> <body> <button onclick="goBack()">Go Back</button> </body> </html>
配置sudo权限
编辑sudoers文件(必须用visudo避免语法错误):
sudo visudo
添加一行(假设web用户是www-data),让它能免密执行你的脚本:
www-data ALL=(ALL) NOPASSWD: /var/www/html/chngpass.sh
保存退出后,别忘了给脚本加执行权限:
sudo chmod +x /var/www/html/chngpass.sh sudo chown root:root /var/www/html/chngpass.sh
内容的提问来源于stack exchange,提问作者Lee Emmery
相关产品推荐
相关产品推荐

