概括:
我正在尝试设置一个 systemd 计时器以使用该rsync
命令定期备份目录。我做了一个rsync
在终端中手动运行时有效的命令,但是当作为 systemd 计时器运行时它不能正常工作。
详细解释:
作为一个简单的例子,我有以下目录树/home/trevor/test_dir/
:
dir_a/
file_a.png
dir_b/
file_b.png
dir_c/
file_c.png
我想用来rsync
将此目录复制到我的 SSD 以进行备份(安装在/my_ssd/
)。但我想排除目录dir_a
和dir_b
. 所以我运行命令
rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/
当我从终端运行此命令时,它会起作用:它排除目录dir_a
和dir_b
,但保留dir_c
.
接下来,我尝试创建一个 systemd 服务和计时器来定期运行该命令(请注意,我主要从Arch Linux Wiki 上的systemd/Timers 页面确定以下步骤)。我制作了以下服务文件
/etc/systemd/system/backup_test.service
:
[Unit]
Description=systemd backup test
[Service]
Type=simple
ExecStart=rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/
以及以下计时器文件,它将每 30 秒运行一次命令(例如)
/etc/systemd/system/backup_test.timer
:
[Unit]
Description=systemd backup test timer
[Timer]
OnCalendar=*:*:0/30
Persistent=true
[Install]
WantedBy=timers.target
我使用systemctl start backup_test.timer
. 计时器确实每 30 秒运行一次,但“排除”部分似乎被忽略了,整个目录都被复制了。
调试尝试:
我尝试了rsync
使用多个--exclude
选项而不是大括号扩展的命令,换句话说,我使用--exclude=/dir_a --exclude=/dir_b
了--exclude={/dir_a,/dir_b}
. 这实际上使命令起作用。所以我认为问题在于支撑扩展没有正确完成。
接下来,我尝试用大括号展开测试一个更简单的命令,看看大括号展开本身是否有问题。所以我rsync
将 systemd 服务中的命令替换为touch /home/trevor/test{1,2}.txt
. 该命令创建了一个字面上名为/home/trevor/test{1,2}.txt
. 所以我很确定问题是 systemd 服务没有正确处理大括号扩展。
我想我是通过阅读 systemd 服务手册(
man systemd.service
)自行解决的。该ExecStart=
选项不直接支持 shell 命令行,我认为这就是为什么没有按预期执行大括号扩展的原因。通过将我的rsync
命令传递到sh -c
行中,我得到了一切工作ExecStart=
:参考: