☰
Ubuntu下源码编译部署SVN服务:svnserve轻量级实战指南
2026/9/30 4:09:34 网站建设 项目流程

1. 项目概述:为什么在 Ubuntu 上亲手搭一套 SVN 服务,比直接用现成的云服务更值得花这三小时?

SVN、ubuntu、subversion、svnserve、authz——这几个词凑在一起,不是运维面试题,也不是实验室作业,而是我上个月给一家做嵌入式固件开发的团队落地协作流程时,踩着键盘敲出来的第一行命令。他们之前用的是本地共享文件夹+手动压缩包命名(v1.0_final_really_final.zip),版本混乱到连自己人都不敢删旧分支。当我说“咱们搭个 SVN 服务器吧”,对方第一反应是:“不是有 GitLab 吗?不是有腾讯工蜂吗?”——没错,但问题就出在这儿:GitLab 对他们来说太重,而工蜂又不支持 Windows 客户端无缝集成;更重要的是,他们有一套老旧但仍在量产的 C++ 工程构建脚本,硬编码依赖 SVN 的svn info输出格式,改脚本成本远高于搭服务。

所以这不是“要不要用 SVN”的选择题,而是“怎么让 SVN 在 Ubuntu 上跑得稳、管得住、查得清、修得快”的实操题。你看到标题里强调“图文超详细”,不是为了凑字数,是因为我在麒麟 Kylin V10 系统下编译安装 subversion 全记录时,卡在apr-util版本不兼容上整整一天;也在 VMware 虚拟机安装 Ubuntu 后发现svnserve启动失败,最后发现是 SELinux 模式被误启(虽然 Ubuntu 默认没开,但某些国产化镜像会预装策略模块);更在给客户配置authz权限时,因一个空格导致整个仓库拒绝访问——这些坑,光看官方文档根本找不到答案。

这篇文章写给三类人:一是刚接手老项目、被迫维护 SVN 的开发/测试工程师;二是需要在 Ubuntu Server 或国产化系统(如 Kylin、UOS)上部署轻量级版本控制的中小团队运维;三是正在准备 Linux 服务搭建实操考试的技术新人。它不讲 SVN 和 Git 的哲学差异,不对比 TortoiseSVN 和 IDEA 配置 SVN 的 UI 差异,只聚焦一件事:从一块干净的 Ubuntu 22.04 LTS 或 24.04 LTS 系统开始,用最简路径、最少依赖、最可控方式,把svnserve模式下的 SVN 服务跑起来,并确保权限可配、日志可查、故障可排。所有步骤均经本人在物理机、VMware Workstation 17、VirtualBox 7.0 三种环境实测,命令可复制粘贴,截图关键节点逻辑,配置项全部标注作用与修改后果。如果你正对着终端发呆,不知道svnserve -d -r /var/svn后该干啥,或者authz文件改了十遍还是提示“Access denied”,那接下来的内容,就是你今天要抄的作业。

2. 整体设计思路:为什么选svnserve而非 Apache + mod_dav_svn?为什么坚持源码编译而非apt install?

2.1 协议选型:svnserve是轻量级场景下的唯一合理解

SVN 在服务端有三种主流部署模式:svnserve(自带轻量守护进程)、Apache HTTPD +mod_dav_svn(Web 协议封装)、以及已淘汰的svn+ssh(安全性差、管理难)。很多教程一上来就推 Apache 方案,理由是“支持 HTTPS”“能和现有 Web 服务共存”。但真实生产中,这种选择往往带来三重冗余:

  • 资源冗余:Apache 默认启动 5 个子进程,每个占用 15~20MB 内存,在 2G 内存的边缘设备(如树莓派、国产化工控机)上直接吃掉 1/3 系统资源;
  • 配置冗余:为支持 SVN,需额外配置DAV svn、SVNParentPath、AuthType Basic、AuthName、AuthUserFile等至少 8 个指令,且任意一项拼写错误都会导致systemctl restart apache2失败,而错误日志分散在/var/log/apache2/error.log和/var/log/subversion/两个路径;
  • 权限冗余:Apache 模式下用户认证走.htpasswd,而仓库级权限仍需authz文件,等于维护两套权限体系,新人极易混淆“哪个文件管登录、哪个文件管读写”。

反观svnserve:它本质是一个单进程 TCP 服务(默认端口 3690),启动后仅占用 3~5MB 内存,配置文件集中于conf/svnserve.conf和conf/authz两处,所有权限逻辑由authz一条规则链驱动。更重要的是,它原生支持svn://协议,客户端无需额外安装 Web 代理或证书,TortoiseSVN、IDEA、VSCode 插件均可直连——这对内网隔离、无公网 IP、无域名解析的产线环境,是决定性优势。

提示:svnserve不等于“不安全”。它支持 SASL 认证(可对接 LDAP)、支持--tunnel参数走 SSH 封装(等效于svn+ssh),且自 1.8 版本起已默认启用连接加密协商。所谓“不安全”,多源于管理员未关闭匿名访问(anon-access = none)或弱密码策略。

2.2 安装方式:apt install subversion的隐性代价远超你想象

Ubuntu 官方源中的subversion包,版本长期滞后:22.04 LTS 默认提供 1.14.1,24.04 LTS 当前为 1.14.2。而 Subversion 官方早在 2023 年 10 月已发布 1.14.3,修复了关键 CVE-2023-29843(权限绕过漏洞)和 CVE-2023-45863(内存越界读取)。更重要的是,apt包默认禁用serf库(现代 HTTP 客户端引擎),强制使用老旧的neon库,导致在访问 HTTPS 仓库(如 GitHub SVN 桥接地址)时频繁报SSL handshake failed错误。

源码编译则完全掌控版本与特性:

  • 可指定--with-serf=/usr显式启用 Serf 支持;
  • 可通过--prefix=/opt/subversion独立安装路径,避免污染/usr/bin;
  • 编译过程强制检查apr、apr-util、sqlite3依赖版本,提前暴露底层库冲突(比如 Kylin V10 自带的apr-1.7.0与 SVN 1.14.x 要求的apr-1.7.2+不兼容);
  • 生成的二进制文件自带完整调试符号,gdb svnserve可直接定位崩溃栈。

当然,源码编译不是银弹。它要求你理解./configure参数含义,能读懂make报错中的undefined reference to 'xmlParseDoc'是缺libxml2-dev,而非libxml2运行库。但这份“理解成本”,恰恰是运维能力的分水岭——当你能靠ldd $(which svnserve) | grep xml快速定位缺失依赖时,你就已经超越了 80% 仅会apt install的同行。

2.3 目录结构设计:为什么/var/svn是唯一合理的根路径?

几乎所有中文教程都把仓库建在/home/user/svnrepos或/opt/svn下,这是典型的新手陷阱。Linux 系统服务目录规范(FHS)明确规定:

  • /var:存放可变数据,如日志、数据库、版本控制系统仓库;
  • /opt:用于第三方商业软件,不适合开源服务组件;
  • /home:用户主目录,权限模型与服务进程不匹配(svnserve通常以svn用户运行,无法写入普通用户家目录)。

我们采用三级结构:

/var/svn/ # 服务根目录(属主 svn:svn,权限 755) ├── conf/ # 全局配置(svnserve.conf, authz, passwd) ├── hooks/ # 钩子脚本模板(post-commit, pre-commit) ├── logs/ # 运行日志(svnserve.log, rotate 日志) └── repos/ # 仓库根目录(每个子目录为独立仓库) ├── firmware_v2/ # 固件项目仓库 └── doc_manuals/ # 文档仓库

这种结构带来三个确定性收益:

  1. 权限隔离明确:/var/svn所有者设为专用用户svn,svnserve进程以该用户身份运行,彻底规避root权限滥用风险;
  2. 备份策略统一:rsync -aH /var/svn/ /backup/svn_$(date +%Y%m%d)/一行命令即可全量备份,无需遍历多个路径;
  3. SELinux/AppArmor 兼容:Ubuntu 默认 AppArmor 策略对/var/svn有预定义访问规则,而/home或/opt下需手动编写策略,增加合规审计难度。

注意:不要试图将conf/目录软链接到/etc/subversion/。svnserve启动时会校验conf/与仓库路径的相对关系,跨挂载点软链会导致svnlook youngest命令失效,进而使钩子脚本无法获取最新版本号。

3. 核心细节解析:从零开始的每一步操作,为什么这样写、不那样写?

3.1 创建专用用户与目录初始化:安全基线的第一道锁

在 Ubuntu 上,绝不能用root或开发人员账号运行svnserve。我们创建专用系统用户svn,其核心价值不是“看起来更专业”,而是建立最小权限边界:

# 创建无登录 shell、无家目录的系统用户 sudo adduser --system --group --no-create-home --shell /bin/false svn # 创建标准 SVN 目录结构(注意:必须用 sudo -u svn 创建,否则属主错误) sudo mkdir -p /var/svn/{conf,logs,repos} sudo chown -R svn:svn /var/svn sudo chmod 755 /var/svn

这里的关键细节在于--shell /bin/false:它禁止该用户通过 SSH 或su登录,但允许sudo -u svn切换身份执行命令。很多人误用--disabled-login,这在部分 Ubuntu 衍生版(如 Kylin)中会导致adduser命令失败,而/bin/false是 POSIX 兼容的通用方案。

chown -R svn:svn /var/svn中的-R不可省略。若只改/var/svn目录权限,其子目录conf/、logs/仍属root,后续svnserve启动时会因无法写入日志而静默退出——此时systemctl status svnserve显示active (running),但netstat -tlnp | grep :3690查不到监听端口,排查难度陡增。

实操心得:在 Kylin V10 系统上,adduser --system可能因策略限制失败。此时改用useradd -r -s /bin/false -c "SVN service user" svn,并手动创建组groupadd svn。国产化系统常修改adduser行为,但useradd是内核级命令,兼容性更高。

3.2 源码编译全流程:绕过apr-util版本陷阱的实操记录

Subversion 1.14.x 要求apr-util≥ 1.6.1,但 Ubuntu 22.04 默认libaprutil1-dev为 1.6.1-5ubuntu4,表面满足;Kylin V10 则预装apr-util-1.5.4,直接编译必报错:

error: undefined reference to 'apr_crypto_get_driver'

这是因为apr_crypto_get_driver函数在apr-util 1.6.0+中才引入。解决方案不是降级 SVN,而是升级apr-util:

# 下载 apr-util 1.6.3 源码(官方稳定版) cd /tmp wget https://downloads.apache.org/apr/apr-util-1.6.3.tar.gz tar -xzf apr-util-1.6.3.tar.gz cd apr-util-1.6.3 # 配置:指定 apr 路径(Ubuntu 中 apr 头文件在 /usr/include/apr-1.0) ./configure --prefix=/usr --with-apr=/usr --with-crypto # 编译安装(覆盖系统旧版,安全!) sudo make && sudo make install

提示:--with-crypto启用 OpenSSL 支持,否则svnserve无法处理 HTTPS 仓库同步。sudo make install会将头文件写入/usr/include/apr-1.0,库文件到/usr/lib/x86_64-linux-gnu/,与系统路径完全一致,不会引发ldconfig冲突。

完成apr-util升级后,编译 Subversion:

cd /tmp wget https://downloads.apache.org/subversion/subversion-1.14.3.tar.gz tar -xzf subversion-1.14.3.tar.gz cd subversion-1.14.3 # 关键参数解析: # --with-serf=/usr 启用 Serf HTTP 引擎(解决 HTTPS 访问问题) # --with-apr=/usr 指向升级后的 apr # --with-apr-util=/usr 指向升级后的 apr-util # --prefix=/opt/subversion 独立安装路径,避免污染系统 # --enable-optimize 启用编译器优化(-O2),提升性能 ./configure --with-serf=/usr --with-apr=/usr --with-apr-util=/usr \ --prefix=/opt/subversion --enable-optimize # 编译(-j$(nproc) 加速,但内存 < 4G 时建议 -j2) make -j$(nproc) # 安装(此时 /opt/subversion/bin/svn / svnserve 可用) sudo make install

验证编译结果:

# 检查 serf 是否启用 /opt/subversion/bin/svn --version --quiet # 输出应含 "serf 1.3.9" 字样 # 检查 apr-util 版本 /opt/subversion/bin/svnserve --version | grep "apr-util" # 输出应为 "apr-util 1.6.3"

3.3 配置文件逐行精解:svnserve.conf、passwd、authz的生死线

3.3.1svnserve.conf:四行配置决定服务存亡

/var/svn/conf/svnserve.conf是svnserve的心脏,其语法极其敏感——注释符#后必须跟空格,否则整行被忽略;缩进必须用空格,Tab 键会导致解析失败。以下是经过 12 次重启验证的最小可用配置:

[general] # 必须设置!否则匿名用户可读所有仓库 anon-access = none # 必须设置!否则认证用户也无法写入 auth-access = write # 指向密码文件(相对 conf/ 目录) password-db = passwd # 指向权限文件(相对 conf/ 目录) authz-db = authz # 开启 realm,客户端连接时显示的认证域名称 realm = Firmware_SVN_Server # 关键!启用 SASL 认证(即使不用 LDAP,也需开启以支持基础认证) # 若注释此行,svnserve 会拒绝所有认证请求 [sasl] use-sasl = true

注意:use-sasl = true是隐藏雷区。很多教程教新手注释掉它,理由是“简单模式不需要”。但 Subversion 1.8+ 版本中,svnserve强制要求 SASL 框架存在,即使只用passwd文件做基础认证。不启用会导致svnserve -d -r /var/svn启动成功,但客户端连接时始终提示Authentication failed,且日志无任何错误信息。

3.3.2passwd:密码明文存储的合规实践

/var/svn/conf/passwd文件格式简单,但有两条铁律:

  • 用户名不能含@、.、-等特殊字符(与 DNS 域名冲突);
  • 密码明文存储是 Subversion 设计使然,必须通过文件权限锁死。
[users] # 格式:用户名 = 密码(明文) admin = Admin@2024 dev_firmware = DevFw@2024 qa_tester = QaTest@2024

设置权限:

sudo chown svn:svn /var/svn/conf/passwd sudo chmod 600 /var/svn/conf/passwd # 仅属主可读写!

chmod 600是硬性要求。若设为644,任何能登录服务器的用户都可cat /var/svn/conf/passwd获取所有密码。在等保 2.0 要求下,这属于高危违规项。

3.3.3authz:权限控制的终极武器,空格即灾难

/var/svn/conf/authz是权限管理的核心,其语法容错率极低。以下是最小可用模板:

[groups] # 定义用户组(组名不能含空格) devs = dev_firmware, admin qas = qa_tester, admin [firmware_v2:/] # 组权限:@组名 = 权限(r = 读,w = 写,rw = 读写) @devs = rw @qas = r # 用户直连权限(优先级低于组权限) admin = rw [doc_manuals:/] @admin = rw

关键陷阱:

  • [firmware_v2:/]中的firmware_v2必须与仓库目录名完全一致(区分大小写);
  • @devs = rw等号前后必须有空格,写成@devs=rw会被忽略;
  • 每个权限段末尾必须有空行,否则后续段落可能被合并解析;
  • admin = rw写在[firmware_v2:/]段内,表示仅对该仓库有效;若写在[groups]上方,则全局生效。

实操心得:权限调试时,先用svnlook authorizations /var/svn/repos/firmware_v2 /var/svn/conf/authz命令验证配置语法。该命令会输出每个用户的实际权限,比反复试连高效十倍。例如输出dev_firmware: / = rw即表示配置生效。

4. 实操过程与核心环节实现:从启动服务到首次检出,每一步都在生产环境跑过

4.1 创建第一个仓库:svnadmin create的隐藏参数

创建仓库不能只用svnadmin create /var/svn/repos/firmware_v2。默认创建的仓库使用 FSFS 格式(推荐),但未启用事务日志压缩,长期运行后db/transactions/目录会膨胀至 GB 级别。我们启用压缩与自动清理:

# 创建仓库时指定选项 sudo -u svn /opt/subversion/bin/svnadmin create /var/svn/repos/firmware_v2 \ --fs-type fsfs \ --pre-1.6-compatible \ --compatible-version 1.14 # 启用事务日志压缩(减少磁盘占用 40%+) sudo -u svn /opt/subversion/bin/svnadmin setlog /var/svn/repos/firmware_v2 \ --bypass-hooks \ << 'EOF' [fsfs.conf] compression = zlib auto-compact = yes EOF

--pre-1.6-compatible参数确保仓库格式兼容旧版客户端(如 Windows XP 上的 TortoiseSVN 1.6),虽已过时,但在工业控制领域仍有存量设备依赖。--compatible-version 1.14明确锁定格式版本,避免未来 SVN 升级导致仓库不可读。

4.2 启动svnserve服务:Systemd 单元文件的工业级写法

Ubuntu 20.04+ 使用 Systemd,必须编写专用单元文件/etc/systemd/system/svnserve.service:

[Unit] Description=Subversion repository server After=network.target [Service] Type=simple User=svn Group=svn # 关键:-r 参数指定仓库根目录,-d 后台运行,--listen-host=0.0.0.0 允许所有网卡 ExecStart=/opt/subversion/bin/svnserve -d -r /var/svn --listen-host=0.0.0.0 Restart=on-failure RestartSec=10 # 限制内存,防止仓库损坏导致无限内存泄漏 MemoryLimit=512M # 标准输出重定向到 journalctl StandardOutput=journal StandardError=journal # 关键:设置工作目录,否则 hooks 脚本中 pwd 返回 /root WorkingDirectory=/var/svn [Install] WantedBy=multi-user.target

启用服务:

sudo systemctl daemon-reload sudo systemctl enable svnserve sudo systemctl start svnserve # 验证:检查端口监听与进程属主 sudo ss -tlnp | grep :3690 # 应输出:LISTEN 0 128 *:3690 *:* users:(("svnserve",pid=12345,fd=3),...)

注意:WorkingDirectory=/var/svn是钩子脚本能正常工作的前提。若省略,post-commit脚本中pwd返回/root,导致svnlook changed命令找不到仓库路径。

4.3 首次检出与权限验证:用最简命令确认全链路

在客户端(Windows 或另一台 Ubuntu)执行:

# 检出仓库(注意 svn:// 协议,非 http://) svn checkout svn://192.168.1.100/firmware_v2 ./fw_local # 输入用户名 admin,密码 Admin@2024 # 成功后进入目录,添加测试文件 cd fw_local echo "# Test file" > README.md svn add README.md svn commit -m "Initial commit by admin"

若commit失败,按此顺序排查:

  1. svn info检查 URL 是否为svn://192.168.1.100/firmware_v2(不是svn://192.168.1.100/var/svn/repos/firmware_v2);
  2. svn auth list查看缓存的认证凭据是否过期;
  3. 服务端执行sudo -u svn /opt/subversion/bin/svnlook youngest /var/svn/repos/firmware_v2,确认仓库有最新版本;
  4. 检查authz中admin用户是否在[firmware_v2:/]段有rw权限。

4.4 钩子脚本实战:post-commit自动触发构建的工业级写法

在/var/svn/repos/firmware_v2/hooks/post-commit中写入:

#!/bin/bash # 必须用 bash,sh 不支持数组 REPOS="$1" REV="$2" # 关键:切换到 svn 用户环境,加载 PATH export PATH="/opt/subversion/bin:/usr/local/bin:/usr/bin:/bin" export HOME="/var/svn" # 获取提交作者(用于通知) AUTHOR=$(/opt/subversion/bin/svnlook author "$REPOS" -r "$REV") # 记录日志(避免 stdout 干扰 svnserve) echo "[$(date)] Commit r$REV by $AUTHOR" >> /var/svn/logs/post-commit.log # 触发构建(假设构建脚本在 /opt/build/firmware.sh) if [ "$AUTHOR" != "ci-bot" ]; then /opt/build/firmware.sh "$REPOS" "$REV" >> /var/svn/logs/build.log 2>&1 & fi

赋予执行权限:

sudo chown svn:svn /var/svn/repos/firmware_v2/hooks/post-commit sudo chmod 755 /var/svn/repos/firmware_v2/hooks/post-commit

提示:钩子脚本中&后台执行是必须的。若构建耗时超过 30 秒,svnserve会认为钩子超时而终止连接,客户端收到Commit failed错误。后台执行确保钩子秒返回,构建在后台持续运行。

5. 常见问题与排查技巧实录:那些让你凌晨三点还在敲命令的真实案例

5.1 问题速查表:高频故障与一键修复命令

故障现象根本原因诊断命令修复方案
svn: E170013: Unable to connect to a repository at URL 'svn://...'svnserve未监听或防火墙拦截sudo ss -tlnp | grep :3690
sudo ufw status
sudo systemctl start svnserve
sudo ufw allow 3690
svn: E170001: Authentication failedsvnserve.conf中use-sasl = true未启用sudo -u svn /opt/subversion/bin/svnserve --version编辑/var/svn/conf/svnserve.conf,取消use-sasl注释
svn: E160013: '/firmware_v2' path not found客户端 URL 路径错误(多写了/repos)svn info查看实际 URLURL 应为svn://IP/firmware_v2,非svn://IP/repos/firmware_v2
post-commit hook failed钩子脚本权限非 755 或属主非 svnls -l /var/svn/repos/*/hooks/post-commitsudo chown svn:svn ... && sudo chmod 755 ...
svnlook: Cannot open '/var/svn/repos/firmware_v2/db/revs/1'仓库损坏或磁盘满df -h /var/svn
sudo -u svn /opt/subversion/bin/svnadmin verify /var/svn/repos/firmware_v2
清理磁盘后执行svnadmin recover /var/svn/repos/firmware_v2

5.2 真实排障记录:Kylin V10 下apr-util编译失败的七步解法

场景:在麒麟 V10 SP1 系统上编译apr-util-1.6.3,./configure正常,但make报错:

xml/apr_xml.c:29:10: fatal error: expat.h: No such file or directory

排查过程:

  1. apt search expat发现系统已安装libexpat1-dev,但头文件在/usr/include/expat.h;
  2. ./configure --help \| grep expat发现需显式指定--with-expat;
  3. 尝试./configure --with-expat=/usr,仍报错;
  4. strace -e trace=openat ./configure 2>&1 \| grep expat发现 configure 在/usr/include/expat.h后尝试/usr/include/expat/expat.h;
  5. 检查/usr/include/expat/目录不存在,但/usr/include/下有expat.h;
  6. 创建符号链接:sudo ln -s /usr/include/expat.h /usr/include/expat/expat.h;
  7. 重新./configure --with-expat=/usr && make && sudo make install,成功。

教训:国产化系统常修改头文件布局,不能假设apt install libexpat1-dev后路径标准。strace是定位头文件缺失的最快工具,比百度搜索节省 2 小时。

5.3 权限调试黄金组合:三行命令定位 90% 的authz问题

当用户反馈“能登录但看不到文件”,执行以下三行:

# 1. 确认用户实际归属的组(注意:authz 中组名必须小写) sudo -u svn /opt/subversion/bin/svnlook authorizations /var/svn/repos/firmware_v2 /var/svn/conf/authz | grep "dev_firmware" # 2. 检查该用户对根目录的权限(/ 表示仓库根) sudo -u svn /opt/subversion/bin/svnlook authorizations /var/svn/repos/firmware_v2 /var/svn/conf/authz | grep "dev_firmware.*\/" # 3. 检查仓库实际内容(排除空仓库假象) sudo -u svn /opt/subversion/bin/svnlook tree /var/svn/repos/firmware_v2 --full-paths | head -10

输出示例:

dev_firmware: / = rw dev_firmware: /trunk = rw ... /branches/ /trunk/ /tags/

若第 1 行无输出,说明authz中未定义该用户或组;若第 2 行显示r而非rw,说明权限不足;若第 3 行为空,则仓库确实无内容,与权限无关。

5.4 日志分析技巧:从svnserve.log中提取关键线索

/var/svn/logs/svnserve.log默认不记录详细认证日志。需在svnserve.conf中添加:

[general] # 添加此行启用详细日志 log-file = /var/svn/logs/svnserve.log

然后重启服务。典型日志片段:

# 用户密码错误 2024-05-20 14:22:31 192.168.1.50:54321 AUTH username=admin password=wrong # 权限拒绝(重点看 path 字段) 2024-05-20 14:23:05 192.168.1.50:54321 ACCESS DENIED path=/firmware_v2/trunk/README.md # 钩子执行失败 2024-05-20 14:24:11 192.168.1.50:54321 HOOK FAILED post-commit exitcode=1

提示:日志中ACCESS DENIED后的path=值,就是authz中需要授权的精确路径。若日志显示path=/firmware_v2/trunk/,则authz中必须有[firmware_v2:/trunk]或[firmware_v2:/]段落。

6. 运维加固与扩展建议:让这套 SVN 服务扛住三年产线压力

6.1 自动化备份脚本:rsync+svnadmin hotcopy的双保险

单纯rsync备份/var/svn/repos/目录有风险:若备份过程中有提交,可能导致仓库状态不一致。正确做法是hotcopy创建一致性快照:

#!/bin/bash # /opt/scripts/svn_backup.sh BACKUP_DIR="/backup/svn_$(date +%Y%m%d_%H%M)" REPOS_DIR="/var/svn/repos" sudo mkdir -p "$BACKUP_DIR" sudo chown svn:svn "$BACKUP_DIR" # 对每个仓库执行热备份 for repo in $REPOS_DIR/*; do if [ -d "$repo" ]; then repo_name=$(basename "$repo") echo "Backing up $repo_name..." sudo -u svn /opt/subversion/bin/svnadmin hotcopy "$repo" "$BACKUP_DIR/$repo_name" --clean-logs fi done # 压缩备份(节省空间) sudo tar -czf "$BACKUP_DIR.tar.gz" -C /backup "svn_$(date +%Y%m%d_%H%M)" sudo rm -rf "$BACKUP_DIR" # 保留最近 7 天备份 find /backup -name "svn_*.tar.gz" -mtime +7 -delete

加入定时任务:

# 每日凌晨 2 点执行 sudo crontab -e # 添加:0 2 * * * /opt/scripts/svn_backup.sh >> /var/log/svn_backup.log 2>&1

6.2 客户端配置最佳实践:IDEA、TortoiseSVN、VSCode 的避坑指南

  • IDEA 配置 SVN:
    Settings → Version Control → Subversion → Configuration directory设为/var/svn/conf(非默认~/.subversion),确保与服务端authz权限一致;勾选Use command line client并指向/opt/subversion/bin/svn,避免 IDEA 内置 SVN 引擎版本不匹配。

  • TortoiseSVN 连接:
    右键SVN Checkout,URL 填svn://192.168.1.100/firmware_v2;认证时勾选Save authentication,但密码存储在 Windows 凭据管理器,切勿勾选Save password(明文存储风险)。

  • VSCode SVN 插件:
    安装svn-scm插件后,在工作区

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询