Jenkins任务中Python调用Shell脚本遇Permission denied问题排查
当前工作目录与脚本所在目录不匹配
Jenkins执行python3 foo.py时,当前工作目录未必是foo.py所在的仓库根目录。如果foo.py里直接用相对路径test.sh调用脚本,实际执行时会在Jenkins的工作目录(而非脚本目录)查找文件,即便文件权限足够,也可能因路径问题触发权限报错(或系统错误提示混淆)。
验证方法:在foo.py开头加入代码打印目录信息,查看Jenkins日志:import os print(f"当前工作目录: {os.getcwd()}") print(f"脚本所在目录: {os.path.dirname(os.path.abspath(__file__))}")解决方法:调用test.sh时使用绝对路径,比如:
script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test.sh') subprocess.Popen([script_path])父目录缺少执行权限
即便test.sh本身是rwxr-xr-x权限,它所在的父目录必须给Jenkins运行用户(通常是jenkins用户)**执行权限(x位)**才能进入目录访问文件。
验证方法:在Jenkins任务里添加命令,查看父目录权限:ls -ld /path/to/your/repo如果输出的权限里,Jenkins用户所属的用户组或其他用户没有x位(比如权限是
rwx------),就会导致无法进入目录,触发权限拒绝。
解决方法:给父目录添加执行权限,比如:chmod o+x /path/to/your/repoSELinux/AppArmor等安全模块拦截
部分Linux系统启用的SELinux或AppArmor会强制限制进程的执行范围,即便文件权限符合要求,也会被拦截。
验证方法:临时关闭SELinux测试(仅用于排查):setenforce 0重新运行Jenkins任务,如果问题消失,说明是SELinux拦截。
解决方法:调整文件的安全上下文,或者添加SELinux规则允许Jenkins执行该脚本,比如:chcon -t httpd_sys_script_exec_t /path/to/your/repo/test.sh(具体上下文类型需根据系统环境调整)
subprocess调用的参数问题
使用cmd.split()拆分命令可能存在路径解析问题,且当shell=False(subprocess默认值)时,相对路径的可执行文件需要在系统PATH中,或者使用绝对路径。另外,未指定cwd参数的话,subprocess会继承当前进程的工作目录,可能不是脚本所在目录。
解决方法:避免用split(),直接传列表格式的命令参数,并指定脚本所在目录为工作目录:script_dir = os.path.dirname(os.path.abspath(__file__)) subprocess.Popen(['./test.sh'], cwd=script_dir)Jenkins容器/安全策略限制
如果Jenkins用Docker容器执行任务,容器内的用户权限可能与宿主不一致,或者容器的挂载目录权限设置错误。另外,Jenkins的全局安全配置中,若启用了严格的进程执行限制,也会阻止外部脚本运行。
验证方法:检查Jenkins任务的容器配置,确认挂载的代码目录权限是否正确;查看Jenkins全局安全设置,是否有禁用外部进程执行的规则。
内容的提问来源于stack exchange,提问作者Pat Jones

