在Linux中使用systemd在引导阶段如何读取用户输入
在本文中,我将共享一个示例systemd单位文件,该文件可在RHEL/CentOS 7/8 Linux中与systemd一起使用shell脚本在引导阶段读取用户输入。
对于系统管理员来说,可能有一些任务,例如设置主机名或者某些要求他(她)在引导阶段出现之前在引导阶段读取用户输入的操作。
然后根据用户输入,使用后台脚本执行某些任务。
使用RHEL/CentOS 7/8 Linux中的systemd单元服务文件可以做到这一点。
第1步:systemd概述
希望我们已经熟悉以下主题
systemd概述以及它与旧版SysV脚本的区别
如何在Linux中创建systemd单位文件
创建示例脚本
在启动阶段,我们将使用带有直到循环的自定义小脚本来读取用户输入。
因此,除非脚本获得用户输入,否则它将不允许引导阶段完成。
[root@centos-8 ~]# cat /tmp/welcome.sh #!/bin/bash until [[ -n ${REPLY} ]]; do read -ep "Enter your name: " done echo "WELCOME ${REPLY^^}"; sleep 5
此处,脚本将提示"输入姓名",然后将等待用户输入。
如果我们在启动阶段调用此脚本,则该脚本将在启动阶段读取用户输入并进行相应的操作。
创建系统单元服务文件以在引导阶段读取用户输入
现在,我们需要一个systemd单元服务文件,该文件将在引导阶段调用脚本以读取用户输入。
该文件应该位于/usr/lib/systemd/system /
或者/etc/systemd/system /
中。
下面是一个示例的systemd单元服务文件:
[root@centos-8 ~]# cat /etc/systemd/system/take-user-input.service [Unit] Description=Get user input at boot stage After=network.target Before=sshd.service systemd-logind.service [email protected] [Service] Type=oneshot TTYPath=/dev/tty13 ExecStartPre=/usr/bin/chvt 13 ExecStart=/tmp/welcome.sh ExecStartPost=/usr/bin/chvt 1 TimeoutStartSec=0 StandardInput=tty TTYVHangup=yes TTYVTDisallocate=yes [Install] WantedBy=default.target RequiredBy=sshd.service systemd-logind.service [email protected]
其中
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 Before= If the script needs to be run before other services--for example, prior to starting sshd or console/graphical logins--ensure there is a Before=XYZ.service in the [Unit] section and a corresponding RequiredBy=XYZ.service in the [Install] section. TTYPath= Specify a tty number here (the writer's choice of tty13 here was mostly arbitrary; however, keep in mind that numbers higher than 12 require the chvt command to access them). ExecStartPre=/usr/bin/chvt 13 This changes the physical console to tty13 (i.e., the tty specified with TTYPath=). ExecStart= The full path to the main script, including any desired script arguments. ExecStartPost=/usr/bin/chvt 1 This changes the physical console back to tty1 after the script finishes (this line is not always necessary, e.g., if a display manager starts after the script, it will probably steal focus by changing the physical console back to whichever tty it is running on). 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 StandardInput=tty This line is absolutely necessary; without specifying the value tty here, this setting defaults to null. (Note that StandardOutput= and StandardError= can also be independently set; however, by default they inherit their value from StandardInput=.) For more information check man page of systemd.exec
刷新systemd配置文件
[root@centos-8 ~]# systemctl daemon-reload
启用服务以在下次启动时自动启动
[root@centos-8 ~]# systemctl enable take-user-input.service Created symlink /etc/systemd/system/default.target.wants/take-user-input.service → /etc/systemd/system/take-user-input.service. Created symlink /etc/systemd/system/sshd.service.requires/take-user-input.service → /etc/systemd/system/take-user-input.service. Created symlink /etc/systemd/system/systemd-logind.service.requires/take-user-input.service → /etc/systemd/system/take-user-input.service. Created symlink /etc/systemd/system/[email protected]/take-user-input.service → /etc/systemd/system/take-user-input.service.
现在我们已经完成了所有工作,继续重新启动Linux节点。
验证systemd单元文件配置
重启后连接到Linux主机的GUI控制台,因为我使用的是Oracle VirtualBox,所以我将连接到虚拟机的控制台。
如我们所见,其中引导已停止,正在等待我们的脚本/tmp/welcome.sh
中的用户输入。
输入后,将继续引导Linux OS。
在此阶段,我们已在激活sshd之前显式使用了" Before = sshd.service"和" After = network.target"来执行脚本,因此尽管网络应该处于活动状态,但sshd在此阶段将不活动。