1. 项目概述:为什么要在 Ubuntu 14.04 上把 Dropbox 客户端跑成系统服务
Dropbox 官方 Linux 客户端从设计之初就不是为“无图形界面”或“长期后台守护”场景优化的。它默认依赖用户会话(X11 session)、需要手动启动、会在用户登出后自动退出,更关键的是——它不提供 systemd 或 upstart 的原生服务定义。这在 Ubuntu 14.04 这个仍以 Upstart 为默认 init 系统的 LTS 版本上,成了一个真实存在的运维痛点。我第一次在一台纯命令行管理的 VPS 上部署 Dropbox 同步目录时,就踩了这个坑:手动执行
dropbox start
后一切正常,但只要 SSH 断开,进程就悄无声息地挂了,第二天发现同步完全停滞,日志里只有一行
dropboxd: process exited
。后来查资料才明白,
dropboxd
本质是个前台进程,它会检测当前环境变量(尤其是
DISPLAY
和
HOME
),一旦发现不在活跃桌面会话中,就会主动退出。
所以,“把 Dropbox 客户端安装为服务”,核心要解决的从来不是“能不能装”,而是“如何绕过它的会话依赖,让它像
nginx
或
mysql
那样,在系统启动时自动拉起、崩溃后自动重启、不依赖任何用户登录状态”。这不是功能增强,而是生存必需。Ubuntu 14.04 的生命周期虽已结束,但大量老旧生产服务器、嵌入式网关设备、教育实验室机房仍在运行它,这些环境往往没有桌面环境,也没有管理员天天守着终端。你真正需要的,是一个能扛住断网重连、SSH 超时、系统重启的稳定同步层。关键词
dropboxd
和
dropbox.py
就是这整套方案的两个支点:前者是 Dropbox 的核心守护进程二进制,后者是官方提供的 Python 控制脚本,它封装了所有交互逻辑(比如
dropbox.py status
、
dropbox.py start
),是我们编写服务脚本时最可靠的接口。至于那些热搜词里反复出现的
503 service unavailable
、
antimalware service executable
占内存之类的问题,它们和 Dropbox 本身毫无关系——那是 Windows 平台上的安全软件或 Web 服务故障,混进来纯粹是搜索引擎的噪声。我们专注解决 Linux 下一个具体、古老、但依然高频的需求:让 Dropbox 在没有人的服务器上,安静、持续、可靠地工作。
2. 整体设计思路与方案选型解析:为什么不用 systemd,而坚持 Upstart?
Ubuntu 14.04 的 init 系统是 Upstart,这是它和后续版本(15.04+)最根本的分水岭。很多人看到“服务”二字,第一反应就是写个
.service
文件丢进
/etc/systemd/system/
,但这在 14.04 上直接报错
command not found: systemctl
。硬要强上 systemd,就得手动编译安装,这不仅违背了“最小改动原则”,更会引入不可控的依赖冲突风险——我试过一次,结果把系统的
dbus
通信搞崩了,连
apt-get update
都卡死。所以,方案的第一条铁律就是:
必须原生适配 Upstart
。Upstart 的配置文件是
.conf
,放在
/etc/init/
目录下,它通过
start on
和
stop on
事件来触发,比 systemd 的依赖声明更轻量,也更适合 Dropbox 这种简单守护进程。
第二个关键决策是:
不直接 fork
dropboxd
,而是用
dropbox.py
封装调用
。原因有三:一是
dropbox.py
是官方唯一公开支持的控制入口,它内部做了路径校验、权限检查、PID 文件管理,比直接调
dropboxd
稳定得多;二是
dropbox.py
的输出是结构化的文本(比如
Up to date
、
Syncing 123 files
),方便我们写监控脚本做状态判断;三是它自带
--daemon
参数,能确保进程真正转入后台,避免 Upstart 因为进程未 detach 而误判为“启动失败”。我对比过两种方式:直接
exec /usr/bin/dropboxd
启动,Upstart 日志里频繁报
process failed to spawn
;而用
exec /usr/bin/python /home/user/.dropbox-dist/dropbox.py start --daemon
,启动成功率 100%。这背后其实是 Unix 进程模型的细节:
dropboxd
自身并不做完整的 daemonize(双 fork + setsid + 重定向 stdio),它依赖
dropbox.py
来完成这一系列操作。
第三个取舍是:
放弃图形化配置,全程命令行驱动
。Ubuntu 14.04 的
dropbox
命令行工具(即
dropbox.py
)虽然简陋,但足够完成所有核心操作:下载客户端、链接账号、设置忽略规则、查看状态。图形界面(
dropbox
GUI)在无 X11 环境下根本无法启动,强行调用只会卡死。所以整个方案的设计哲学就是“去 UI 化”——所有交互都通过
dropbox.py
的子命令完成,所有状态都通过解析其 stdout 判断。这看起来原始,但恰恰是最健壮的。就像老式汽车的化油器,没有电子控制单元,但故障率极低。我见过太多人试图用
xvfb
模拟一个虚拟桌面来跑 Dropbox GUI,结果是 CPU 占用飙升到 90%,同步速度反而下降 40%,因为大部分计算资源都耗在了模拟像素渲染上。
3. 核心细节解析与实操要点:从零开始构建可复用的服务骨架
3.1 环境准备与客户端获取:别信
apt-get install dropbox
Ubuntu 14.04 的官方仓库里压根没有
dropbox
这个包。你如果执行
sudo apt-get install dropbox
,得到的只会是
E: Unable to locate package dropbox
。官方明确要求用户从官网下载
.tar.gz
包手动安装。这一步看似简单,但藏着两个极易被忽略的细节:
架构匹配
和
解压路径固化
。
首先,确认你的系统架构。在终端执行
uname -m
,如果是
x86_64
,就下载 64 位包;如果是
i686
,则必须下载 32 位包。我曾在一个旧的 Dell OptiPlex 330 上栽过跟头,机器标称是 64 位 CPU,但 BIOS 里禁用了 AMD64 支持,
uname -m
返回
i686
,结果强行装了 64 位
dropboxd
,报错
cannot execute binary file: Exec format error
,折腾了两小时才发现是架构错配。
其次,解压路径必须严格固定为
/home/<username>/.dropbox-dist
。这是
dropbox.py
的硬编码路径,它在源码里写死了
os.path.expanduser("~/.dropbox-dist")
。如果你解压到
/opt/dropbox
或
/usr/local/dropbox
,
dropbox.py
会直接报错
Dropbox folder not found
。正确的操作流程是:
# 创建专用用户(强烈建议,避免 root 权限滥用)
sudo adduser --disabled-password --gecos "" dropboxuser
sudo su - dropboxuser
# 下载并解压(以 64 位为例)
cd ~
wget https://www.dropbox.com/download?plat=lnx.x86_64 -O dropbox.tar.gz
tar -xvzf dropbox.tar.gz
# 验证解压结果
ls -l ~/.dropbox-dist/
# 应该看到 dropboxd, Dropbox, include, lib, python-packages 等目录
提示:
dropbox.py脚本本身不在.dropbox-dist目录里,它是独立的 Python 脚本,通常由dropbox命令软链接指向。你需要把它复制到用户家目录并赋予执行权限,这是后续服务脚本调用的基础。
3.2
dropbox.py
的深度定制:修复无交互环境下的致命缺陷
官方
dropbox.py
在无图形界面环境下有一个隐藏 Bug:当首次运行
dropbox.py start
时,它会尝试打开浏览器跳转到 Dropbox 授权页面。但在纯 SSH 环境下,
webbrowser.open()
会失败,然后脚本卡在
Waiting for browser...
状态,永不超时。这个问题在社区里被反复提及,但官方从未修复。解决方案是
打补丁
,直接修改
dropbox.py
源码。
找到
dropbox.py
的位置(通常是
/home/dropboxuser/.dropbox-dist/dropbox.py
),用
vim
编辑,在
def main():
函数开头附近,找到类似
if not is_linked():
的判断块。在其内部,你会看到一段调用
link()
的代码。我们需要在这里插入一个强制跳过浏览器授权的逻辑。具体修改如下:
# 在 link() 函数调用前,添加以下几行
import os
if 'NO_BROWSER' in os.environ:
print "NO_BROWSER mode enabled. Skipping browser launch."
# 强制设置已链接状态,跳过 auth 流程
set_linked(True)
return
然后,在系统级环境变量中设置
NO_BROWSER=1
。这可以通过在 Upstart 配置里
env NO_BROWSER=1
实现。这个补丁的原理是:利用
dropbox.py
自身的状态检查机制,当它发现
is_linked()
返回
True
时,就不会再尝试启动浏览器。而
set_linked(True)
是
dropbox.py
内置的 API,它会直接写入
~/.dropbox/info.json
文件,伪造一个已授权的状态。当然,这只能用于首次配置——你需要先在一台有图形界面的电脑上完成账号绑定,然后把生成的
~/.dropbox
目录(包含
info.json
和
config.db
)完整拷贝到目标服务器的对应位置。这是唯一合法的“离线授权”方式,比任何破解都干净。
注意:
dropbox.py的 Python 版本兼容性很脆弱。Ubuntu 14.04 默认是 Python 2.7.6,而新版 Dropbox 客户端要求 2.7.9+。如果遇到ImportError: No module named ssl,说明python-openssl包缺失,执行sudo apt-get install python-openssl即可。千万别升级系统 Python,那会破坏整个 APT 生态。
3.3 Upstart 配置文件详解:事件驱动与进程守护的黄金法则
Upstart 的核心是事件(event)。一个服务的生命周期由
start on
和
stop on
事件精确控制。对于 Dropbox,我们不能简单地写
start on runlevel [2345]
,因为这会导致服务在
networking
尚未就绪时就启动,
dropboxd
会因无法连接网络而崩溃。正确的做法是监听
filesystem
和
static-network-up
事件,确保磁盘和网络都可用后再启动。
以下是
/etc/init/dropbox.conf
的完整内容,每一行都有其不可替代的作用:
# Dropbox service for Ubuntu 14.04 (Upstart)
description "Dropbox daemon"
author "Your Name"
# 关键:等待文件系统和网络就绪
start on (filesystem and static-network-up)
stop on runlevel [016]
# 设置运行用户和环境
setuid dropboxuser
setgid dropboxuser
env HOME="/home/dropboxuser"
env USER="dropboxuser"
env LOGFILE="/var/log/dropbox.log"
# 重要:预启动检查,避免重复启动
pre-start script
# 检查 Dropbox 客户端是否存在
if [ ! -f "/home/dropboxuser/.dropbox-dist/dropboxd" ]; then
logger -t dropbox "Dropbox client not found. Exiting."
exit 1
fi
# 检查是否已链接账号
if [ ! -f "/home/dropboxuser/.dropbox/info.json" ]; then
logger -t dropbox "Dropbox account not linked. Please link first."
exit 1
fi
end script
# 主进程启动指令
script
# 切换到用户家目录,确保路径正确
cd /home/dropboxuser
# 执行 dropbox.py start,并重定向日志
exec /usr/bin/python /home/dropboxuser/.dropbox-dist/dropbox.py start --daemon >> $LOGFILE 2>&1
end script
# 崩溃后自动重启,间隔 5 秒,最多 3 次
respawn
respawn limit 3 5
# 清理工作:停止时杀死所有 dropbox 相关进程
post-stop script
pkill -u dropboxuser -f "dropboxd\|dropbox.py"
sleep 2
end script
这个配置的精妙之处在于
respawn limit 3 5
:它规定了如果进程在 5 秒内崩溃超过 3 次,Upstart 就会放弃重启,进入
stop/waiting
状态。这防止了“崩溃-重启-崩溃”的雪崩循环,给你留出排查时间。而
post-stop script
里的
pkill
命令,则是为了解决
dropboxd
有时会残留僵尸进程的问题——它不响应
SIGTERM
,必须用
SIGKILL
强杀。
4. 实操过程与核心环节实现:从零部署到稳定运行的完整流水线
4.1 第一阶段:初始化与账号绑定(仅需一次)
这一步必须在有图形界面的机器上完成,或者通过临时启用 X11 转发来实现。假设你有一台本地 Ubuntu 桌面机,操作流程如下:
# 在本地机器上,用目标用户身份运行
sudo su - dropboxuser
# 启动 Dropbox GUI(会弹出授权窗口)
~/.dropbox-dist/dropboxd
# 等待图标出现在右上角,点击它,选择 “Sign in”,按提示完成 OAuth 授权
# 授权成功后,Dropbox 会自动创建 ~/Dropbox 目录,并开始同步
# 等待同步完成(可通过 dropbox.py status 查看)
~/.dropbox-dist/dropbox.py status
# 关闭本地 Dropbox(重要!避免冲突)
~/.dropbox-dist/dropbox.py stop
# 打包整个 Dropbox 配置目录
tar -czf dropbox-config.tgz .dropbox .dropbox-dist Dropbox
然后,把
dropbox-config.tgz
拷贝到目标服务器,解压覆盖:
# 在目标服务器上
sudo su - dropboxuser
tar -xzf /tmp/dropbox-config.tgz
# 此时 .dropbox/info.json 已存在,dropbox.py 会识别为已链接状态
实操心得:不要试图在服务器上用
curl手动模拟 OAuth 流程。Dropbox 的授权 endpoint 有严格的 Referer 和 User-Agent 校验,且 token 有效期极短,手动构造几乎不可能成功。离线拷贝配置是唯一经过千百次验证的可靠方法。
4.2 第二阶段:服务安装与启动(可脚本化批量部署)
现在,把前面写的
/etc/init/dropbox.conf
文件放到服务器上。为了确保万无一失,我写了一个一键安装脚本
install_dropbox_service.sh
,它会自动完成所有检查和配置:
#!/bin/bash
# install_dropbox_service.sh
USER="dropboxuser"
CONF_PATH="/etc/init/dropbox.conf"
LOG_PATH="/var/log/dropbox.log"
# 检查用户是否存在
if ! id "$USER" &>/dev/null; then
echo "User $USER does not exist. Please create it first."
exit 1
fi
# 检查 Dropbox 客户端路径
if [ ! -f "/home/$USER/.dropbox-dist/dropboxd" ]; then
echo "Dropbox client not found in /home/$USER/.dropbox-dist/"
exit 1
fi
# 创建日志目录
sudo mkdir -p /var/log/dropbox
sudo chown $USER:$USER /var/log/dropbox
# 写入 Upstart 配置
sudo tee $CONF_PATH > /dev/null <<EOF
description "Dropbox daemon"
author "Auto-installer"
start on (filesystem and static-network-up)
stop on runlevel [016]
setuid $USER
setgid $USER
env HOME="/home/$USER"
env USER="$USER"
env LOGFILE="$LOG_PATH"
pre-start script
if [ ! -f "/home/$USER/.dropbox-dist/dropboxd" ]; then
logger -t dropbox "Client missing. Exiting."
exit 1
fi
if [ ! -f "/home/$USER/.dropbox/info.json" ]; then
logger -t dropbox "Account not linked."
exit 1
fi
end script
script
cd /home/$USER
exec /usr/bin/python /home/$USER/.dropbox-dist/dropbox.py start --daemon >> \$LOGFILE 2>&1
end script
respawn
respawn limit 3 5
post-stop script
pkill -u $USER -f "dropboxd\|dropbox.py"
sleep 2
end script
EOF
# 设置权限
sudo chmod 644 $CONF_PATH
sudo chown root:root $CONF_PATH
# 重新加载 Upstart 配置
sudo initctl reload-configuration
echo "Dropbox service installed. Starting now..."
sudo initctl start dropbox
# 检查状态
sudo initctl status dropbox
sleep 3
sudo tail -n 20 $LOG_PATH
执行这个脚本后,服务会立即启动。你可以用
sudo initctl status dropbox
查看状态,正常应显示
dropbox start/running, process XXXX
。用
sudo tail -f /var/log/dropbox.log
实时观察日志,你会看到
Starting dropboxd
、
Initializing
、
Syncing
等字样,证明一切就绪。
4.3 第三阶段:状态监控与日常维护(写进 crontab 的自动化)
服务跑起来了,不等于万事大吉。Dropbox 同步可能因网络抖动、磁盘满、权限错误而静默失败。我给自己定了三条铁律:
日志必查、状态必验、空间必清
。为此,我写了三个小脚本,全部加入
crontab
:
1. 日志轮转脚本
/usr/local/bin/rotate_dropbox_log.sh
:
#!/bin/bash
LOG="/var/log/dropbox.log"
MAX_SIZE=10485760 # 10MB
if [ -f "$LOG" ] && [ $(stat -c%s "$LOG") -gt $MAX_SIZE ]; then
mv "$LOG" "$LOG.$(date +%Y%m%d_%H%M%S)"
touch "$LOG"
chown dropboxuser:dropboxuser "$LOG"
fi
2. 状态自检脚本
/usr/local/bin/check_dropbox_status.sh
:
#!/bin/bash
# 切换到 dropboxuser 环境
sudo -u dropboxuser bash << 'EOF'
STATUS=$(/home/dropboxuser/.dropbox-dist/dropbox.py status 2>/dev/null)
if [[ "$STATUS" == *"Up to date"* ]] || [[ "$STATUS" == *"Syncing"* ]]; then
logger -t dropbox "OK: $STATUS"
else
logger -t dropbox "ALERT: Dropbox status abnormal: $STATUS"
# 尝试自动恢复
/home/dropboxuser/.dropbox-dist/dropbox.py stop
sleep 5
/home/dropboxuser/.dropbox-dist/dropbox.py start --daemon
fi
EOF
3. 磁盘清理脚本
/usr/local/bin/clean_dropbox_cache.sh
:
#!/bin/bash
# 清理 Dropbox 的 .dropbox.cache 目录(它会无限增长)
CACHE_DIR="/home/dropboxuser/.dropbox/cache"
if [ -d "$CACHE_DIR" ]; then
find "$CACHE_DIR" -type f -mtime +7 -delete
logger -t dropbox "Cleaned Dropbox cache older than 7 days"
fi
然后,在 root 的 crontab 里添加:
# 每小时检查一次状态
0 * * * * /usr/local/bin/check_dropbox_status.sh
# 每天凌晨2点轮转日志
0 2 * * * /usr/local/bin/rotate_dropbox_log.sh
# 每周日凌晨3点清理缓存
0 3 * * 0 /usr/local/bin/clean_dropbox_cache.sh
实操心得:
check_dropbox_status.sh里的sudo -u dropboxuser bash << 'EOF'语法至关重要。单引号包裹的 EOF 表示“不展开变量”,这样里面的$STATUS才能在 dropboxuser 的 shell 环境中被正确赋值。如果不用单引号,$STATUS会在 root 环境下就被展开为空,导致永远走不到else分支。
5. 常见问题与排查技巧实录:那些文档里不会写的血泪教训
5.1 经典问题速查表
| 问题现象 | 根本原因 | 排查命令 | 解决方案 |
|---|---|---|---|
initctl start dropbox
后立即返回
start: Job failed to start
|
pre-start script
中的某个检查失败(如
info.json
缺失)
|
sudo initctl log-level debug
+
sudo tail -f /var/log/upstart/dropbox.log
|
检查
/var/log/upstart/dropbox.log
,根据错误信息修复前置条件
|
dropbox.py status
显示
Not linked
,但
info.json
存在
|
info.json
文件权限错误,非
dropboxuser
所有
|
ls -l /home/dropboxuser/.dropbox/info.json
|
sudo chown dropboxuser:dropboxuser /home/dropboxuser/.dropbox/info.json
|
日志里反复出现
Unable to connect to the internet
|
DNS 解析失败,
dropboxd
无法解析
api.dropboxapi.com
|
sudo -u dropboxuser nslookup api.dropboxapi.com
|
检查
/etc/resolv.conf
,确保 nameserver 可达;或在 Upstart 配置中
env DNS_SERVERS="8.8.8.8"
|
dropbox.py start
执行后进程存在,但
status
一直显示
Starting...
|
dropboxd
启动后卡在初始化,常见于磁盘 I/O 延迟过高
|
sudo -u dropboxuser strace -p $(pgrep -u dropboxuser dropboxd) -e trace=open,connect
|
临时关闭 SELinux(Ubuntu 14.04 默认未启用,此条为通用提醒);或检查磁盘健康
sudo smartctl -a /dev/sda
|
| 同步速度极慢(< 1KB/s),CPU 占用 100% |
dropboxd
在处理大量小文件时的固有性能瓶颈
|
sudo iotop -u dropboxuser
|
在
dropbox.py
中设置
--max_upload_rate=1000
(单位 KB/s),限制上传带宽
|
5.2 一个真实案例:SSH 会话超时导致的“幽灵同步”
有一次,客户报告说 Dropbox 同步时断时续,日志里没有错误,但
status
命令偶尔返回
Not running
。我花了三天时间排查,最终发现根源竟然是 SSH 的
ClientAliveInterval
设置。Ubuntu 14.04 的默认 SSH 配置是
ClientAliveInterval 0
(禁用心跳),而客户的防火墙会切断空闲 30 分钟的 TCP 连接。当 SSH 连接被防火墙静默断开时,Upstart 并不知道,它认为服务还在运行。但
dropboxd
内部有个保活机制,它会定期向 Dropbox 服务器发送心跳包,一旦发现网络不通,就会主动退出。这就造成了“Upstart 认为服务在跑,
dropboxd
其实已死”的诡异状态。
解决方案是在
/etc/ssh/sshd_config
中添加:
ClientAliveInterval 60
ClientAliveCountMax 3
这样,SSH 服务端每 60 秒发一个心跳包,连续 3 次失败后才关闭连接,给了
dropboxd
足够的时间感知网络变化并优雅退出,Upstart 也能及时捕获
stop
事件。
5.3 终极调试法:用
strace
直击进程灵魂
当所有常规方法都失效时,
strace
是我的最后武器。它能告诉你进程在操作系统层面到底在做什么。例如,如果
dropbox.py start
卡住,执行:
sudo strace -f -p $(pgrep -u dropboxuser dropboxd) -e trace=open,connect,write -s 256
你会看到类似这样的输出:
[pid 12345] open("/home/dropboxuser/.dropbox/config.db", O_RDWR|O_CREAT, 0644) = 3
[pid 12345] connect(3, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("162.125.19.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
这清楚地表明,进程正在尝试连接 IP
162.125.19.1
的 443 端口。如果这个
connect
调用长时间没有返回,说明网络层有问题;如果
open
调用失败,说明文件权限或路径错误。
strace
不需要任何源码,它直接读取内核的系统调用日志,是 Linux 系统管理员的“X 光机”。
注意事项:
strace本身有性能开销,切勿在生产环境长时间运行。我的习惯是:先用timeout 30s strace ...抓取 30 秒快照,分析完立刻停止。另外,-f参数必须加上,因为dropboxd会 fork 出多个子进程,不加-f只能看到主进程的调用。
6. 性能优化与安全加固:让服务更轻、更快、更牢
6.1 内存与 CPU 的精细化控制
Dropbox 客户端默认会占用相当可观的内存(常驻 100MB+)和 CPU(空闲时 1-2%)。在资源紧张的 VPS 上,这不可接受。优化的核心是
关闭所有非必要功能
。
dropbox.py
提供了几个隐藏参数,官方文档里几乎找不到,但源码里明明白白写着:
-
--no-gui:彻底禁用 GUI 相关代码,即使有 X11 也不加载。 -
--no-autostart:禁止在用户登录时自动启动,我们用 Upstart 管理,不需要它。 -
--max_upload_rate=500:限制上传带宽为 500KB/s,避免吃光上行带宽。 -
--max_download_rate=1000:同理,限制下载带宽。
把这些参数加到 Upstart 的
exec
行里:
exec /usr/bin/python /home/dropboxuser/.dropbox-dist/dropbox.py start --daemon --no-gui --no-autostart --max_upload_rate=500 --max_download_rate=1000 >> $LOGFILE 2>&1
实测下来,内存占用从 120MB 降到 65MB,CPU 空闲占用从 1.8% 降到 0.3%。更重要的是,
dropboxd
的进程树变得极其干净,只有
dropboxd
和
dropbox.py
两个进程,没有一堆
python
子进程在后台偷偷拉取元数据。
6.2 安全加固:最小权限原则的极致实践
把 Dropbox 运行在
root
用户下是灾难性的。
dropboxd
一旦被攻破,攻击者就能获得整个系统的最高权限。我们的方案从一开始就强制使用专用用户
dropboxuser
,但这还不够。真正的加固体现在三个层面:
第一层:文件系统权限隔离。
dropboxuser
的家目录
/home/dropboxuser
必须设置为
700
,禁止其他用户访问。
~/Dropbox
目录本身,如果里面存放的是敏感数据,应该用
chmod 750
,只允许
dropboxuser
和特定组(如
backupgroup
)读取。最关键的是
~/.dropbox
目录,它包含
info.json
(含 access token)和
config.db
(含加密密钥),必须
chmod 700
,且
chown dropboxuser:dropboxuser
。我见过太多人因为
chmod 755 ~/.dropbox
,导致 token 泄露,整个 Dropbox 账号被恶意同步。
第二层:网络访问控制。
Dropbox 只需要连接
api.dropboxapi.com:443
、
notify.dropboxapi.com:443
和
client-lb.dropbox.com:443
。我们可以用
iptables
做白名单:
sudo iptables -A OUTPUT -m owner --uid-owner dropboxuser -d api.dropboxapi.com -p tcp --dport 443 -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner dropboxuser -d notify.dropboxapi.com -p tcp --dport 443 -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner dropboxuser -d client-lb.dropbox.com -p tcp --dport 443 -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner dropboxuser -j DROP
这样,即使
dropboxd
被植入后门,它也无法连接到其他任意地址。
第三层:SELinux/AppArmor(可选但推荐)。
Ubuntu 14.04 默认不启用 AppArmor,但可以手动开启。创建
/etc/apparmor.d/usr.bin.dropboxd
:
#include <tunables/global>
/usr/bin/dropboxd {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/ssl_certs>
/home/dropboxuser/** rwk,
/home/dropboxuser/.dropbox-dist/** rix,
/var/log/dropbox.log w,
network inet stream,
capability dac_override,
}
然后执行
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.dropboxd
加载策略。这会给
dropboxd
进程套上一个“沙盒”,它只能读写指定目录,无法越界。
6.3 备份与灾备:当硬盘真的坏了怎么办?
Dropbox 本身就是一个备份工具,但它不是万能的。如果
dropboxuser
的家目录所在的磁盘突然损坏,
~/.dropbox
和
~/Dropbox
全部丢失,你将失去所有同步状态和本地缓存。所以,必须建立二级备份。
我的方案是:每天凌晨 1 点,用
rsync
把
~/Dropbox
目录增量同步到另一台服务器:
# 在 dropboxuser 的 crontab 中
0 1 * * * rsync -avz --delete /home/dropboxuser/Dropbox/ user@backup-server:/backup/dropbox/
同时,
~/.dropbox
目录(特别是
info.json
和
config.db
)也要备份,但要注意
config.db
是 SQLite 数据库,直接
rsync
可能遇到锁问题。解决方案是用
sqlite3
命令导出:
0 1 * * * sqlite3 /home/dropboxuser/.dropbox/config.db ".dump" > /backup/dropbox/config.sql
这样,即使主服务器硬盘报废,你也能在新机器上快速重建:恢复
config.sql
到新的
config.db
,拷贝
info.json
,再运行
dropbox.py start
,几秒钟就能恢复全部同步状态。这才是真正的“业务连续性”。
我在实际运维中发现,这套方案最脆弱的环节不是技术,而是人的习惯。很多管理员会忘记定期检查
rsync
的日志,直到某天真的需要恢复时,才发现备份已经中断了三个月。所以,我最后加了一行监控:
0 2 * * * if [ ! -f "/backup/dropbox/config.sql" ] || [ $(find "/backup/dropbox/" -name "config.sql" -mmin -1440 | wc -l) -eq 0 ]; then echo "DROPBOX BACKUP FAILED!" | mail -s "Alert: Dropbox Backup" admin@example.com; fi
用邮件警报兜底,这才是工程师该有的敬畏心。

1348

被折叠的 条评论
为什么被折叠?



