web-dev-qa-db-ja.com

systemdとコピー(/ bin / cp):そのようなファイルまたはディレクトリはありません

ファイルを手動でコピーしている間、次のように機能します。

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'

ただし、システムサービスとしてインストールすると、「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'.

以下のような私のサービスファイル:

[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

ジャーナルは以下を示しています

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'.

誰かがこれに光を当てることができますか?

5

コマンドラインでファイル名の展開パターンを使用する場合、展開パターンを一致するファイル名に展開するのはシェルであり、パス名のリストを作成してから、呼び出すユーティリティに渡されます(cpここ)。 。

サービスファイルでExecStartを使用して指定するコマンドは、シェルでは実行されません。これは、ファイル名展開パターン*が展開されず、/opt/test-bak/*をコピーする単一のリテラルソースパスとしてcpが呼び出されることを意味します。

コマンドをインラインシェルスクリプトでラップしてみてください。

ExecStart=/bin/sh -c '/bin/cp -rv /opt/test-bak/* /opt/test/'

または、短いシェルスクリプトでコマンドをラップします。

#!/bin/sh

/bin/cp -rv /opt/test-bak/* /opt/test/

代わりにそれを呼び出します。

私はsystemdについて事実上何も知らないので、これを行うにはもっと良い方法があるかもしれません。

*グロブが何にも一致しない場合(ディレクトリが空であるため)、以前と同じ問題が発生することに注意してください。一致しないグロビングパターンは、デフォルトでは展開されません。

個人的に、私はどちらかを使います

cd /opt/test-bak && /bin/cp -Rp -v . /opt/test

または

rsync -ai /opt/test/bak-test/ /opt/test

これらはどちらもシェルがファイル名の生成を行うことに依存していないため、どちらもラップシェルなしで実行できます。この場合、シェルグロブに依存しないことで、bak-testの隠しファイルとディレクトリが確実にコピーされるようになります。

10
Kusalananda