ArchiveBox 路径体系深度解析:`archivebox.config.paths` 的目录布局、运行时临时目录与数据定位机制 📅 发布时间:2026/9/20 5:00:44 👁 浏览次数: ArchiveBox 路径体系深度解析archivebox.config.paths的目录布局、运行时临时目录与数据定位机制【免费下载链接】ArchiveBox Open source self-hosted web archiving. Takes URLs/browser history/bookmarks/Pocket/Pinboard/etc., saves HTML, JS, PDFs, media, and more...项目地址: https://gitcode.com/gh_mirrors/ar/ArchiveBoxArchiveBox 自托管网页归档系统把「代码目录」与「数据目录」严格分离所有快照、索引、临时文件与运行依赖都建立在archivebox/config/paths.py这一路径基础设施之上。本文以该模块为核心系统讲解PACKAGE_DIR/DATA_DIR/ARCHIVE_DIR等核心常量的定义规则、Collection ID 与 Machine ID 的生成机制、TMP_DIR 与 ABXPKG_LIB_DIR 的可写性校验与自动修复流程并结合archivebox version命令与 supervisord 运行时说明这些路径如何被实际消费帮助你掌握 ArchiveBox 的磁盘布局能够独立排查目录权限、UNIX socket 与存储位置相关故障。模块定位ArchiveBox 启动流程中最先被加载的路径层archivebox/config/paths.py位于配置子系统archivebox/config中是 ArchiveBox 启动流程中最早被加载的模块之一。它只依赖标准库os、socket、hashlib、tempfile、platform、pathlib以及同级的permissions模块刻意避免导入 Django、其他 INSTALLED_APPS 或config.common这与 constants.py 中「启动早期加载、不得引入重型依赖」的设计约束完全一致。因此该模块提供的全部路径与 ID 在进程早期即可安全使用是后续一切配置、数据库与插件初始化的前提。从源码结构看该模块承担三类职责定义路径常量PACKAGE_DIR、DATA_DIR、ARCHIVE_DIR、USERS_DIR、DATABASE_FILE等见 paths.py提供 ID 生成函数get_collection_id、get_machine_id、get_machine_type提供运行时目录的查找、创建、校验与自修复get_or_create_working_tmp_dir、get_or_create_working_lib_dir以及数据/代码位置总览get_data_locations、get_code_locations。模块 docstring 对应的公开 API 摘要可见 api 文档本文所有函数签名、常量值与行为描述均与该文档及源码一一对应。核心路径常量DATA_DIR 是整套布局的锚点模块在导入期即计算以下模块级常量paths.py常量类型默认值含义PACKAGE_DIRPathPath(__file__).resolve().parent.parentArchiveBox 源码包目录即archivebox/所在位置DATA_DIRPathPath(os.getcwd()).resolve()当前「集合」collection的数据目录即你运行 ArchiveBox 命令时所在的工作目录ARCHIVE_DIRPathDATA_DIR / archive快照数据目录存放每个快照的输出文件USERS_DIRPathARCHIVE_DIR / users按用户隔离的爬取/快照数据目录DATABASE_FILEPathDATA_DIR / index.sqlite3SQLite 主索引数据库文件MAX_TMP_SOCKET_URL_LENGTHint90TMP_DIR 内 supervisord socket 的file://URL 最大字符数上限SUPERVISORD_SOCKET_FILENAMEstrsupervisord.socksupervisord 运行时创建的 UNIX socket 文件名IN_DOCKERbool依据环境变量当IN_DOCKER环境变量为1/true/True/TRUE/yes之一时为True其中最关键的设计是DATA_DIR绑定当前工作目录ArchiveBox 允许你在同一台机器的不同目录中各自维护独立的集合collection每个集合拥有自己的archive/、index.sqlite3与ArchiveBox.conf。因此任何 CLI 命令都应先cd进目标集合目录再执行这也解释了archivebox version输出中「No collection DATA_DIR is currently active」的提示逻辑见 archivebox_version.py。从路径常量到完整目录树constants.py 在 paths 模块之上进一步派生出完整的数据目录树常量SOURCES_DIR DATA_DIR / sources导入的 URL 源文件PERSONAS_DIR DATA_DIR / personasPersona 配置LOGS_DIR DATA_DIR / logs日志CACHE_DIR DATA_DIR / cache缓存CUSTOM_TEMPLATES_DIR DATA_DIR / custom_templates自定义模板USER_PLUGINS_DIR DATA_DIR / custom_plugins用户插件CONFIG_FILE DATA_DIR / ArchiveBox.confTOML 配置文件DEFAULT_TMP_DIR DATA_DIR / tmp / MACHINE_ID默认临时目录如./data/tmp/abc3244323DEFAULT_ABXPKG_LIB_DIR来自环境变量ABXPKG_LIB_DIR默认platformdirs的user_config_path(abx) / lib同时constants.py还定义了ALLOWED_IN_DATA_DIR白名单constants.py列出archive、sources、logs、tmp、index.sqlite3、.archivebox_id等允许存在于数据目录中的文件名用于archivebox init时判断目录是否「足够干净」可初始化为新集合防止误伤用户主目录或桌面。机器与集合的身份标识Machine ID 与 Collection IDget_machine_id()每台机器一个短 IDcache def get_machine_id() - str: Get a short, stable, unique ID for the current machine (e.g. abc45678)实现位于 paths.py优先级如下优先尝试machineid.hashed_id(archivebox)[:8]失败则回退到hashlib.sha256(str(uuid.getnode()).encode()).hexdigest()[:8]基于网卡 MAC仍失败则返回unknown。函数被cache装饰进程内只计算一次。它用于标识「这台机器」与具体的集合无关。get_machine_type()机器平台标识cache def get_machine_type() - str: Get a short, stable, unique type identifier for the current machine (e.g. linux-x86_64-docker)见 paths.py。它组合platform.system()与platform.machine()若在 Docker 内运行则追加-docker后缀形如linux-x86_64-docker用于区分不同平台的运行依赖如二进制文件的平台后缀。get_collection_id()每个集合一个短 IDcache def get_collection_id(DATA_DIRDATA_DIR) - str: Get a short, stable, unique ID for the current collection (e.g. abc45678) return _get_collection_id(DATA_DIRDATA_DIR)核心逻辑在_get_collection_idpaths.py若DATA_DIR/.archivebox_id文件存在直接读取其内容并返回去空白否则计算sha256(f{machine_id}:{collection_path}{creation_date})[:8]作为 8 位十六进制 ID其中creation_date取DATA_DIR.stat().st_ctime异常时回退为当前时间戳仅当目录「看起来像真正的集合」时存在index.sqlite3或ArchiveBox.conf且archive/目录存在、目录可写或者显式传入force_createTrue才将 ID 持久化写入.archivebox_id若当前以 root 运行还会通过SudoPermission将文件属主调整为 archivebox 用户root 场景下改为0o777。这一设计确保ID 由「机器 路径 创建时间」三元组决定同一集合路径在重建后也能得到稳定 ID同时避免在非集合目录中创建多余文件。get_collection_id同样带cache。三个 ID 在archivebox version中以ID{MACHINE_ID}:{COLLECTION_ID}形式对外输出archivebox_version.py并用于临时目录的目录命名见下文。目录可写性与权限自修复dir_is_writable与create_and_chown_dirdir_is_writable(dir_path, uid, gid, fallback, chown)def dir_is_writable(dir_path: Path, uid: int | None None, gid: int | None None, fallbackTrue, chownTrue) - bool: Check if a given directory is writable by a specific user and group (fallbacktry as current user is unable to check with provided uid)见 paths.py。机制是实测而非猜测在目标目录写入临时文件.permissions_test删除该文件成功则返回True若因权限失败且chownTrue则以SudoPermission尝试os.chown(dir_path, uid, gid)修复属主后递归重测chownFalse避免死循环仍失败返回False。该函数与 permissions.py 的SudoPermission配合解决了「ArchiveBox 以 root 启动、但实际归档工作由低权限 archivebox 用户执行」场景下的权限判定问题。create_and_chown_dir(dir_path)def create_and_chown_dir(dir_path: Path) - None: Create a required runtime dir and fix only that dirs ownership when needed.见 paths.py。行为要点mkdir(parentsTrue, exist_okTrue)创建目录若目录已存在且属主已是ARCHIVEBOX_USER:ARCHIVEBOX_GROUP直接返回避免无谓的 chown否则以 root 权限SudoPermission(uid0, fallbackTrue)执行os.chown失败时静默忽略。assert_dir_can_contain_unix_sockets(dir_path)见 paths.py。它会在目标目录中实际创建一个.test_socket.sock的AF_UNIXsocket 并删除以此验证文件系统支持 UNIX socketbind mount、网络盘、FUSE 挂载通常不支持。失败时抛出带pretty_path信息的异常。tmp_dir_socket_path_is_short_enough(dir_path)见 paths.py。计算file://{dir}/supervisord.sock的完整长度并断言其 MAX_TMP_SOCKET_URL_LENGTH90。这是为了规避 UNIX 对 socket 路径长度的硬性限制——路径过长时 supervisord 将无法启动。运行时临时目录的选址与自动修复tmp_dir_candidates(config)候选目录优先级def tmp_dir_candidates(config: ArchiveBoxConfig) - list[Path]:见 paths.py。它按优先级生成候选列表并去重优先级候选路径说明1config.TMP_DIR用户显式配置的临时目录2CONSTANTS.DEFAULT_TMP_DIR即./data/tmp/machine_id3/var/run/archivebox/collection_id系统运行时目录4/tmp/archivebox/collection_id系统临时目录5~/.tmp/archivebox/collection_id用户目录下的隐藏临时目录6system_tmp/archivebox/collection_id系统临时目录tempfile.gettempdir()7system_tmp/archivebox/collection_id 前 4 位缩短版8system_tmp/abx/collection_id 前 4 位更短版注意collection_id_short collection_id[:4]末尾几个候选刻意缩短路径正是因为 socket 路径长度限制。get_or_create_working_tmp_dir(autofixTrue, quietTrue, configNone, **config_kwargs)见 paths.py。执行流程通过get_config()获取配置或使用传入的config遍历tmp_dir_candidates对每个候选执行create_and_chown_dir再用check_tmp_dir(candidate, throwFalse, quietTrue, must_existTrue, configconfig)做完整校验第一个通过校验的候选即被采用若autofixTrue且采用路径与config.TMP_DIR不同会将环境变量TMP_DIR设为该路径os.environ[TMP_DIR] str(candidate)从而对后续进程生效若所有候选都未通过完整校验则回退到「目录存在、可写、且 socket 路径长度足够」的fallback_candidate针对沙箱环境禁止AF_UNIXbind 的情况仍可让只读 CLI 命令运行仍找不到且quietFalse时抛出OSError(fArchiveBox is unable to find a writable TMP_DIR, tried {candidates}!)。check_tmp_dir的完整校验内容校验函数位于 checks.py核心约束如下dir_is_writable(tmp_dir)必须可由 archivebox 用户写入默认ALLOW_NO_UNIX_SOCKETSFalse下必须通过assert_dir_can_contain_unix_socketstmp_dir_socket_path_is_short_enoughfile://dir/supervisord.sock必须短于 90 字符。失败时quietFalse会输出 rich 面板提示明确指出 TMP_DIR 的硬性要求必须位于本地盘不能是 docker volume、网络盘或 FUSE 挂载、必须对 archivebox 用户可读写、路径必须短于 90 字符、应能容纳至少 200MB 数据并给出修复命令archivebox config --set TMP_DIR/tmp/archivebox对应配置项定义于 common.py 的StorageConfigTMP_DIR默认CONSTANTS.DEFAULT_TMP_DIR./data/tmp/machine_idABXPKG_LIB_DIR默认来自环境变量或platformdirs的user_config_path(abx) / libALLOW_NO_UNIX_SOCKETS别名ARCHIVEBOX_ALLOW_NO_UNIX_SOCKETS默认False设为True可跳过 socket 支持检查适合沙箱环境。supervisord socket 的实际消费临时目录最终服务于 supervisord 的 UNIX socket。在 supervisord_util.py 中TMP_DIR get_or_create_working_tmp_dir(autofixTrue, quietFalse) assert TMP_DIR, Failed to find or create a writable TMP_DIR! return TMP_DIR / SUPERVISORD_SOCKET_FILENAME即 supervisord 的 socket 文件路径恒为TMP_DIR/supervisord.sockworker 进程的TMP_DIR环境变量也从该路径推导。这正是paths.py对 socket 路径长度做硬性校验的最终原因。运行依赖目录get_or_create_working_lib_dirABXPKG_LIB_DIR用于存放 ArchiveBox 自动安装的插件库与二进制依赖如 Chromium其查找与自修复逻辑与 TMP_DIR 对称def get_or_create_working_lib_dir(autofixTrue, quietFalse, configNone, **config_kwargs): from archivebox.config.common import get_config from archivebox.misc.checks import check_lib_dir config config or get_config(**config_kwargs) CANDIDATES [config.ABXPKG_LIB_DIR] for candidate in CANDIDATES: try: create_and_chown_dir(candidate) except Exception: pass if check_lib_dir(candidate, throwFalse, quietTrue, must_existTrue, configconfig): if autofix and config.ABXPKG_LIB_DIR ! candidate: os.environ[ABXPKG_LIB_DIR] str(candidate) return candidate if not quiet: raise OSError(fArchiveBox is unable to find a writable ABXPKG_LIB_DIR, tried {CANDIDATES}!)见 paths.py。check_lib_dirchecks.py只要求目录可写并提示应由 archivebox 用户读写、应位于本地快速盘SSD/HDD 而非网络盘、应能容纳至少 1GB 数据。默认位置来自ABXPKG_LIB_DIR环境变量未设置时为platformdirs.user_config_path(abx) / libLinux 下通常为~/.config/abx/lib。位置总览get_data_locations与get_code_locations这两个函数返回带状态标注的AttrDict每个条目都包含path、enabled、is_valid部分包含is_mount是否为挂载点供archivebox version等命令做诊断展示。get_data_locations(configNone, **config_kwargs)见 paths.py覆盖以下数据位置条目path 来源校验要点DATA_DIRDATA_DIR.resolve()目录存在且可读写is_mount标记挂载点CONFIG_FILECONSTANTS.CONFIG_FILEArchiveBox.conf文件存在且可读写SQL_INDEXPostgreSQL 时为database_display_location()否则DATABASE_FILEindex.sqlite3由_sql_index_location动态判断是否 PostgresARCHIVE_DIRCONSTANTS.ARCHIVE_DIR可读写 is_mountUSERS_DIRCONSTANTS.USERS_DIR存在且可读写 is_mountSOURCES_DIRCONSTANTS.SOURCES_DIR存在且可读写PERSONAS_DIRCONSTANTS.PERSONAS_DIR存在且可读写LOGS_DIRCONSTANTS.LOGS_DIR存在且可读写TMP_DIRget_or_create_working_tmp_dir(...) or config.TMP_DIR可读写且socket 路径长度足够其中_sql_index_locationpaths.py通过is_postgres(config)判断若使用 PostgreSQL 数据库则 SQL 索引位置显示为数据库地址而非本地文件。get_code_locations(configNone, **config_kwargs)见 paths.py覆盖代码与资源位置条目path 来源校验要点PACKAGE_DIRPACKAGE_DIR.resolve()检查__main__.py是否可执行TEMPLATES_DIRCONSTANTS.TEMPLATES_DIRPACKAGE_DIR/templates检查STATIC_DIR可读可列出CUSTOM_TEMPLATES_DIRCONSTANTS.CUSTOM_TEMPLATES_DIRDATA_DIR/custom_templates目录存在且可读USER_PLUGINS_DIRCONSTANTS.USER_PLUGINS_DIRDATA_DIR/custom_plugins目录存在且可读ABXPKG_LIB_DIRget_or_create_working_lib_dir(...) or config.ABXPKG_LIB_DIR存在且可读写在archivebox version中的使用archivebox version命令archivebox_version.py会同时打印两份清单未进入集合目录时仅打印 Code locations并提示「Data locations: (not in a data directory)」进入集合目录后通过printable_folder_status(name, path)展示每个数据/代码位置的path/enabled/is_valid状态并据此计算OUTPUT_IS_REMOTE_FS data_locations.DATA_DIR.is_mount or data_locations.ARCHIVE_DIR.is_mount判断归档输出是否落在远程文件系统上。同时get_data_locations/get_code_locations也被archivebox initarchivebox_init.py调用用于初始化时展示与校验目录状态。实战排查路径相关问题的定位顺序综合paths.py、checks.py 与 supervisord_util.py 的代码路径遇到路径类故障时可按以下顺序排查进入集合目录所有命令都应在DATA_DIR含ArchiveBox.conf与archive/的目录中执行否则大量路径校验会处于「未激活」状态查看位置状态在集合目录中运行archivebox version重点看Data locations中各条目的is_valid与is_mount确认DATA_DIR、ARCHIVE_DIR、TMP_DIR是否可写、是否落在远程/挂载文件系统上检查 TMP_DIR若后台 worker 无法启动先确认 TMP_DIR 所在文件系统支持 UNIX socket本地盘而非 docker volume/FUSE且完整 socket 路径短于 90 字符可用archivebox config --set TMP_DIR/tmp/archivebox修复检查属主ArchiveBox 常以 root 启动而以 archivebox 用户执行归档出现写入失败时确认相关目录属主是否为ARCHIVEBOX_USER:ARCHIVEBOX_GROUPpaths.py的create_and_chown_dir与dir_is_writable(chownTrue)会自动修复若手动改过权限可重新触发校验检查 ABXPKG_LIB_DIR若插件或二进制安装失败确认该目录可读写且位于本地盘必要时设置ABXPKG_LIB_DIR环境变量指定新位置确认标识文件DATA_DIR/.archivebox_id应存在且内容为 8 位短 ID若丢失get_collection_id会根据机器、路径与创建时间重新生成并写回。小结archivebox.config.paths是理解 ArchiveBox 磁盘布局的钥匙它以「当前工作目录即数据目录」为锚点通过PACKAGE_DIR/DATA_DIR/ARCHIVE_DIR/DATABASE_FILE等常量划清代码与数据边界以 Machine ID 与 Collection ID 提供跨机器、跨集合的稳定标识并以「实测写入 socket 探测 路径长度校验 权限自修复」的组合策略保证 TMP_DIR 与 ABXPKG_LIB_DIR 这两类运行时目录在任何部署形态裸机、Docker、沙箱下都能被可靠地创建、校验与消费。掌握本模块的函数签名、常量与校验规则即可快速定位 ArchiveBox 部署中绝大多数与目录、权限、UNIX socket 相关的故障。【免费下载链接】ArchiveBox Open source self-hosted web archiving. Takes URLs/browser history/bookmarks/Pocket/Pinboard/etc., saves HTML, JS, PDFs, media, and more...项目地址: https://gitcode.com/gh_mirrors/ar/ArchiveBox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考