在 Ubuntu 上使用 systemd 配置开机执行脚本

简述

在配置自用服务器时,经常需要在开机后启动某些服务。人工登录后手动启动服务肯定可行,但本文希望节省人工干预的时间。省出来的时间可以用来陪家人、学习、锻炼身体,也可以用来发呆、睡觉,反正就不要花时间进行重复的机械性操作。

为此,本文使用 systemd 配置的方式让 Ubuntu 系统在开机且未登录的的状态下执行特定的 Shell 脚本。

本文原为《基于加密的 RAID-1 硬盘阵列搭建 Nextcloud 私有网络硬盘服务》文章中阐述配置开机启动 Nextcloud 服务的章节,因配置开机执行脚本的方法具有通用的参考价值,故另起本文详述。

systemd

systemd 可以看作是 Linux 系统下的服务管理者,已被应用到很多主流的 Linux 发行版中(如 Ubuntu, Debian, Fedora 等)用于系统管理。如在 Ubuntu 20.04 上用命令行关机,可直接使用如下 systemd 提供的命令:

sudo systemctl poweroff

本文选取 systemd 实现开机执行 Shell 脚本有两个原因:

  1. 配置方法简便。
  2. systemd 已被 Linux 发行版广泛采用,使用 systemd 在开机时执行脚本可以认为是一种官方建议做法。

通用操作步骤

  • 创建希望开机马上执行的脚本,本文举例脚本存放位置为 /home/tqh/Documents/Example/StartupScipt.sh,脚本内容如下:
#!/bin/sh
# 开机时在脚本的同级目录下创建一个名为 StartupTouch.txt 的文件
touch /home/tqh/Documents/Example/StartupTouch.txt
  • 开机执行的脚本需增加可执行权限才能被 systemd 运行,使用如下命令
chmod u+x /home/tqh/Documents/Example/StartupScipt.sh
chmod g+x /home/tqh/Documents/Example/StartupScipt.sh
  • 进入 systemd 放置 service 的目录,在该目录下可看到大量服务配置文件,命令如下
# 进入 systemd 的 service 目录
cd /etc/systemd/system
# 查看文件列表
ls -al
  • 在该目录创建一个新的 .service 文件用于配置开机启动脚本,本例中的文件名为 StartupExample.service,所执行命令和文件中的配置内容如下:
# 创建服务配置文件
sudo touch /etc/systemd/system/StartupExample.service

# 以下为 StartupExample.service 配置文件的内容
[Unit]
Description=Startup Example

[Service]
ExecStart=/home/tqh/Documents/Example/StartupScipt.sh

[Install]
WantedBy=multi-user.target
  • 尝试手动运行新创建的 service,使用如下命令:
# 手动运行 StartupExample.service
sudo systemctl start StartupExample.service
# 查看运行日志
systemctl status StartupExample.service
运行日志显示:服务启动成功
  • 查看服务中创建的文件是否创建成功,使用如下命令:
ls -al /home/tqh/Documents/Example/
文件创建成功,证明服务配置已生效
  • 删除文件后将服务设置为 enable 状态,再重启计算机,看服务是否能正常运行。使用如下命令:
# 删除刚测试服务时创建的文件
rm -f /home/tqh/Documents/Example/StartupTouch.txt
# 设置服务为 enable 状态,使之能开机运行
sudo systemctl enable StartupExample.service
# 重启机器
systemctl reboot
  • 下图中能看到开机运行的脚本中 touch 的文件已经创建成功
文件创建成功,证明开机运行的脚本已配置完成

启动 Nextcloud 服务的操作步骤

本章将对《基于加密的 RAID-1 硬盘阵列搭建 Nextcloud 私有网络硬盘服务》一文中配置开机启动 Nextcloud 服务的部分进行细述,除用到上述通用的操作步骤外,还有特殊情况需要讨论处理。

  • 创建启动 Nextcloud 服务的脚本并为之增加可运行权限,操作如下
# 创建开机启动 Nextcloud 的脚本
touch /mnt/data/nextcloud/start_nextcloud.sh

# 为脚本增加可执行权限
chmod u+x /mnt/data/nextcloud/start_nextcloud.sh
chmod g+x /mnt/data/nextcloud/start_nextcloud.sh
  • 编辑脚本内容如下
#!/bin/sh

docker start nextcloud_container
《基于加密的 RAID-1 硬盘阵列搭建 Nextcloud 私有网络硬盘服务》使用 docker run 创建 nextcloud 镜像的 container(名为 nextcloud_container),在开机执行的脚本中使用 docker start 启动该 container 即可。
不建议每次都用 docker run 来启动 nextcloud 服务,会产生许多无用的 container 占用磁盘空间。
  • 在 /etc/systemd/system 目录下新建服务描述文件 Nextcloud.service,操作及文件内容如下
# 创建 systemd 使用的 service 描述文件
sudo touch /etc/systemd/system/Nextcloud.service

# 以下为 Nextcloud.service 的文件内容
[Unit]
Description=Nextcloud Service

[Service]
ExecStart=/mnt/data/nextcloud/start_nextcloud.sh

[Install]
WantedBy=multi-user.target
  • 设置 Nextcloud.service 为开机启动并重启计算机,操作如下
# 设置 Nextcloud.service 为开机启动
sudo systemctl enable Nextcloud.service
# 重启机器
sudo systemctl reboot
  • 重启后查看运行日志,所执行命令及其结果如下
# 查看 systemd 的运行日志
systemctl status Nextcloud.service
执行失败:找不到脚本文件
根据日志中的报错信息,发现开机后 systemd 要执行 Nextcloud.service 时找不到脚本。结合该文中加密硬盘阵列分区的使用方法,可疑的原因是启动服务时脚本所在的硬盘分区未挂载完成
解决的思路是等待分区挂载完成再执行启动 Nextcloud 服务的脚本。
  • 先找到挂载 /mnt/data 的服务,使用命令和运行结果如下
systemctl list-unit-files
在 systemd 的 UNIT 列表中找到了 mnt-data.mount 的挂载操作
  • 使用文本工具修改 Nextcloud.service 文件,增加语句 “ After=mnt-data.mount ”保证硬盘分区的挂载操作先执行,修改后的文件如下
[Unit]
Description=Nextcloud Service
After=mnt-data.mount

[Service]
ExecStart=/mnt/data/nextcloud/start_nextcloud.sh

[Install]
WantedBy=multi-user.target
  • 重启计算机后查看 systemd 执行日志,使用命令和运行结果如下
# 重启机器
sudo systemctl reboot
# 查看 systemd 的运行日志
systemctl status Nextcloud.service
Nextcloud.service 启动成功

至此, 开机启动 Nextcloud 服务的配置操作已经完成。

附语

有很多特殊原因可能导致使用通用的 systemd 配置开机启动脚本方法时失败,建议使用 systemd 的 status 命令查看日志以定位问题。

systemctl status ***.service

编辑于 2021-12-10 01:47