LGFae / swww

A Solution to your Wayland Wallpaper Woes
GNU General Public License v3.0
2.01k stars 62 forks source link

cronjob can't find daemon #164

Open nxwbxdy opened 10 months ago

nxwbxdy commented 10 months ago

I changed the example script that works when i execute it as the logged in user. It tells me the it can't find the socket file when I run it with cron. I also tried to set the XDG_RUNTIME_DIR=/run/user/$(id -u) but it didn't work. I am not an expert so I need a little help with this.

❯ cat ~/.scripts/swww/change-background
#!/bin/bash

if [[ $# -lt 1 ]] || [[ ! -d $1 ]]; then
    echo "$0 <dir>"
    exit 1
fi

swww img "$(find $1 -type f | shuf -n 1)" --transition-fps 60 --transition-step 90 --transition-type wipe --transition-angle 100 2>> ~/not_working.txt >> ~/not_working.txt
~
❯ sudo crontab -u luky -l
[sudo] password for luky:
* * * * * bash ~/.scripts/swww/change-background ~/Pictures/background
~
❯ cat ~/not_working.txt

Error: "Socket file not found. Are you sure swww-daemon is running?"
Error: "Socket file not found. Are you sure swww-daemon is running?"
Error: "Socket file not found. Are you sure swww-daemon is running?"
Error: "Socket file not found. Are you sure swww-daemon is running?"
Error: "Socket file not found. Are you sure swww-daemon is running?"
J-C-Zeppeli-Gyro commented 10 months ago

I managed to work around the problem, because I had that error too. In the hyprland.conf I set the script to change the bg to exec and every other I don't need to be executed every time to exec-once. So I created another script that edits the hyprland.conf file, just adds 1row at the end then deletes that row.

home/$USER/.config/hypr/hyprland.conf { ... exec = /path/to/bg/changer/script ... }

/path/to/hyprland.conf/editor { ... echo "Anything" >> home/$USER/.config/hypr/hyprland.conf sed -i '$d' home/$USER/.config/hypr/hyprland.conf ... }

crontab { ... * * * * * /path/to/hyprland.conf/editor ... }

nxwbxdy commented 9 months ago

I made my own daemon for now the loop file basically calls the background changer and the loop file is called from the hyprland config with the delay. I hope this will be fixed one day with the daemon. https://github.com/moessler-bit/.scripts/tree/main/swww

eccentricfae commented 9 months ago

So for anyone wondering this is a problem not just with running "swww img ..." with cron but running it with elevated privileges (as root, w/ sudo etc). Hopefully this info will help people looking into the problem

nxwbxdy commented 9 months ago

I am currently learning rust and could try to find the problem once i am more familiar with the language

eccentricfae commented 9 months ago

So I found the issue (I think?) In file: utils/src/ipc.rs, line 331 let runtime_dir = if let Ok(dir) = std::env::var("XDG_RUNTIME_DIR") {

The std::env::var("XDG_RUNTIME_DIR") returns an error (i.e. env var not found) when program is run with elevated privileges. What's funny is that when I run: echo $XDG_RUNTIME_DIR , sudo echo $XDG_RUNTIME_DIR and su then echo $XDG_RUNTIME_DIR I get the same output, so in my mind it means that XDG_RUNTIME_DIR is set and visiable for both user account and root account.

But when the rust program tries to read that variable (using std::env::var("XDG_RUNTIME_DIR")):

I verified this issue to be persistent across different Rust codebases, so the issue is with the std::env::var() instruction itself rather then swww codebase.

I will try to figure out if this can be fixed in some way but I'm quite new to Rust (like I started learning Rust few days ago lmao) so I encourage someone experienced with Rust to try and fix it

nxwbxdy commented 9 months ago

So that would mean that any rust program that uses the std::env crate doesn't work with sudo privileges

nxwbxdy commented 9 months ago

I think the author isn't using a normal daemon like systemd i think. I have to look into this i don't know too much yet

eccentricfae commented 9 months ago

So update: it seems that when you run the program with sudo calling user's enviroment variables do not transfer (see the output of printenv and sudo printenv), which is kinda whack because when you enter root account (using su) and use the printenv command all the variables are still set, therefore I can only assume that cron runs the swww img command not "as root (as in using su to log in to a root account)" but "with sudo". When you run swww img:

Bad news is that there's probably nothing that can be done to rectify it in this codebase, because this is not an issue with rust, but this is an issue with linux enviroment variables and / or cron daemon. Good news: you can easily create such script that will rectify this issue at linux-enviroment level:

#!/bin/bash

export XDG_RUNTIME_DIR=/run/usr/1000 # Assuming this is also your $XDG_RUNTIME_DIR value
swww img /path/to/img

works on my machine when added as a script that is supposed to be run as a cron job and when run with sudo

StitiFatah commented 5 months ago

So update: it seems that when you run the program with sudo calling user's enviroment variables do not transfer (see the output of printenv and sudo printenv), which is kinda whack because when you enter root account (using su) and use the printenv command all the variables are still set, therefore I can only assume that cron runs the swww img command not "as root (as in using su to log in to a root account)" but "with sudo". When you run swww img:

  • as user or with su then swww img works
  • with sudo (as either su or user) - it doesn't work

Bad news is that there's probably nothing that can be done to rectify it in this codebase, because this is not an issue with rust, but this is an issue with linux enviroment variables and / or cron daemon. Good news: you can easily create such script that will rectify this issue at linux-enviroment level:

#!/bin/bash

export XDG_RUNTIME_DIR=/run/usr/1000 # Assuming this is also your $XDG_RUNTIME_DIR value
swww img /path/to/img

works on my machine when added as a script that is supposed to be run as a cron job and when run with sudo

Thanks it works on my machine too, had written a python script to pick random images from specified folders and it was driving me crazy

nergdron commented 2 months ago

as an update, I just ran into this, and had to add export WAYLAND_DISPLAY="wayland-1" to my script to get things to work, since perhaps per-wayland sockets was implemented after folks found the workaround initially. it might be nice to just have these variables default to those values in the swww codebase if the env vars aren't defined? wouldn't fix every use case, but would catch the most common one at least.

DaniD3v commented 1 month ago

Note that this behavior isn't even according to XDG spec.

image (from the arch wiki)

I'd suggest adding a fallback to /run/user/UID. For getting the UID I'm not sure whether there's something in std but I know this library works. Would add quite a bit of unnecessary bloat tho.

DaniD3v commented 1 month ago

I just had a look at the current code for this

let runtime_dir = if let Ok(dir) = std::env::var("XDG_RUNTIME_DIR") {
        dir
    } else {
        "/tmp/swww".to_string()
    };

This is a terrible default. $XDG_RUNTIME_DIR is /run/user/UID in 99% of cases. We should also use that default. + /tmp is insecure. Wouldn't want other users randomly setting my wallpaper.

LGFae commented 1 month ago

~@DaniD3v, well, sure. But that's not really what's causing this problem. That's just the daemon's socket location. The wayland socket location is what we need to find. Right now if we can't get it from XDG_RUNTIME_DIR we just give up. The code was simply copy-pasted from wayland.rs, so if it's a problem here, it's also a problem over there~.

EDIT: actually, no. This is really a problem in the daemon, since for wayland you can just set WAYLAND_DIPLAY to an absolute path and you don't have to use XDG_RUNTIME_DIR.

I'd suggest adding a fallback to /run/user/UID. For getting the UID I'm not sure whether there's something in std but I know this library works. Would add quite a bit of unnecessary bloat tho.

We can just use rustix's getuid. We already depend on rustix anyway.

LGFae commented 1 month ago

@nergdron

I just ran into this, and had to add export WAYLAND_DISPLAY="wayland-1" to my script to get things to work, since perhaps per-wayland sockets was implemented after folks found the workaround initially. it might be nice to just have these variables default to those values in the swww codebase if the env vars aren't defined? wouldn't fix every use case, but would catch the most common one at least.

327 implements this. But note that we default to wayland-0, not wayland-1. This is consistent with libwayland's behavior. Which means that, if you need to export WAYLAND_DISPLAY=wayland-1, ironically, this still won't fix your particular use case.