Linux: how to run commands by keypress on the local console

This is probably not the only way to do this, and just something I had to dig up to be able to control the piStorm from the console keyboard without being logged in.

After trying to find some built-in way of doing it, I ended up using ‘lirc’ (‘inputlircd’) to fetch the keystrokes and execute appropriate commands in the background. The guide is not intended to be complete, and it’s not even re-tested because of the trial-and-error attempt on getting this working the first time, and not taking any notes.

The most useful resource for the success was:
How to run script on keypress? (superuser.com)

Required steps to getting started with lirc

Become root

sudo su -

Install required packages:

apt -y install lirc inputlirc input-utils socat

Configuration
Find the input device you wish to capture keypresses from:

lsinput

The not really necessary step
Examine the inputlirc start/stop script “/etc/init.d/inputlirc” to see where it looks for configuration:

...
DAEMON="/usr/sbin/inputlircd"
NAME="inputlirc"
DESC="inputlirc"

test -x $DAEMON || exit 0

[ -r /etc/default/$NAME ] && . /etc/default/$NAME
...

The marked lines in the partial content of “/etc/init.d/inputlirc” reveals that a file “/etc/default/inputlirc” is sourced.

Change startup parameters for inputlircd
“/etc/default/inputlirc” contains parameters for running inputlircd, including the input device to capture events from and the parameters to the service looking for keystrokes.

Read the inputlircd manpage (man 8 inputlircd) to find out which parameters you need/want to use. The below is what I had to put in the file:

# Options to be passed to inputlirc.
EVENTS="/dev/input/event0"
OPTIONS=-m 0 -c

-m 0 = -m sets the lowest keycode to pass to the daemon
I also use -c to allow to capture the modifier keys (CTRL, SHIFT, ALT) so they will be part of a keystroke instead of generating their own events. This will make it possible to use combinations like SHIFT + F1 for command execution.

After editing and saving the file, enable and (re)start the inputlirc service:

systemctl enable inputlirc
systemctl restart inputlirc

Then check that it’s running:

systemctl status inputlirc

The irexec service
To make the irexec service restart when inputlirc is restarted (due to a key configuration change), the service startup file has to be slightly modified:

/lib/systemd/system/irexec.service:

[Unit]
Documentation=man:irexec(1)
Documentation=http://lirc.org/html/configure.html
Documentation=http://lirc.org/html/configure.html#lircrc_format
Description=Handle events from IR remotes decoded by lircd(8)
After=inputlirc.service
Requires=inputlirc.service
...

Add the lines marked above, then rebuild the systemd service configuration file and restart the irexec service:

systemctl daemon-reload
systemctl restart irexec

Snooping for keypress events
Unless you know all the keycodes you are going to use for running commands, now is a good time to check what lircd receives on specific keypresses. Run the command to snoop for keypresses in the shell, and press keys on the keyboard connected to the computer (this could be connected through USB, PS/2, Bluetooth, IR, whatever)

socat UNIX-CONNECT:/var/run/lirc/lircd STDOUT

Sample output (F12 and modifier keys)

root@raspberrypi:~# socat UNIX-CONNECT:/var/run/lirc/lircd STDOUT
58 0 SHIFT_KEY_F12 /dev/input/event0
58 0 CTRL_SHIFT_KEY_F12 /dev/input/event0

Configuring what to run on keypresses
The file “/etc/lirc/irexec.lircrc” contains the configuration for what commands to run when selected key(combinations) are used. Wipe out all the defaults in there and add something useful. The below is my very specific settings for switching between piStorm configurations:

begin
    prog   = irexec
    button = SHIFT_KEY_F1
    config = cp /home/pi/a1200_4068.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F2
    config = cp /home/pi/a1200_4068-nohd.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F3
    config = cp /home/pi/a500_345.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F4
    config = cp /home/pi/a500_37175.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F5
    config = cp /home/pi/mb_ks.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F6
    config = cp /home/pi/diagrom.cfg /home/pi/default.cfg; sudo systemctl restart pistorm
end

begin
    prog   = irexec
    button = SHIFT_KEY_F12
    config = sudo systemctl stop pistorm; sudo reboot
end

begin
    prog   = irexec
    button = CTRL_SHIFT_KEY_F12
    config = sudo systemctl stop pistorm; sudo halt -p
end

Whenever you have made a change to /etc/lirc/irexec.lircrc, you need to restart inputlirc (which automatically restarts liexec):

systemctl restart inputlirc

I have used SHIFT+F12 for a safe reboot, and CTRL+SHIFT+F12 for a shutdown of the pi. If running piStorm in RTG mode there can be a delay of about 1 minute before something happens. You can check the status of the piStorm service to see that it received the shutdown command:

root@raspberrypi:~# systemctl status pistorm
● pistorm.service - Start piStorm 68k emulator
   Loaded: loaded (/lib/systemd/system/pistorm.service; disabled; vendor preset: enabled)
   Active: deactivating (final-sigterm) since Sat 2021-04-24 23:48:43 BST; 1min 6s ago
  Process: 1023 ExecStart=/home/pi/start-emulator.sh (code=killed, signal=TERM)
 Main PID: 1023 (code=killed, signal=TERM)
    Tasks: 10 (limit: 873)
   CGroup: /system.slice/pistorm.service
           ├─1024 sudo ./emulator --config /home/pi/default.cfg
           └─1025 ./emulator --config /home/pi/default.cfg

Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: [MUSASHI] Mapped read range 4: 40000000-48000000
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: [MUSASHI] Mapped write range 3: 40000000-4800000
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: Platform custom range: 00E90000-80010000
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: Platform mapped range: 00200000-48000000
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: RTG display disabled.
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: Pitch: 800 (800 bytes)
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: RTG thread running
Apr 24 13:23:53 raspberrypi start-emulator.sh[1023]: error: XDG_RUNTIME_DIR not set in the environmen
Apr 24 23:48:43 raspberrypi systemd[1]: Stopping Start piStorm 68k emulator...
Apr 24 23:48:43 raspberrypi systemd[1]: pistorm.service: Main process exited, code=killed, status=15/
root@raspberrypi:~# 

One thought to “Linux: how to run commands by keypress on the local console”

Leave a Reply

Your email address will not be published. Required fields are marked *