
将 python 脚本移出 web 根目录(如 `/var/www/html`),存放于 apache 无法通过 url 直接访问的系统路径(如 `/opt/scripts/` 或 `/usr/local/bin/`),即可彻底杜绝浏览器直接查看源码的风险,同时不影响 php 通过 `exec()` 等函数正常调用。
在典型的 LAMP(Linux + Apache + MySQL + PHP)环境中,开发者常误将可执行脚本(如 .py 文件)置于网站根目录或其子目录下,导致存在严重的安全风险:用户只需在浏览器中输入 https://yoursite.com/scripts/myscript.py,即可直接查看甚至下载原始代码——这不仅泄露业务逻辑、API 密钥或认证凭证,还可能为攻击者提供攻击面。
根本解法并非修改 .htaccess、调整文件权限(如 chmod 710)或尝试代码混淆(既无效又损害可维护性),而是严格分离执行权限与 Web 可访问性:
✅ 正确做法:将脚本移至 Web 根目录之外
例如,将 myscript.py 从 /var/www/html/scripts/myscript.py 迁移至 /opt/myapp/scripts/myscript.py。确保该路径对 Web 服务器用户(通常是 www-data 或 apache)具备执行权限:
sudo chown root:www-data /opt/myapp/scripts/myscript.py sudo chmod 750 /opt/myapp/scripts/myscript.py
同时,确认 Python 解释器路径正确(建议使用绝对路径,避免环境差异):
#!/usr/bin/env python3
# myscript.py — 示例内容
import sys
print("Data from external service: OK")✅ 在 PHP 中安全调用(推荐同步方式获取结果)
原问题中使用了后台异步执行 exec("$cmd > /dev/null 2>&1 & echo $!;"),虽能“不阻塞”,但丢失输出、难以调试且增加进程管理复杂度。更健壮的做法是同步执行并捕获结果:
&1';
$result = shell_exec($cmd);
if ($result === null || trim($result) === '') {
error_log("Python script execution failed or returned empty output");
die("Service temporarily unavailable");
}
echo json_encode(['status' => 'success', 'data' => trim($result)]);
?>⚠️ 注意事项:
立即学习“Python免费学习笔记(深入)”;
- 禁用危险函数(生产环境必做):在 php.ini 中移除 exec, shell_exec, system 等函数(disable_functions = exec,shell_exec,system,passthru),或改用更安全的替代方案(如通过本地 socket、消息队列或专用 API 服务解耦)。
- 最小权限原则:运行脚本的系统用户(如 www-data)应仅拥有执行该脚本及必要依赖库的权限,禁止写入敏感目录。
- 日志与超时控制:为 shell_exec() 添加超时(需配合 proc_open() 实现)并记录错误日志,防止脚本挂起或异常崩溃影响 Web 服务。
- 避免硬编码路径:使用配置文件或环境变量管理脚本路径,提升部署灵活性。
总结:安全的本质在于纵深防御与职责分离。Python 脚本不是 Web 资源,不应被当作静态文件托管;它是一个后端工具,理应像数据库客户端或系统命令一样,部署在受控的非公开路径下。只要路径不可被 Apache 的 DocumentRoot 或别名(Alias)映射,就天然免疫 URL 暴露风险——这是最简单、最可靠、也最符合 Unix 哲学的解决方案。










