我有一个脚本(不是我写的,我无法修改它),它必须运行几天,有时会失败(退出时出现错误)。
在这种情况下我所要做的只是重启服务器(目前没有更好的解决方案),以及重新开始剧本。目前我这样做:
通过 SSH 登录
screen -S job
./myscript.sh
启动作业(假设此脚本仅包含:dothis
并且此过程可能会因错误而退出)CTRL A,D从屏幕分离
……等几个小时……
登录后,使用 恢复屏幕
screen -r job
。如果仍在运行,请断开并稍后返回。
如果脚本失败,sudo reboot
则从步骤 1 开始,以使冗长的作业继续进行。
如何在没有人工干预的情况下做到这一点?
如果脚本存在错误,如何自动执行此操作并让服务器自动重新启动,然后重新启动脚本?
答案1
首先,我会尝试将该脚本放入容器中。这将从主机本身中删除一些依赖项,并允许自动重新启动。
使用 docker 和 docker-compose 的解决方案
这种方法需要 docker 和 docker compose。如果您有 Ubuntu,您可以通过安装它们sudo apt install docker.io docker-compose
。
- 创建一个 Dockerfile 来构建容器,例如:
FROM ubuntu
COPY /path/to/script/on/host /myscript.sh
# maybe deal with some dependencies here
CMD /bin/bash /myscript.sh
将以上命名保存Dockerfile
在任意文件夹中。您可以在以下位置查看一些文档https://docs.docker.com/engine/reference/builder/
- 创建 docker-compose.yml
version: "3.9"
services:
scriptrunner:
build: .
restart: always
将其放置docker-compose.yml
在同一目录作为你的 Dockerfile。请参阅此处的一些文档:https://docs.docker.com/compose/compose-file/compose-file-v3/
我假设您想要获得脚本的一些输出,在这种情况下,您可能必须设置 docker 卷以在主机和容器之间“共享”文件夹。
- 转到终端中的文件夹并输入
docker-compose up -d
.
使用此方法,您将脚本放入容器中,在每个脚本失败后重新启动容器,并将作为守护进程运行。
使用systemd的解决方案
如果您不想处理容器,可以将脚本包装在另一个容器中,例如my-runner.sh
.
#!/bin/bash
/path/to/my-script.sh || systemctl reboot
这将在脚本失败后重新启动您的计算机。请注意,重新启动可能需要不同的命令或 root 权限。
现在,让我们为我们的运行脚本创建一个 systemd 服务。这是一个很好的教程,但可以归结为以下几点:
创建一个 systemd 单元文件,/etc/systemd/system/my-script.service
并将以下内容放入其中。
[Unit]
Description=my script runner service
After=network.target
Type=simple
User=my-user
ExecStart=/path/to/the/previous/my-runner.sh
[Install]
WantedBy=multi-user.target
现在您只需发出命令systemcl start my-script && systemctl enable my-script
即可启动它并使其在重新启动后启动。