Open tceydeliler opened 7 years ago
Your USB keyboard isn't autodetected or the incorrect one (e.g. the built in one) is. Yes, those device ids might be changed at boot time by the kernel/udev.
Is there any way to use more than one device at the same time? Or Is there any way to fix event no?
Not without a pull request that does it.
Hi @kernc, I've done some work on using udev rules in combination with systemd unit files to allow the input device to be predictable via the udev rules and using a systemd service to reliably pick up that device and run logkeys with configurable settings as a service.
It would also allow a 'fix' to #38 by allowing multiple services to be started and log input from multiple keyboard devices (eg: onboard laptop keyboard and another usb device).
basically:
At the moment they are just 'templates' showing how it can be done (in the same way that you can adjust the current files in the scripts directory) but I'm interested to do some more work on it if you can point me in the right direction.
let me know.
the udev rule:
# /etc/udev/rules.d/99-logkeys.rules
#
# This udev rule works together with the systemd system and service manager to
# start and stop the logkeys program as a service.
# It provides some extra functionality by providing a starting point to be activated
# when an external keyboard is attached.
# The systemd service files can be found at /etc/systemd/system/
# one is 'logkeys.service' and the other is 'logkeys-alternate.service'
#
# When using udev to get a match on a device, make matches as specific as possible.
# this prevents multiple events generated by the udev system to be matched.
# This is what you want since multiple matches might fire a script called via "RUN" to be
# called multiple times.
#
# use ENV{name}=="value" to match on environment variables when removing devices,
# ATTRS are only available on adding
#
# ACTION: add, bind, change, remove, unbind
# SUBSYSTEMS: input, usb ..
# ATTRS{name}=="value"
# ENV{name}=="value"
# SYMLINK+="symlink in /dev/ here"
# RUN+="program invocation"
#
#
#
# helpful commands:
# udevadm monitor --environment --udev --kernel
# udevadm info -a -n <device-path>
# udevadm test $(udevadm info -q path -n device_name) 2>&1
# udevadm control --log-priority=debug
# ps auxf | grep logkeys
################################################################################
########################## fixed keyboard #########################################
# This is a fixed keyboard on a laptop
# this works together with /etc/systemd/system/logkeys.service
# and sets the correct input device up with a predictable name (instead of /dev/input/event<X>)
# find out the correct keyboard by checking:
# cat /dev/input/event<X>
# untill you see output and then
# udevadm info -a -n /dev/input/event<X>
# with the correct input device to check the attributes for the device in the udev rules key froma
# then enable and start the logkeys.service via
# systemctl enable logkeys.service
# systemctl start logkeys.service
SUBSYSTEMS=="input", ATTRS{name}=="AT Translated Set 2 keyboard", ATTRS{phys}=="isa0060/serio0/input0", SYMLINK+="input/logkeys"
########################## alternate keyboard #########################################
# it is possible to run logkeys multiple times via systemd. we can then create multiple
# service files that can be started and stopped via udev events for multiple keyboards that can be attached
# this is very useful if you are using a laptop with an external keyboard attached
# so you can always monitor the standard keyboard together with the external keyboard.
# make sure that the match is as exact as possible on start and stop.
# matching on SUBSYSTEM should always be done on 'input' since it's an input device
# on addition of the target keyboard (match it!) create a symlink and run the systemd service for the external keyboard
#ACTION=="add", SYMLINK+="input/logkeys-alternate", RUN+="/usr/bin/systemctl start logkeys-alternate.service"
#ACTION=="remove", RUN+="/usr/bin/systemctl stop logkeys-alternate.service"
# ewent keyboard
SUBSYSTEMS=="input", ATTRS{name}=="USB USB Keyboard", \
SYMLINK+="input/logkeys-alternate", RUN+="/usr/bin/systemctl start logkeys-alternate.service"
################################################################################
and the systemd service file:
[Unit]
Description=keylogger service from https://github.com/kernc/logkeys
[Service]
Type=simple
# used together with /etc/udev/rules.d/99-logkeys.rule
ExecStart=/usr/local/bin/logkeys -s -d /dev/input/logkeys --keymap /root/keymap-ewent-keyboard.txt --no-daemon
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target```
Hello and welcome, @rolfvreijdenberger!
I think that's a wonderful idea! I'd be quite willing to merge a generic udev rule and a generic systemd service. What I mean by generic is that they both should match and work for all kinds of keyboards out of the box.
I think this can be achieved with an udev rule such as:
SUBSYSTEM=="input", \
ENV{DEVNAME}=="/dev/input/event*", \
PROGRAM="/usr/share/logkeys/check-if-keyboard.sh", \
SYMLINK="logkeys-$result", \
RUN+="/bin/systemctl start logkeys@%E{SYMLINK}.service"
where the PROGRAM exits with 0 if the related device is a keyed (...) keyboard device, or if not, the whole rule fails. Roughly something like this should do it:
check-if-keyboard.sh:
#!/bin/sh
set -e
event=${DEVNAME#/dev/input/}
# Ensure keyboard
grep -q '1[02]001[3Ff]' /sys/class/input/$event/device/capabilities/ev
# Print name to be used as $result
cat /sys/class/input/$event/device/name
And then in the systemd service use %I
specifier:
ExecStart=/usr/bin/logkeys -s -d /dev/input/%I --no-daemon -o /var/log/logkeys/%i
Note, path /usr/bin/logkeys depends on $PREFIX chosen in ./configure
step of the program compilation, so this would have to be a file generated from logkeys@.service.in
template.
If you figure something out and can wrap it all in a nice PR, I'd sure have a look at it! :smiley:
a template unit file can only accept 1 parameter, of which the device would be the logical option. it would be my preferred way to go also.
then there is another parameter that's high on my list: the keyboard map (since it did not work out of the box for me). this would be nice if it was configurable also (allowing the user to do only limited adjustments to make it work.
The environment variable set in the udev rule can also be used to pass information to the unit file itself (if kickstarted from the shell file of from the udev rule), possibly providing some sort of user configurable hook to pass on the keymap. this would make it so that the user would only need to adjust the udev rule to make it work.
I'm not sure how the keymaps are detected and/or/if one keymap is usable for all keyboards attached to a system.
Will look into it a bit more then :+1:
any pointers on how to handle the differences between hotplug and coldplug devices? (this boils down to enabling a service and starting it or only starting the service).
then there is another parameter that's high on my list: the keyboard map (since it did not work out of the box for me). this would be nice if it was configurable also (allowing the user to do only limited adjustments to make it work.
I would opt for EnvironmentFile
, so that the udev rule and systemd service can be left intact.
https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html
Then the user would be advised to edit the environment file, if needed, and enable the systemd service (which should be disabled by default).
I'm not sure how the keymaps are detected and/or/if one keymap is usable for all keyboards attached to a system.
I'd imagine most users type in their one chosen layout. Some people switch between two or more layouts, but I don't know how to handle that gracefully. I guess advanced users should be able to configure their system as they wish.
any pointers on how to handle the differences between hotplug and coldplug devices?
Indeed, I think once the service is enabled (and then started for the first time), it should work the same for all devices.
I would opt for EnvironmentFile, so that the udev rule and systemd service can be left intact
sounds good
I'd imagine most users type in their one chosen layout. Some people switch between two or more layouts, but I don't know how to handle that gracefully. I guess advanced users should be able to configure their system as they wish.
thanks for clarifying, I am not familiar with the usage patterns of logkeys and have configured logkeys with devices and keyboard maps myself. looking at the documentation is seems that it 'should work' by itself but logkeys has never done that for me. nothing big, configuring is easy.
Indeed, I think once the service is enabled (and then started for the first time), it should work the same for all devices.
detecting the onboard input device is done early in the boot sequence, so you can just start the service. there is no need to synch the service with a systemd target . In my example above, the goal is to detect the onboard and peripheral keyboards via udev. The onboard keyboard can always be started and enabled (before the multi-user.target as in the example), but enabling does not seem to be necessary since if it is detected we can start the service (start via udev event instead of via the 'enable' of systemd) the peripheral keyboard is hotplugable (and detachable) and can thus be started at 'detection' time also without the need to be enabled (which is an auto start at system initialization time basically). so that service can be opportunistically started without being enabled also
I'm actually not familiar with systemd that much. :blush: What I meant is that I would prefer the service file to be installed (upon e.g. make install
) but in latent, inactive state. So systemd doesn't start logkeys neither for onboard keyboard nor for keyboards plugged in anytime later, until the system admin at one time decides specifically to run sudo systemctl enable logkeys
(or similar). Only after that should the keyboards (all kinds) be logged automatically.
Hi, I have a ubuntu laptop and I use USB keyboard. If dont use "--device " switch I get nothing. To get keystrokes I have use this switch. But, ltough I put same USB port, device (/dev/input/event..) changes after restart. Is there any way to use more than one device at the same time? Or Is there any way to fix event no?
Hi, My new keyboard seems to be not auto detected by logkeys and event number indeed changes after each restart. logkeys seems to be hard-coded to refuse using any other directory, including "by-id", which would totally fix this issue. BUT I use these commands to work around this problem:
sudo ln -s /dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-kbd /dev/input/keebord sudo logkeys -d keebord -s -o /home/mctom/myass
What it does is it creates a softlink of my keyboard, from "by-id" directory to dev/input/something. Then logkeys is fed something as its event file. Works every time when I reboot my machine. Hope it helps!
@tomek-szczesny Thanks for the fix. Does the symlink stays after a reboot? In my case it's not, maybe it depends of the OS. Anyway, I added the symlink creation on my custom systemd service (using ExecStartPre
and ExecStopPost
).
After some testing, it looks like that logkeys only use the last part of the path specified to the -d
option. Which means we can't directly specify device aliases present in /dev/input/by-id
or /dev/input/by-path
.
-d /dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-kbd
is resolved to /dev/input/usb-Logitech_USB_Receiver-if02-event-kbd
.
Because I thought that logkeys was replacing -d XXX
to /dev/input/XXX
, maybe using the following may have worked, but no:
-d by-id/usb-Logitech_USB_Receiver-if02-event-kbd
is resolved to /dev/input/usb-Logitech_USB_Receiver-if02-event-kbd
.
@scotow
Does the symlink stays after a reboot?
No, it didn't stay on my Linux Mint system. I included my workaround in a script that ran on each boot.
I guess it should be quite easy to fix within the code of logkeys, but maybe @kernc has a valid reason to let this stay the way it is.
Does the symlink stays after a reboot?
/dev
is constructed by kernel/udev on each boot.
I'm not particualrly active in maintaining this, but improvements (PRs) sure are welcome.
Hi, I have a ubuntu laptop and I use USB keyboard. If dont use "--device " switch I get nothing. To get keystrokes I have use this switch. But, ltough I put same USB port, device (/dev/input/event..) changes after restart. Is there any way to use more than one device at the same time? Or Is there any way to fix event no?