I like to have random wallpapers while working on PC, a kind of window opened to the world.
Now add to that a set of wonderful and free pictures from Unsplash, and you’ll need nothing else to stay happy and motivated!
For Windows, there are tools that do that we no big deal, like DMT.
For Ubuntu, I didn’t find such tool, so I’m tweaking something here (that’s Linux power :))
Thanks to this post, I have enough help to start. It already uploads random picture and set it as wallpaper.
#!/bin/bash wget -O /tmp/wallpaper.jpg https://source.unsplash.com/random gsettings set org.gnome.desktop.background picture-uri file:///tmp/wallpaper.jpg
Create a script with above code (I’m doing it in /bin folder):
cd /bin
sudo nano unsplash.sh
Ctrl+X, then Y, then Enter.
Make it executable, and run it:
sudo chmod +x unsplash.sh
./unsplash.sh
You’ll see after some seconds that the wallpaper changes to a new one.
If nothing happens or you lost the previous one, it is may be a problem of connection
Now let’s execute it every 5 minutes using crontab, edit it:
crontab -e
Choose an editor with its number, then add at the end the line:
*/5 * * * * /bin/unsplash.sh
Ctrl+X, then Y, then Enter.
Here is a good explanation of crontab syntax, I quote the part:
The stars represent different date parts in the following order:
- minute (from 0 to 59)
- hour (from 0 to 23)
- day of month (from 1 to 31)
- month (from 1 to 12)
- day of week (from 0 to 6) (0=Sunday)
It mean every 5 minutes, every hour, every day, and every month.
For the moment this basic script works fine 🙂
If you want to have images with specifi keyword, in the script, replace :
https://source.unsplash.com/random
with:
https://source.unsplash.com/1600x900/?nature,water
Where nature and water and keywords, and 1600×900 are the resolution of your screen.
If you have any remark or suggestion please add a comment. Thank you.
Old script before 04/10/2019 is someone still need it:
#!/bin/bash wget -O /tmp/wallpaper.jpg https://unsplash.it/2560/1440/?random gsettings set org.gnome.desktop.background picture-uri file:///tmp/wallpaper.jpg
Here are the improvements I made:
- Create the script in /usr/bin/ instead of /bin/, respecting that /bin/ directory is for resources mandatory for boot step.
- Store the wallpapers in /var/tmp/ instead of /tmp/, assuming that we want to keep these images in temporary but persistent folder.
- Check if we are using a metered connection or not, to avoid consuming data while using limited or expensive connection.
- Concatenate the wallpaper download and change steps, if wget response isn’t positive, no need to go further.
The improvements I’m still trying to add:
- Copy the new wallpaper only if it is 100% downloaded, to avoid the case of corrupted file due to an interruption e.g. power loss.
- Add a timeout to limit the waiting time for wget.
Now the v2 script procedure.
cd /usr/bin/
sudo nano unsplash_v2.sh
Copy paste the code:
#!/bin/bash if [[ $(nmcli -t -f GENERAL.METERED dev show wlanx) = 'GENERAL.METERED:no (guessed)' ]]; then wget -O /var/tmp/wallpaper.jpg https://source.unsplash.com/1600x900/?nature,water && gsettings set org.gnome.desktop.background picture-uri file:///var/tmp/wallpaper.jpg fi
There are two important parameters to change based on your machine.
- wlanx: This is the name of your internet interface.
- GENERAL.METERED:no (guessed): This status of metered property.
To find 1), use the command : ifconfig
To find 2), run the following command: nmcli -t -f GENERAL.METERED dev show wlanx
(replace wlanx with your interface)
Save the script: Ctrl+X, then Y, then Enter.
Make it executable: sudo chmod +x unsplash_v2.sh
Run it: ./unsplash_v2.sh
The cron step is the same as for the first version of the script above.
works. thanks a lot!
You’re welcome 🙂
nice
[…] (source code originally found at youness.net) […]
Nice ! Thanks…
The BEST !
Thanks, works great!
Small addition to also modify your lockscreen wallpaper use:
`gsettings set org.gnome.desktop.screensaver picture-uri file:///tmp/wallpaper.jpg`
Thanks for the addition.
Thanks!
Just a correction, the shebang is wrong:
#/bin/bash
should be:
#!/bin/bash
Thanks! Corrected.
[…] (source code originally found at youness.net) […]
it’s possible to use a key-word to set the wallpapers? For example if you set it to “Forest” the wallpapers are going to be random but only using the images of the “Forest” search result on unsplash. (some of the apps in other OS let you do this). how ever thank you for the script, is really cool!
Unfortunately the website used doesn’t allow this option.
Hi Brian,
I just found that Unsplash has now its own API to get imges, you can replace the URL to get the random image to : https://source.unsplash.com/1600×900/?forest
Set up the correct resolution for you.
(I was looking for this great option too) 🙂
thanks dude!
Hmm sometimes the wallpaper is just flickering while executing the script and finally black
there might be a problem with gsettings with my system, but i cant figure it out.
thanks anyway!
I’ve never experienced such issue on my machine.
There are several issues with this I’d like to mention.
The first: /tmp is a good destination for files that do not need to persist between reboots. It is usually mounted on a physical volume, and as such usually does persist between reboots, but it is not guaranteed to do so. In fact, on some of my systems that have more memory than common sense, I mount /tmp in tmpfs. It doesn’t persist between reboots on those systems. And by in large, this is not a problem.
The correct place to keep temporary but persistent data is in /var/tmp. So the script in this article ought to be sending the files to /var/tmp instead. This path exists specifically to provide a persistent (between reboots) tempfile destination.
The second issue: What happens if the device running the cron does not have Internet connectivity. wget will wait for a long time, and then fail. That’s fine, the file won’t get replaced unless there is something replacing it. But it’s a little inelegant. There should be a better safeguard: “wget ….. && gsettings set …” would do the trick, since wget has an exit code of 0 on success or something else on failure. So using the && will only attempt to change the gsettings setting if wget was successful. Along these lines, I would also recommend using a -T timeout for wget so that the system isn’t waiting around for very long.
The third issue is with regards to Internet connectivity again. There is no attempt to avoid an image download in cases where the device is using a metered connection. I don’t know offhand how to detect this, but I imagine it is probably possible. I’ll look into it and if I can find a solution I’ll follow-up here.
The fourth issue is regarding atomic writes. In the event of an unexpected shutdown (really in the event of total power loss) there is a risk that the output file could become corrupted. A better solution would be to request a tmpfile using “BGFILE = $(mktemp -p /var/tmp background.XXXXXX.jpg) wget …. && mv $BGFILE current-background.jpg && gsettings set …” By doing this you eliminate the race condition; the file only gets moved into position after a successful fetch, and it’s moved atomically.
The fifth issue is around run duration. The cron runs every 5 minutes. What if, for some reason, one cron is still in progress while another one kicks off. This is pretty unlikely, particularly if you’re using the -T option with wget, but it’s not totally impossible. To resove this I would recommend touch the destination file, obtain a non-blocking write lock on the target file at the beginning of the process. If the lock cannot be obtained, just gracefully exit, because failure to obtain the lock means that another instance of the cron is in progress. When the cron exits the lock will be released by the kernel.
Hi David,
Thanks a lot for such detailed feedback, I didn’t expect that someone will go down and come up with all those great points. I myself experienced some of them but since it was just for fun I “let them be resolved by time”, but this weekend I’ll do my homework to come up with a second version to improve it ! 🙂
I may get something up on Github soon. When I do I’ll follow up here.
Here’s a proof of concept for most of the ideas I mentioned above:
https://github.com/daoswald/bg-changer
The README.md includes a few TODO items I’ll get to within a few days.
I’ve never used Perl before, so I’ll continue with bash commands. I just added a v2 work in progress at the end of the post, please check it and let me know your feedback. FYI I found a way to check the metered property of the connection. Thanks!