ydotool
requires the program ydotoold
to be running in the background. Now to make this easier the developer ships a systemd
unit file with the project. If ydotoold
isn't running the program won't work.
A systemd unit file basically calls programs in the background which are needed for the OS to run. In this case we will use this file to run ydotoold
in the background as soon as we boot our device. If your distro packages ydotool
sensibly then
the service (the background program run by the file) should already be running.
To check, run:
systemctl status ydotoold.service
This should return something like this :
● ydotool.service - Starts ydotoold service
Loaded: loaded (/usr/lib/systemd/system/ydotool.service; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/system/service.d
└─10-timeout-abort.conf
Active: active (running) since Sun 2024-04-28 14:12:42 IST; 26min ago
Main PID: 1328 (ydotoold)
If don't see something like 'active (running) since...' then you'll have to start the service. To start it, run :
systemctl start ydotoold.service
To always run the service at boot time, run :
systemctl enable ydotoold.service
Now, since it's running, let's run a little test to check if yodtool is working as expected. Run :
ydotool type 'Hello World!'
This should make ydotool type 'Hello World!' on the screen.
If you are facing an error that's something along the lines of error: /tmp/.ydotool_socket : permission denied
or error: /tmp/.ydotool_socket : file not found or file doesn't exist
.
This file, /tmp/.ydotool_socket
, is a 'socket' file which the ydotoold service needs. By default this file in loacted in /tmp
.
To make sure that this is the file used by ydotoold
, make an env variable $YDOTOOL_SOCKET
with the value of tmp/.ydotool_socket
. To do this in bash, go to ~/.bashrc
and add this line :
export YDOTOOL_SOCKET=/tmp/.ydotool_socket
If you use another shell like fish and zsh, go ahead and add this variable in your config. Now, try and restart the service again :
systemctl restart ydotoold.service
Now run the test again. There is a chance that this might stil not work. If this is the case, run :
ls -l /tmp/.ydotool_socket
If the output is something along the lines of :
srw-------. 1 root root 0 Apr 28 14:18 /tmp/.ydotool_socket=
Then, you can see that the file is owned by the root user. This means the ydotool
command run by your
non-root user can't access this file, as a result of which, ydotool
won't work. To fix this we need to edit
the unit file itself.
Locate the unit file, most probably in /usr/lib/systemd/system
, if it's not there and in something like /usr/lib/systemd/user
then delete the file under the user
sub-directory and create another ydotoold.service
file under /usr/lib/systemd/system
.
This is because ydotoold
needs root privileges to run, running .service
files from the /usr/lib/systemd/system
directory also requires the same privileges.
So instead of running it with sudo
everytime, we will run the file once and ydotoold
will acquire the permissions it needs forever.
Now, open the ydotoold.service
file in your favorite editor as root (using sudo
).
You'll see something like this:
[Unit]
Description=Starts ydotoold service
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/ydotoold
ExecReload=/usr/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=180
[Install]
WantedBy=default.target
The program ydootoold
has a flag named --socket-own
which decides the ownership of the socket file, this takes in it's value in the format UID:GID
, like 1000:1000
. To get these values for yourself, run :
echo $(id -u):$(id -g)
For me it's 1000:1000
but it might be different for you.
Now go to the 'ExecStart' line and after /usr/bin/ydotoold
, add --socket-own=1000:1000
and save the file. Now this
line should look like :
[Unit]
...
[Service]
...
ExecStart=/usr/bin/ydotoold --socket-own=1000:1000
...
[Install]
...
Since you have changed the contents of the unit file, you'll first have to run :
systemctl daemon-reload
Make sure run to run :
sudo rm /tmp/.ydotool_socket
We need to remove the previous socket file before restarting the service because the old socket file will be used, which would still be owned by root. Removing that file results in the creation of a new file owned by your user.
Now finally run :
systemctl restart ydotoold.service
The program should now work as expected. As a test you can run :
ydotool type 'Hello World!'