Debian

systemd and copy (/bin/cp): 沒有這樣的文件或目錄

  • April 21, 2019

在手動複製文件時,以下工作如下:

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

任何人都可以對此有所了解嗎?

在命令行上使用文件名通配模式時,外殼程序將通配模式擴展為與其匹配的文件名,創建一個路徑名列表,然後將其傳遞給您正在呼叫的實用程序(cp此處)。

您在服務文件中指定的命令ExecStart不會在 shell 中執行。這意味著文件名通配模式*不會被擴展,並且cp/opt/test-bak/*作為要複製的單個文字源路徑呼叫。

您可以嘗試將您的命令包裝在一個內聯的 shell 腳本中:

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

或者,將您的命令包裝在一個簡短的 shell 腳本中,

#!/bin/sh

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

然後改為呼叫它。

由於我對 systemd 幾乎一無所知,但可能有更好的方法來做到這一點。

請注意,如果*glob 不匹配任何內容(因為目錄為空),那麼您將遇到與以前相同的問題。預設情況下,不匹配的 globbing 模式將保持未擴展。

就個人而言,我會使用

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

或者

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

由於它們都不依賴 shell 生成文件名,因此它們都可以在沒有包裝 shell 的情況下執行。在這種情況下,不依賴 shell glob 也可以確保bak-test複製其中的隱藏文件和目錄。

引用自:https://unix.stackexchange.com/questions/513633