How to allow a custom service script in RHEL7 to run in the foreground and accept user input
https://access.redhat.com/solutions/1466153
SOLUTION 已验证 - 已更新 2019年三月14日06:49 -
环境
- Red Hat Enterprise Linux 7
问题
- How to start a script at boot time in the foreground and let it accept keyboard input?
决议
NOTE: Red Hat does not support implementation of custom scripts, including custom systemd startup scripts. This article is provided as a how-to and Red Hat will not troubleshoot any issues after the implementation of the steps provided here. For more information please see the Production Support Scope of Coverage
See also: man systemd-ask-password
-
Create a new service unit file at
/etc/systemd/system/example.service
1 with content based on the following[Unit] Description=Example Interactive Service Script description goes here After=network.target Before=sshd.service systemd-logind.service getty@tty1.service [Service] Type=oneshot TTYPath=/dev/tty13 ExecStartPre=/usr/bin/chvt 13 ExecStart=/usr/local/sbin/example.sh ExecStartPost=/usr/bin/chvt 1 TimeoutStartSec=0 StandardInput=tty TTYVHangup=yes TTYVTDisallocate=yes [Install] WantedBy=default.target RequiredBy=sshd.service systemd-logind.service getty@tty1.service
Optionally, consult footnotes of individual arguments for explanation:
After=
2Before=
3TTYPath=
4ExecStartPre=/usr/bin/chvt 13
5ExecStart=
6ExecStartPost=/usr/bin/chvt 1
7TimeoutStartSec=
8StandardInput=tty
9TTYVTDisallocate=
10 -
Create the example shell script mentioned in the unit file's
ExecStart
directive
For example, save the following to/usr/local/sbin/example.sh
, making sure the file is executable#!/bin/bash until [[ -n ${REPLY} ]]; do read -ep "Enter your name: " done echo "WELCOME ${REPLY^^}"; sleep 5
-
Enable the service and then reboot to test
systemctl enable example.service reboot
-
The file should be located in either
/usr/lib/systemd/system/
or/etc/systemd/system/
. See UNIT LOAD PATH section inman systemd.unit
. ↩ -
After=
If the script needs any other system facilities (networking, etc), modify the[Unit]
section to include appropriateAfter=
,Wants=
, orRequires=
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 aBefore=XYZ.service
in the[Unit]
section and a correspondingRequiredBy=XYZ.service
in the[Install]
section. For more discussion, see: How to prevent console and ssh logins until a service has started in RHEL7. ↩ -
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 thechvt
command to access them). ↩ -
ExecStartPre=/usr/bin/chvt 13
This changes the physical console to tty13 (i.e., the tty specified withTTYPath=
). ↩ -
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 withinTimeoutStartSec
, systemd considers the service failed; for long-running shell scripts it is essential to modifyTimeoutStartSec
or disable the timeout logic altogether as above, withTimeoutStartSec=0
. Seeman systemd.service
for more details. ↩ -
StandardInput=tty
This line is absolutely necessary; without specifying the valuetty
here, this setting defaults tonull
. (Note thatStandardOutput=
andStandardError=
can also be independently set; however, by default they inherit their value fromStandardInput=
.) Seeman systemd.exec
for more details. ↩ -
TTYVTDisallocate=
When set toyes
, this causes the tty (TTYPath
) to be cleared before and after use. ↩