以下は、以下のようにファイルを手動でコピーするときに機能します。
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'.
誰でもこれを説明できますか?
答え1
コマンドラインでファイル名globbingパターンを使用すると、シェルはglobbingパターンを一致するファイル名に展開し、パス名のリストを作成し、それを呼び出すユーティリティ(cp
ここ)に渡します。
サービスファイルに指定するコマンドは、シェルExecStart
では実行されません。これは、ファイル名globbingパターンが*
拡張されず、コピーする単一のリテラルソースパスとして呼び出されることを意味しますcp
。/opt/test-bak/*
インラインシェルスクリプトでコマンドをラップしてみることができます。
ExecStart=/bin/sh -c '/bin/cp -rv /opt/test-bak/* /opt/test/'
または、短いシェルスクリプトでコマンドをラップします。
#!/bin/sh
/bin/cp -rv /opt/test-bak/* /opt/test/
それから電話してください。
私はsystemdについてほとんど何も知らないので、これを行うより良い方法があるかもしれません。
*
globが何も一致しない場合(ディレクトリが空であるため)、以前と同じ問題が発生することに注意してください。デフォルトでは、一致しないワイルドカードパターンは拡張されません。
個人的に
cd /opt/test-bak && /bin/cp -Rp -v . /opt/test
または
rsync -ai /opt/test/bak-test/ /opt/test
どちらもファイル名を生成するためにシェルに依存しないため、どちらもラッピングシェルなしで実行できます。この場合、シェルglobに依存しないと、隠しファイルとディレクトリがbak-test
コピーされる可能性があります。