我想在我的 PC 关机时将文件上传到我的 Dropbox。
sudo vim /etc/systemd/system/upload.service
[Unit]
Description=upload files into dropbox
Before=network.target shutdown.target reboot.target
Requires=network-online.target
[Service]
ExecStop=/bin/true
ExecStart=/bin/bash /home/upload.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
以及upload.sh脚本。
cd /home
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer xxxx" \
--header "Dropbox-API-Arg: {\"path\":\"/test.txt\",\"mode\":{\".tag\":\"overwrite\"}}" \
--header "Content-Type: application/octet-stream" \
--data-binary @"test.txt"
bash upload.sh
可以成功执行,并且test.txt
文件已上传到我的dropbox。
sudo systemctl enable upload service
重新启动我的电脑。
sudo journalctl -u upload
Apr 13 23:58:52 localhost systemd[1]: Started upload files into dropbox.
Apr 13 23:58:52 localhost systemd[1]: Starting upload files into dropbox...
Apr 13 23:58:52 localhost bash[117]: % Total % Received % Xferd Average Speed Time Time Time Current
Apr 13 23:58:52 localhost bash[117]: Dload Upload Total Spent Left Speed
Apr 13 23:58:52 localhost bash[117]: 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (6) Could not resolve host: content.dropboxapi.com; Un
Apr 13 23:58:52 localhost systemd[1]: upload.service: main process exited, code=exited, status=6/NOTCONFIGURED
Apr 13 23:58:52 localhost systemd[1]: Unit upload.service entered failed state.
Apr 13 23:58:52 localhost systemd[1]: upload.service failed.
某些 DNS 错误Could not resolve host: content.dropboxapi.com
导致 upload.service 失败。
我已经在 upload.service 中添加了Requires=network-online.target
,如何让我的电脑在关机时 DNS 解析器解析主机?
答案1
方法一:/etc/systemd/system/upload.service
1.1 /etc/systemd/system/upload.service
sudo vim /etc/systemd/system/upload.service
[Unit]
Description=upload files into dropbox
Before=shutdown.target reboot.target
Requires=network-online.target
After=network.target
[Service]
ExecStop=/bin/true
ExecStart=/bin/bash /home/upload.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
1.2 vim /home/upload.sh
cd /home
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer xxxx" \
--header "Dropbox-API-Arg: {\"path\":\"/test.txt\",\"mode\":{\".tag\":\"overwrite\"}}" \
--header "Content-Type: application/octet-stream" \
--data-binary @"test.txt"
1.3 sudo systemctl enable upload.service
方法二:/lib/systemd/system-shutdown/upload.service
2.1 /lib/systemd/system-shutdown/upload.service
sudo vim /lib/systemd/system-shutdown/upload.service
[Unit]
Description=upload files into dropbox
Before=shutdown.target reboot.target
Requires=network-online.target
After=network.target
[Service]
ExecStop=/bin/true
ExecStart=/bin/bash /home/upload.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
2.2 vim /home/upload.sh
cd /home
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer xxxx" \
--header "Dropbox-API-Arg: {\"path\":\"/test.txt\",\"mode\":{\".tag\":\"overwrite\"}}" \
--header "Content-Type: application/octet-stream" \
--data-binary @"test.txt"
2.3 sudo systemctl enable /lib/systemd/system-shutdown/upload.service
答案2
在系统停机时运行程序或脚本的最佳方法是使用ExecStop=
单元的 来运行此类程序。ExecStart=
可以是虚拟脚本(例如/bin/true
),或者在最新版本的 systemd 中,甚至可以省略它。
关于依赖关系,你想把你的单位后您需要的服务,例如,network-online.target
如果systemd-resolved.service
您正在使用它进行 DNS 解析。原因是系统在关机时会按启动时的相反顺序停止。因此,通过订购您的服务后依赖项,这意味着你的ExecStop=
脚本将运行前依赖关系已停止。
类似这样的事情应该可以工作:
[Unit]
Description=upload files into dropbox
After=network.target systemd-resolved.service
Requires=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/bin/bash /home/upload.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
像往常一样启用该单元(该--now
参数也启动它):
$ sudo systemctl enable --now upload.service
并且它将在以下情况下执行上传停止,你可以用它测试:
$ sudo systemctl stop upload.service
这是最近讨论在 systemd-devel 邮件列表中。
答案3
Execstop 和 Execstart 反转
根据这个Unix&Linux答案:如何在关机前使用 systemd 运行脚本,你的 Execstop 和 Execstart 是相反的。
行:
ExecStop=/bin/true
ExecStart=/bin/bash /home/upload.sh
应该读:
ExecStart=/bin/true
ExecStop=/bin/bash /home/upload.sh
答案继续提到重新启动服务。因此,在创建文件后,请systemctl daemon-reload
确保systemctl enable yourservice --now
替代方法不起作用
before=
、等requires=
有时会令人困惑。您可以将脚本放在/usr/lib/systemd/system-shutdown/
目录中。它将在关机时立即运行。请参阅:https://superuser.com/questions/1016827/how-do-i-run-a-script-before-everything-else-on-shutdown-with-systemd
在某些系统上前缀/usr
可能不同,例如,目录名仅以 开头/lib
。