You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Databricks运行PySpark作业偶发Errno13权限拒绝如何调试排查

Databricks PySpark 随机PermissionError调试定位方案

问题特征

作业运行时随机抛出如下反序列化阶段权限错误,无固定触发规律:

Traceback (most recent call last):
  File "/databricks/spark/python/pyspark/serializers.py", line 165, in _read_with_length
    return self.loads(obj)
  File "/databricks/spark/python/pyspark/serializers.py", line 469, in loads
    return pickle.loads(obj, encoding=encoding)
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 844, in exec_module
  File "<frozen importlib._bootstrap_external>", line 980, in get_code
  File "<frozen importlib._bootstrap_external>", line 1038, in get_data
PermissionError: [Errno 13] Permission denied

故障核心表现:

  • 同一份代码、配置下,作业偶发运行失败,偶发运行成功,无固定触发的数据阶段、业务逻辑节点
  • 作业无重大代码、配置变更,平稳运行2周后突然开始出现该随机故障

分步调试定位方法

第一步:补全日志拿到报错对应的具体文件路径

默认栈追踪没有打印触发权限错误的具体文件路径,这是定位慢的核心原因。在作业代码最开头(所有Spark逻辑、UDF定义之前)加如下异常捕获代码,捕获到PermissionError时打印完整上下文:

import builtins
import os
import traceback
original_import_func = builtins.__import__

def wrapped_import(name, globals=None, locals=None, fromlist=(), level=0):
    try:
        return original_import_func(name, globals, locals, fromlist, level)
    except PermissionError:
        print(f"[DEBUG] Failed to import module: {name}")
        print(f"[DEBUG] Process uid: {os.getuid()}, cwd: {os.getcwd()}")
        print(f"[DEBUG] Python search path: {os.sys.path}")
        traceback.print_exc()
        raise

builtins.__import__ = wrapped_import

重新运行作业触发报错时,就能从executor日志里拿到具体是读哪个文件被拒绝,直接缩小排查范围。

第二步:排查运行时并发写依赖目录的问题

这类随机权限报错90%以上的根因是:作业运行过程中动态安装Python依赖、动态写入依赖目录,同一个executor上多个task并发执行时,一个task正在写入/覆盖依赖文件,另一个task刚好执行import操作读取同一个文件,触发锁冲突或者临时权限位异常,就会抛PermissionError。
排查方式:

  • 拉取报错executor的完整日志,搜索报错时间点前后有没有pip install、unzip、文件写入类操作记录
  • 检查代码里有没有在UDF、map/foreach等executor侧执行的逻辑里写Python安装目录、__pycache__目录、分发的py-files目录的操作
  • 检查集群是否开启了自动依赖安装、节点缓存自动清理策略,这类后台任务会在作业运行时无感知修改本地依赖目录的文件状态,刚好匹配“无变更运行2周后突然出问题”的特征。

第三步:排查pyc缓存文件权限异常

Databricks共享集群上,不同租户作业会复用节点本地磁盘,如果其他作业以高权限写入了Python库目录下的__pycache__缓存文件,当前作业的运行用户没有读权限时,import对应模块就会报错。因为task调度到哪个节点是随机的,所以故障触发完全随机。
验证方式:在作业Spark配置里加如下参数,禁止生成pyc缓存文件,观察故障是否消失:

spark.executorEnv.PYTHONDONTWRITEBYTECODE 1
spark.driverEnv.PYTHONDONTWRITEBYTECODE 1

第四步:排查UDF闭包引用本地文件问题

如果自定义UDF的闭包里硬编码引用了executor本地磁盘的文件路径,当task调度到存在该文件、且权限正常的节点时就能运行成功,调度到没有对应文件、权限不对的节点就会报错。
排查方式:梳理所有UDF、闭包逻辑里的文件读取操作,所有需要在executor侧访问的文件,全部通过spark.addFile()分发,不要硬编码本地绝对路径。

对应修复方案

  • 若定位到是动态安装依赖导致的并发冲突:把所有Python依赖安装操作移到集群初始化脚本(init script)中,确保executor进程启动前所有依赖已经部署完成,禁止在业务代码、UDF中运行pip install操作
  • 若定位到是pyc缓存权限问题:保留上述PYTHONDONTWRITEBYTECODE=1配置即可,也可以在init script里加一行命令给Python依赖目录加全局可读权限:chmod -R a+r /databricks/python/lib/python*/site-packages/
  • 若定位到是闭包引用本地文件问题:将所有依赖的资源文件通过Spark官方文件分发接口传递,移除硬编码的本地路径逻辑

内容的提问来源于stack exchange,提问作者flbzer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 19:54:20