概括:
我正在尝试设置一个 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 服务和计时器来定期运行该命令(请注意,我主要从systemd/定时器页面在 Arch Linux Wiki 上)。我制作以下服务文件
/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 服务没有正确处理大括号扩展。
答案1
我想我是通过阅读 systemd 服务手册()自己解决了这个问题man systemd.service
。该ExecStart=
选项不直接支持 shell 命令行,我认为这就是为什么大括号扩展没有按预期执行的原因。我通过将rsync
命令传递到行sh -c
中来使一切正常工作ExecStart=
:
ExecStart=sh -c 'rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/'
参考:
$ man systemd.service ... 请注意,不直接支持 shell 命令行。如果壳 要使用命令行,它们需要显式传递给 某种 shell 实现。例子: ExecStart=sh -c 'dmesg | 执行命令塔克 ...