1. Introduction

When we’re working in GUI mode, turning off the computer entails a flurry of events. Usually, we’re asked to confirm, and may be warned about other users logged in. However, while working on a remote server or in text mode, we’re not in such a comfortable position.

In this tutorial, we’ll learn how to avoid accidentally shutting down the computer with the power button.

2. What Are Input Events?

The Linux kernel translates all inputs generated by the peripheral devices into standard input events. Next, they feed all user-end applications. In turn, the application can react to them, in a configurable way. With this, we can set the GNOME action for switching off:

Configuring power button settings in GNOME

Let’s read input events from the device files with evtest:

$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:    Power Button
/dev/input/event1:    Power Button
/dev/input/event2:    Logitech Wireless Keyboard PID:4023
# ...

Subsequently, examining event1 reveals that it produces events while we’re pressing the power button:

$ sudo evtest /dev/input/event1
# ...
Input device name: "Power Button"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 116 (KEY_POWER)
Properties:
Testing ... (interrupt to exit)
Event: time 1691523460.535468, type 1 (EV_KEY), code 116 (KEY_POWER), value 1
Event: time 1691523460.535468, -------------- SYN_REPORT ------------
Event: time 1691523460.535495, type 1 (EV_KEY), code 116 (KEY_POWER), value 0
Event: time 1691523460.535495, -------------- SYN_REPORT ------------

Throughout this tutorial, we’ll run Linux in text mode. In this way, we’ll avoid interference from GUI-based applications and services, which would take their own actions otherwise.

3. How to Block the Button Events

We can intercept input events by using the –grab option of evtest:

$ sudo evtest --grab /dev/input/event1

Now we see events as they’re coming while we’re pressing the button. However, there’s no reaction to events because all interested applications are cut off from them.

4. The Inhibit Functionality

The systemd-inhibit functionality protects a command against being interrupted. The idea is to avoid disruption of actions such as CD burning or to give applications time to take appropriate actions before shutdown.

Here’s its basic syntax:

$ systemd-inhibit <command>

This runs the command and blocks system actions shutdown, sleep, and idle. However, we can pass other actions with the –what option. Additionally, we can specify the reason for protection with the –why option.

So, let’s start the stress-ng command and make sure that it won’t be interrupted by the power button:

$ systemd-inhibit --what=handle-power-key --why="stress-ng test run" stress-ng --cpu 4 --timeout 60s --metrics-brief

Then, let’s list existing inhibitors with the –list option:

$ systemd-inhibit --list
WHO UID USER PID COMM WHAT WHY MODE 
WHO                              UID  USER PID COMM            WHAT             WHY                                       MODE
ModemManager                     0    root 690 ModemManager    sleep            ModemManager needs to reset devices       delay
NetworkManager                   0    root 709 NetworkManager  sleep            NetworkManager needs to turn off networks delay
stress-ng --cpu 4 --timeout 120s 1000 joe  994 systemd-inhibit handle-power-key stress-ng test run                        block

3 inhibitors listed.

5. The logind Service

The systemd-logind service is responsible for an action taken upon clicking the power key. First, let’s check the status of the service:

$ systemctl status systemd-logind
● systemd-logind.service - User Login Management
# ...
Aug 08 17:25:39 fedora systemd-logind[728]: Watching system buttons on /dev/input/event1 (Power Button)
Aug 08 17:25:39 fedora systemd-logind[728]: Watching system buttons on /dev/input/event0 (Power Button)
# ...

Notably, the service listens to event interfaces /dev/input/event0 and event1.

The service parameter HandlePowerKey assigns the action to the power button event. By default, it’s poweroff. To change it, let’s edit logind.conf file:

$ sudo nano /etc/systemd/logind.conf

Then, let’s set the parameter’s value to ignore:

[Login]
# ...
HandlePowerKey=ignore

Afterwards, we need to restart the service:

$ sudo systemctl restart systemd-logind

6. Conclusion

In this article, we talked about input events triggered by pushing the power button. Then, we learned how to suppress them altogether. Next, we discussed the use of systemd-inhibit to protect the execution of commands. Finally, we configured the systemd-logind service to ignore the use of this button.

Finally, it’s worth noting that we can’t use the above methods to thwart the effect of long-time pressing, because this is handled by the computer firmware.