如何在Linux中使用systemd在启动时运行脚本
在本文中,我将共享一个示例systemd单位文件,我们可以使用该文件在systemd启动时运行脚本,而无需在RHEL/CentOS 7/8 Linux中使用crontab。
当我们期望启动时调用脚本或者命令时,可能有多种情况,例如
等待N分钟的启动后执行脚本
加载所有systemd服务后执行脚本
登录提示出现后立即执行脚本
在登录提示出现之前执行脚本
在本文中,我将介绍以下两个主题,因为它们几乎相似
网络可达后,在启动时使用systemd运行脚本
加载所有systemd服务后,在starup上执行脚本
我将使用CentOS/RHEL 7/8 Linux节点来验证本文中的步骤,以在登录提示之前立即使用systemd运行脚本。
第1步:systemd概述
希望我们已经熟悉以下主题
systemd概述以及它与旧版SysV脚本的区别
如何在Linux中创建systemd单位文件
创建示例脚本
现在要使用systemd在启动时运行脚本,首先我们需要一个脚本或者命令。
为了这篇文章,我创建了一个虚拟的shell脚本/tmp/startup_script.sh
,我们将使用它来测试本文。
[root@centos-8 ~]# cat /tmp/startup_script.sh #!/bin/bash SCRIPT_NAME=$(basename -- "[root@centos-8 ~]# chmod u+x /tmp/startup_script.sh") z=0 for i in {1..5}; do sleep 1m ((z++)) wall $SCRIPT_NAME: finished minute ${z} done wall $SCRIPT_NAME: COMPLETELY FINISHED
该脚本将继续运行5分钟,并使用" wall"命令为每一个节点上的所有Linux用户每分钟在屏幕上打印一条echo语句作为广播消息。
并在第5分钟结束时将打印完整的广播。
这样,如果脚本继续运行5分钟,我们还可以确保该脚本不会被systemd杀死。
提供脚本的可执行权限
[root@centos-8 ~]# systemctl enable run-at-startup.service Created symlink /etc/systemd/system/default.target.wants/run-at-startup.service → /etc/systemd/system/run-at-startup.service.
启用服务以确保重新启动后自动调用该服务
[root@centos-8 ~]# cat /etc/systemd/system/run-at-startup.service [Unit] Description=Run script at startup after network becomes reachable After=network.target [Service] Type=simple RemainAfterExit=yes ExecStart=/tmp/startup_script.sh TimeoutStartSec=0 [Install] WantedBy=default.target
为不同情况创建系统化的单位文件
.1:网络可访问后,在启动时使用systemd运行脚本
在这种情况下,我们将在网络可访问时(即,在启动阶段network.target开始运行时使用After = network.target
)开始执行脚本。
单位文件应该位于/usr/lib/systemd/system
或者/etc/systemd/system
中。
我将其放置在"/etc/systemd/system"下,因为它用于放置自定义单元文件。
[root@centos-8 ~]# cat /etc/systemd/system/run-at-startup.service [Unit] Description=Run script at startup after all systemd services are loaded After=default.target [Service] Type=simple RemainAfterExit=yes ExecStart=/tmp/startup_script.sh TimeoutStartSec=0 [Install] WantedBy=default.target
.2:在加载所有systemd服务之后,使用systemd在启动时运行脚本
现在,在此senario中,我们必须确保在启动脚本之前已加载了相应目标的所有系统服务。
因此,要在加载所有systemd服务之后使用systemd在启动时运行脚本,我们必须相应地定义After =
指令。
由于default.target会根据环境而变化,因此,我们将使用After = default.target
而不是指定特定的目标名称,因此systemd将决定它自己的default.target并在Linux启动时调用脚本。
[root@centos-8 ~]# cat /etc/systemd/system/run-at-startup.service [Unit] Description=Run script at startup after all systemd services are loaded After=getty.target [Service] Type=simple RemainAfterExit=yes ExecStart=/tmp/startup_script.sh TimeoutStartSec=0 [Install] WantedBy=default.target
.3:在出现登录提示后,使用systemd在启动时运行脚本
现在在这种情况下,我们也将只使用单位文件的After =
指令。
现在,由于要求是在出现登录提示后使用systemd在启动时运行脚本,因此我们将使用After = getty.target
。
After= If the script needs any other system facilities (networking, etc), modify the [Unit] section to include appropriate After=, Wants=, or Requires= directives, as described in: man systemd.unit Type= Switch Type=simple for Type=idle in the [Service] section to delay execution of the script until all other jobs are dispatched (see man systemd.service for even more choices -- e.g., Type=oneshot can be useful in concert with other services). TimeoutStartSec= When a service doesn't signal start-up completion within TimeoutStartSec, systemd considers the service failed; for long-running shell scripts it is essential to modify TimeoutStartSec or disable the timeout logic altogether as above, with TimeoutStartSec=0. See man systemd.service for more details.
其中
[root@centos-8 ~]# systemctl daemon-reload [root@centos-8 ~]# systemctl enable run-at-startup.service
其中如果我们观察到,我们已经定义了After = network.target
以确保脚本
刷新systemd配置文件并启用服务
[root@centos-8 ~]# ps -ef | grep startup root 805 1 0 11:38 ? 00:00:00 /bin/bash /tmp/startup_script.sh root 1198 1147 0 11:39 pts/0 00:00:00 grep --color=auto startup
验证systemd单元文件配置
现在,我们的配置已经就绪,可以在CentOS/RHEL 7/8 Linux中启动时运行脚本。
提示:
我们还可以在脚本中使用systemctl list-jobs
来监视启动时执行脚本时的活动作业列表。
现在,在重新启动Linux节点后,我们可以看到startup_script.sh在后台运行
Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:39: startup_script.sh: finished minute 1 Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:40: startup_script.sh: finished minute 2 Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:41: startup_script.sh: finished minute 3 Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:42: startup_script.sh: finished minute 4 Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:43: startup_script.sh: finished minute 5 Broadcast message from [email protected] (somewhere) (Thu Jan 16 11:43: startup_script.sh: COMPLETELY FINISHED
同样在一段时间后,我们开始从root用户那里获取广播消息。
##代码##我已经验证了这两种方案的脚本,以便在Linux中使用systemd(不使用crontab)启动时运行脚本,但是由于两种情况的输出相同,因此我没有将这两种方案的输出都放入。
说明:
引导后,使用systemd-analyze plot> file.svg
生成引导过程的镜像以进行检查。
我们可以使用任何浏览器来查看此file.svg
并验证启动过程。
在run-at-startup.service之后,可能会有一两个短暂的服务开始。
如果有问题,请修改/etc/systemd/system/run-at-startup.service以设置Type = idle。