systemd 和 copy (/bin/cp):没有那个文件或目录

Koa*_*eik 5 debian cp file-copy systemd

手动复制文件时,以下工作,如下所示:

userx@x:~$ cp -rv /opt/test-bak/* /opt/test/
'/opt/test-bak/file1' -> '/opt/test/file1'
'/opt/test-bak/file2' -> '/opt/test/file2'
'/opt/test-bak/file3' -> '/opt/test/file3'
'/opt/test-bak/subdir1/subfile1' -> '/opt/test/subdir1/subfile1'
'/opt/test-bak/subdir2/subfile2' -> '/opt/test/subdir2/subfile2'
Run Code Online (Sandbox Code Playgroud)

但是,将其安装为系统服务会返回“cannot stat '/opt/test-bak/*': No such file or directory”错误

? testcopy.service - test usage of /bin/cp in systemd
   Loaded: loaded (/etc/systemd/system/testcopy.service; disabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sun 2019-04-21 14:55:16 +08; 4min 28s ago
  Process: 7872 ExecStart=/bin/cp -rv /opt/test-bak/* /opt/test/ (code=exited, status=1/FAILURE)
 Main PID: 7872 (code=exited, status=1/FAILURE)

Apr 21 14:55:15 userx@x systemd[1]: Started test usage of /bin/cp in systemd.
Apr 21 14:55:15 userx@x cp[7872]: /bin/cp: cannot stat '/opt/test-bak/*': No such file or directory
Apr 21 14:55:16 userx@x systemd[1]: testcopy.service: Main process exited, code=exited, status=1/FAILURE
Apr 21 14:55:16 userx@x systemd[1]: testcopy.service: Unit entered failed state.
Apr 21 14:55:16 userx@x systemd[1]: testcopy.service: Failed with result 'exit-code'.
Run Code Online (Sandbox Code Playgroud)

我的服务文件如下:

[Unit]
Description=test usage of /bin/cp in systemd

[Service]
Type=simple
ExecStart=/bin/cp -rv /opt/test-bak/* /opt/test/

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

日志显示如下

Apr 21 15:05:12 x systemd[1]: Started test usage of /bin/cp in systemd.
Apr 21 15:05:12 x cp[9892]: /bin/cp: cannot stat '/opt/test-bak/*': No such file or directory
Apr 21 15:05:12 x systemd[1]: testcopy.service: Main process exited, code=exited, status=1/FAILURE
Apr 21 15:05:12 x systemd[1]: testcopy.service: Unit entered failed state.
Apr 21 15:05:12 x systemd[1]: testcopy.service: Failed with result 'exit-code'.
Run Code Online (Sandbox Code Playgroud)

任何人都可以对此有所了解吗?

Kus*_*nda 10

在命令行上使用文件名通配模式时,shell 将通配模式扩展为匹配它们的文件名,创建一个路径名列表,然后将其传递给您正在调用的实用程序(cp此处)。

ExecStart在服务文件中指定的命令不会在 shell 中运行。这意味着文件名通配模式*不会被扩展,并且cp/opt/test-bak/*作为要复制的单个文字源路径被调用。

您可以尝试将您的命令包装在一个内嵌的 shell 脚本中:

ExecStart=/bin/sh -c '/bin/cp -rv /opt/test-bak/* /opt/test/'
Run Code Online (Sandbox Code Playgroud)

或者,将您的命令包装在一个简短的 shell 脚本中,

ExecStart=/bin/sh -c '/bin/cp -rv /opt/test-bak/* /opt/test/'
Run Code Online (Sandbox Code Playgroud)

然后调用它。

因为我对 systemd 几乎一无所知,所以可能有更好的方法来做到这一点。

请注意,如果*glob 不匹配任何内容(因为目录为空),那么您将遇到与以前相同的问题。默认情况下,不匹配的通配模式将保持未扩展状态。

就个人而言,我会使用

cd /opt/test-bak && /bin/cp -Rp -v . /opt/test
Run Code Online (Sandbox Code Playgroud)

或者

rsync -ai /opt/test/bak-test/ /opt/test
Run Code Online (Sandbox Code Playgroud)

由于这些都不依赖于 shell 进行文件名生成,因此它们都可以在没有包装 shell 的情况下运行。在这种情况下,不依赖于 shell glob 也会确保隐藏的文件和目录bak-test将被复制。