从PHP调用含Selenium的Python脚本无输出问题求助
看起来你遇到的问题很典型——手动运行Python脚本完全正常,但通过PHP的shell_exec调用时,只要涉及ChromeDriver的逻辑就没输出,仅保留print却能正常工作。这大概率是PHP运行环境(web服务器用户,通常是www-data)和你手动运行的环境不一致导致的,下面分几个方向帮你排查和解决:
1. 先捕获错误信息,定位问题根源
shell_exec默认只捕获标准输出(stdout),但脚本执行失败的错误信息会输出到标准错误(stderr),所以你根本看不到哪里出问题。先修改PHP代码,把stderr重定向到stdout:
$ID = $_POST['ID']; $Plan = $_POST['Plan']; // 替换成Python脚本的绝对路径,同时把错误输出合并到标准输出 $command = '/usr/bin/python3 /full/path/to/PUBG_Linux_no_bot.py ' . escapeshellarg($ID) . ' ' . escapeshellarg($Plan) . ' 2>&1'; $output = shell_exec($command); echo "<pre>$output</pre>";
注意:一定要用
escapeshellarg()转义参数,避免命令注入风险!
运行后你就能看到具体的错误提示了,比如找不到ChromeDriver、权限不足、依赖缺失等,这是排查的关键第一步。
2. 指定ChromeDriver的绝对路径
手动运行时,你的用户环境变量里能找到ChromeDriver,但www-data用户的环境变量可能没有这个路径。在Python脚本里直接指定ChromeDriver的绝对路径:
from selenium import webdriver import time options = webdriver.ChromeOptions() options.add_argument('--ignore-ssl-errors=yes') options.add_argument('--ignore-certificate-errors') options.add_argument('--no-sandbox') options.add_argument('--headless') options.add_argument('--disable-dev-shm-usage') # 解决Linux下/dev/shm空间不足的问题 # 替换成你ChromeDriver的实际绝对路径,比如/usr/local/bin/chromedriver driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver', options=options) driver.get('https://www.midasbuy.com/midasbuy/ot/buy/pubgm') time.sleep(1) print("done") driver.quit() # 别忘了关闭浏览器,避免进程残留
3. 检查www-data用户的权限
- Chrome/ChromeDriver的执行权限:确保
www-data能执行Chrome和ChromeDriver,比如运行chmod o+x /usr/bin/google-chrome /usr/local/bin/chromedriver(路径根据你的实际安装位置调整)。 - 临时目录权限:Headless Chrome需要写入临时文件,确保
/tmp目录对www-data可写,一般默认是允许的,但如果有特殊权限设置,可以运行chmod 777 /tmp(临时测试用,之后可以调整更严格的权限)。 - Python脚本和依赖的访问权限:确保
www-data能读取你的Python脚本,以及Selenium库所在的目录(可以用pip3 show selenium查看安装路径,然后检查该路径的权限)。
4. 确认Python环境一致性
有时候手动运行的python3和PHP调用的python3不是同一个版本/环境,比如你手动用的是虚拟环境里的Python,但www-data用的是系统默认的。可以手动运行which python3得到绝对路径,然后在PHP的命令里用这个绝对路径替换python3。
5. 添加更多适配Headless模式的参数
Linux服务器上运行Headless Chrome经常需要额外参数,除了上面的--disable-dev-shm-usage,还可以试试这些:
options.add_argument('--disable-gpu') options.add_argument('--window-size=1920x1080') # 指定窗口大小,避免某些页面布局问题 options.add_argument('--user-data-dir=/tmp/chrome_www_data') # 给www-data单独的用户数据目录,确保可写
按照上面的步骤排查,应该能解决你的问题。如果还是不行,把捕获到的错误信息贴出来,就能更精准定位了。
内容的提问来源于stack exchange,提问作者Aladdin Jiroun

