How to read user input during boot stage with systemd in Linux


Deepak Prasad

How To

In this article I will share a sample systemd unit file which can be used to read user input during boot stage using shell script with systemd in RHEL/CentOS 7/8 Linux. It is possible that for a system administrator there are some tasks such as setting hostname or something which requires him/her to read user input during boot stage before login prompt comes up. And then based on the user input certain task is performed using a background script.

This is possible using systemd unit service file in RHEL/CentOS 7/8 Linux.

 

Some more articles on similar topic:

 

Step 1: Overview on systemd

I hope you are already familiar with below topics

 

Step 2: Create Sample script

We will use a custom small script with until loop to read user input during boot stage. So unless the script gets the user input, it will not allow the boot stage to complete.

[root@centos-8 ~]# cat /tmp/welcome.sh
#!/bin/bash
until [[ -n ${REPLY} ]]; do
    read -ep "Enter your name: "
done
echo "WELCOME ${REPLY^^}"; sleep 5

Here the script will prompt "Enter your name" and then will wait for user input. If we call this script at boot up stage then the script will read user input during boot stage and proceed accordingly.

 

Step 3: Create systemd unit service file to read user input during boot stage

Now we need a systemd unit service file which will call our script at boot stage to read user input. The file should be located in either /usr/lib/systemd/system/ or /etc/systemd/system/. Below is a sample systemd unit service file:

[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 getty@tty1.service

[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 getty@tty1.service

Here,

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

Refresh the systemd configuration files

[root@centos-8 ~]# systemctl daemon-reload

Enable the service to automatically start at next boot

[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/getty@tty1.service.requires/take-user-input.service → /etc/systemd/system/take-user-input.service.

Now you are all done, proceed with the reboot of the Linux node.

 

Step 4: Verify the systemd unit file configuration

Post reboot connect to the GUI console of you Linux host, since I am using Oracle VirtualBox, I will connect to the console of my Virtual Machine.

Here as you see the booting has halted and is awaiting for user input from our script /tmp/welcome.sh

How to read user input during boot stage in CentOS/RHEL 7/8 Linux

Once you give the input the booting of your Linux OS will continue.

As this stage we had explicitly used Before=sshd.service and After=network.target to execute script before activating sshd hence sshd will not be active at this stage although network should be active.

 

References:
How to allow a custom service script in RHEL7 to run in the foreground and accept user input

 

Lastly I hope the steps from the article to read user input during boot stage using systemd on CentOS/RHEL 7 Linux was helpful. So, let me know your suggestions and feedback using the comment section.

 

Related Searches: read user input in shell script at boot stage in Linux. bash read input from stdin during boot up. take input at the startup script in Linux.

Views: 39

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can reach out to him on his LinkedIn profile or join on Facebook page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

6 thoughts on “How to read user input during boot stage with systemd in Linux”

  1. Hi, thanks for your help. The steps works well for Ubuntu but with Debian doesn’t work. I got this error:

    ● firstboot.service - Get user input at boot stage
       Loaded: loaded (/etc/systemd/system/firstboot.service; enabled; vendor preset
       Active: failed (Result: exit-code) since Sun 2021-08-08 20:40:47 UTC; 17s ago
      Process: 766 ExecStartPre=/usr/bin/chvt 13 (code=exited, status=203/EXEC)
    
    Aug 08 20:40:47 debiandev systemd[1]: Starting Get user input at boot stage...
    Aug 08 20:40:47 debiandev systemd[766]: firstboot.service: Failed to execute com
    Aug 08 20:40:47 debiandev systemd[766]: firstboot.service: Failed at step EXEC s
    Aug 08 20:40:47 debiandev systemd[1]: firstboot.service: Control process exited,
    Aug 08 20:40:47 debiandev systemd[1]: firstboot.service: Failed with result 'exi
    Aug 08 20:40:47 debiandev systemd[1]: Failed to start Get user input at boot sta
    Reply
    • I am afraid I don’t have a Debian setup but the logs should help. You can use journalctl -u firstboot and go to the last line to check the recent logs

      Reply
      • root@debiandev:~# journalctl -u firstboot
        -- Logs begin at Mon 2021-08-09 14:02:08 UTC, end at Mon 2021-08-09 14:03:02 UTC
        Aug 09 14:02:12 debiandev systemd[1]: Starting Get user input at boot stage...
        Aug 09 14:02:12 debiandev systemd[727]: firstboot.service: Failed to execute com
        Aug 09 14:02:12 debiandev systemd[727]: firstboot.service: Failed at step EXEC s
        Aug 09 14:02:12 debiandev systemd[1]: firstboot.service: Control process exited,
        Aug 09 14:02:12 debiandev systemd[1]: firstboot.service: Failed with result 'exi
        Aug 09 14:02:12 debiandev systemd[1]: Failed to start Get user input at boot sta
        Aug 09 14:02:13 debiandev systemd[1]: Starting Get user input at boot stage...
        Aug 09 14:02:13 debiandev systemd[738]: firstboot.service: Failed to execute com
        Aug 09 14:02:13 debiandev systemd[738]: firstboot.service: Failed at step EXEC s
        Aug 09 14:02:13 debiandev systemd[1]: firstboot.service: Control process exited,
        Aug 09 14:02:13 debiandev systemd[1]: firstboot.service: Failed with result 'exi
        Aug 09 14:02:13 debiandev systemd[1]: Failed to start Get user input at boot sta
        Aug 09 14:02:36 debiandev systemd[1]: Starting Get user input at boot stage...
        Aug 09 14:02:36 debiandev systemd[741]: firstboot.service: Failed to execute com
        Aug 09 14:02:36 debiandev systemd[741]: firstboot.service: Failed at step EXEC s
        Aug 09 14:02:36 debiandev systemd[1]: firstboot.service: Control process exited,
        Aug 09 14:02:36 debiandev systemd[1]: firstboot.service: Failed with result 'exi
        Aug 09 14:02:36 debiandev systemd[1]: Failed to start Get user input at boot sta
        Aug 09 14:03:02 debiandev systemd[1]: Starting Get user input at boot stage...
        Aug 09 14:03:02 debiandev systemd[752]: firstboot.service: Failed to execute com
        Aug 09 14:03:02 debiandev systemd[752]: firstboot.service: Failed at step EXEC s
        Aug 09 14:03:02 debiandev systemd[1]: firstboot.service: Control process exited,
        Aug 09 14:03:02 debiandev systemd[1]: firstboot.service: Failed with result 'exi
        Aug 09 14:03:02 debiandev systemd[1]: Failed to start Get user input at boot sta
        Reply

Leave a Comment

GoLinuxCloud Logo


We try to offer easy-to-follow guides and tips on various topics such as Linux, Cloud Computing, Programming Languages, Ethical Hacking and much more.

Programming Languages

JavaScript

Python

Golang

Node.js

Java

Laravel