9

I'd like to start xcape with a nice value of -20 as non-root. However setting a nice value of -20 requires root permissions. So I was wondering whether this is somehow possible. I also tried to create a system service and setting User=myuser, but xcape requires xorg and thus DISPLAY and XAUTHORITY

What I got so far:

[Unit]
Description=xcape: esc on caps lock
PartOf=graphical-session.target

[Service]
Type=simple
Nice=-20
ExecStart=/usr/bin/xcape -t 180 -e 'Caps_Lock=Escape'

[Install]
WantedBy=default.target
Liblor
  • 261

2 Answers2

7

I eventually came up with a workaround using sudo1 as systemd doesn't support this out of the box afaik.

1) Add command to sudoers file

First add the following line to the end of /etc/sudoers (replace myusername with your username, mycommand with the command to execute and adjust the niceness value as you like):

myusername ALL=(root) NOPASSWD: /usr/bin/nice -n -20 sudo -u myusername mycommand

Explanation:
Allow the user myusername to execute the command sudo /usr/bin/nice -n -20 sudo -u myusername mycommand as root without entering a password. Since sudo nice -n -20 mycommand would execute mycommand as root we prepend sudo -u myusername to the command, that way mycommand is executed by myusername. This is a security measure to adhere the principle of least privilege.

2) Execute the command using sudo in the service script

Now we can execute this specific command without entering a password:

[Service]
ExecStart=sudo /usr/bin/nice -n -20 sudo -u myusername mycommand

Example: xcape

/etc/sudoers

myusername ALL=(root) NOPASSWD: /usr/bin/nice -n -20 sudo -u myusername xcape -t 180 -e Caps_Lock=Escape

~/.config/systemd/user/xcape.service

[Unit]
Description=xcape: esc on caps lock
PartOf=graphical-session.target

[Service] Type=forking ExecStart=sudo /usr/bin/nice -n -20 sudo -u myusername mycommand

[Install] WantedBy=default.target

Start the service: systemdctl --user start xcape


1 One could also write a helper executable and use the setuid bit, if sudo is not available.
Liblor
  • 261
-1

Just wanted to chime in in case anyone else finds this on a web search like I have - I found the following in the systemd docs=

Nice= Sets the default nice level (scheduling priority) for executed processes. Takes an integer between -20 (highest priority) and 19 (lowest priority).....

So looks like just dropping a Nice=# property in the service file should work! I was able to get my process to start with the nice value I wanted; In my case, I was trying to help bump up the priority of my Factorio server to help latency. Worked like a charm!

(from my factorio.service file)

[Service]
User=factorio
...

Nice=-4 ExecStart=/opt/factorio/bin/x64/factorio --start-server ....

After restarting the service I checked htop & it seems to work!

screenshot of htop showing factorio's nice value