作为 systemd 服务运行时,rsync 命令不起作用

作为 systemd 服务运行时,rsync 命令不起作用

概括:

我正在尝试设置一个 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_adir_b.所以我运行命令

rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/

当我从终端运行该命令时,该命令有效:它排除目录dir_adir_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}.这实际上使命令起作用了。所以我认为问题在于支撑扩展没有正确完成。

接下来,我尝试使用大括号扩展来测试一个更简单的命令,看看大括号扩展本身是否是问题所在。所以我将rsyncsystemd服务中的命令替换为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 | 执行命令塔克
...

相关内容