6

EDIT Thanks to pa4080 I added one line to the script below and now it works great. I don't exactly understand how, oh well.

I would like to make a cron job to adjust my brightness at different hours of the day. After doing some googling and trial and error I wrote the following bash script that works well:

#!/bin/bash
export DISPLAY=$(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}')

H=$(date +%H)

if (( 00 <= 10#$H && 10#$H < 07 )); then
    xrandr --output HDMI-1 --brightness .3 && xrandr --output HDMI-2 --brightness .3 && xrandr --output HDMI-3 --brightness .3
elif (( 07 <= 10#$H && 10#$H < 10 )); then
    xrandr --output HDMI-1 --brightness .5 && xrandr --output HDMI-2 --brightness .5 && xrandr --output HDMI-3 --brightness .5
elif (( 10 <= 10#$H && 10#$H < 19 )); then
    xrandr --output HDMI-1 --brightness .7 && xrandr --output HDMI-2 --brightness .7 && xrandr --output HDMI-3 --brightness .7
elif (( 19 <= 10#$H && 10#$H < 22 )); then
    xrandr --output HDMI-1 --brightness .5 && xrandr --output HDMI-2 --brightness .5 && xrandr --output HDMI-3 --brightness .5
elif (( 22 <= 10#$H && 10#$H < 23 )); then
    xrandr --output HDMI-1 --brightness .3 && xrandr --output HDMI-2 --brightness .3 && xrandr --output HDMI-3 --brightness .3
else
    echo "Error"
fi

Then I used crontab -e to add the following line:

0 * * * * /home/piney/screendimmer.sh

The cronjob is triggered but the script doesn't run. What am I doing wrong?

Piney
  • 163

5 Answers5

7

Cron provides limited set of environment variables by default [1]. To get xrandr to work through a Cron job, you should export [2] the value of the current user's $DISPLAY variable [3]. To do that add the follow line to the beginning of your script (or add it within the crontab file [4]):

export DISPLAY=$(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}')

References:


I liked the idea and already implemented it in my system. Here is my version of the above script:

#!/bin/bash

# While the user is not logged in == until the $DISPLAY variable is unset or empty
unset DISPLAY
while [ -z "$DISPLAY" ] || [ "$DISPLAY" == "" ]; do
        DISPLAY=$(w "$(id -un)" | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}' 2>/dev/null)
        if [ "$DISPLAY" == "" ]; then sleep 30; else export DISPLAY="$DISPLAY"; fi
done

brightness(){
        # Get the list of the active monitors automatically
        # To set this list manually use: OUT=( VGA-1 HDMI-1 HDMI-2 HDMI-3 )
        OUT=$(xrandr --listactivemonitors | awk 'NR!=1{print " "$NF" "}')
        # Adjust the brightness level for each monitor
        for current in "${OUT[@]}"; do xrandr --output "${current// /}" --brightness "$1"; done
}

if [ -z "${1+x}" ]; then  # If the scrip is called from Cron or CLI without an argument: 'brightness'
        H=$(date +%-H)
        if   ((  0 <= "$H" && "$H" <  7 )); then brightness ".5"
        elif ((  7 <= "$H" && "$H" < 10 )); then brightness ".6"
        elif (( 10 <= "$H" && "$H" < 19 )); then brightness ".7"
        elif (( 19 <= "$H" && "$H" < 22 )); then brightness ".6"
        elif (( 22 <= "$H" && "$H" < 24 )); then brightness ".5"
        else echo "Error"
        fi
else brightness "$1"    # If the scipt is called with an additional argument: 'brightness "<value>"'
fi
  • The script is able to get the list of the active monitors automatically. I've tested it with two monitors.

  • Nice idea is to place the executable file [5] in /usr/local/bin, thus it will be available also as shell command. Let's assume it is called brightness.

  • The script is able to use an arguments, which will override the default brightness values, for example: brightness .9.

  • While /usr/local/bin is not listed in the crontab's $PATH variable [1] [4] [6], the Cron jobs should use the full path:

    @hourly /usr/local/bin/brightness
    
  • Probably the @reboot Cron jobs will not work with the current version of the script [7].

pa4080
  • 29,831
  • 1
    Great, @pa4080! You will solve an issue I have about DISPLAY a long time... – Redbob Sep 22 '17 at 10:23
  • For @reboot support see this Q&A: https://askubuntu.com/questions/1102389/xrandr-not-working-on-crontab/1102436?noredirect=1#comment1816960_1102436 your comments would be welcome. – WinEunuuchs2Unix Dec 17 '18 at 14:42
5

You must type the path where xrandr is installed. Type command -v xrandr (or which xrandr) to know where it is installed. I suppose it's /usr/bin/xrandr, if it's installed by default.

So, edit yout crontab so:

#!/bin/bash

H=$(date +%k)

if   (( $H >  0 && $H <=  7 )); then
    /usr/bin/xrandr --output HDMI-1 --brightness .3 && /usr/bin/xrandr --output HDMI-2 --brightness .3 && /usr/bin/xrandr --output HDMI-3 --brightness .3
elif (( $H >  7 && $H <= 10 )); then
    /usr/bin/xrandr --output HDMI-1 --brightness .5 && /usr/bin/xrandr --output HDMI-2 --brightness .5 && /usr/bin/xrandr --output HDMI-3 --brightness .5
elif (( $H > 10 && $H <= 19 )); then
    /usr/bin/xrandr --output HDMI-1 --brightness .7 && /usr/bin/xrandr --output HDMI-2 --brightness .7 && /usr/bin/xrandr --output HDMI-3 --brightness .7
elif (( $H > 19 && $H <= 22 )); then
    /usr/bin/xrandr --output HDMI-1 --brightness .5 && /usr/bin/xrandr --output HDMI-2 --brightness .5 && /usr/bin/xrandr --output HDMI-3 --brightness .5
elif (( $H > 22 && $H <= 23 )); then
    /usr/bin/xrandr --output HDMI-1 --brightness .3 && /usr/bin/xrandr --output HDMI-2 --brightness .3 && /usr/bin/xrandr --output HDMI-3 --brightness .3
else
    echo "Error"
fi
Redbob
  • 1,596
  • This is not the issue here, because xrandr is actually located in /usr/bin/, but the default value of crontab's $PATH variable is /usr/bin:/bin. – pa4080 Sep 22 '17 at 08:36
  • thanks for the suggestion but it doesn't work :( – Piney Sep 26 '17 at 07:28
  • Pinney, did you follow pa4080 instructions? I think they will help you. Otherwise, I installed Redshift as marcelm suggested, it works like a charm. – Redbob Sep 26 '17 at 13:53
5

Instead of writing cron jobs to manually change your display's brightness, you might want to have a look at redshift, a program that can do exactly this. It can be set up to track daylight at your location, and change both your display's brightness and color temperature to better match natural light.

Image illustrating the effect of redshift

Its main selling point is changing the color temperature (i.e., shifting the color more towards the red, which is where the name comes from), but it can also adjust brightness. You could configure it to do just brightness, if that's what you want.

The main advantage over the manual solution is that redshift changes color/brightness gradually, matched to the current daily cycle of your location, rather than in steps as with your cron approach. You can also switch the effect on/off rather easily; sending the process SIGUSR1 will toggle the effect. I made a keybinding that does killall -USR1 redshift to make this easily accessible.

There is another program of similar functionality called f.lux, which also supports Windows and MacOS and seems quite popular. I have no experience with it though; in particular I'm not entirely sure if it can change brightness in addition to color temperature.

marcelm
  • 702
  • 6
  • 9
  • This solution is valid @marcelm, besides Piney didn't informed ubuntu flavor and release. It's good to check if it will work on it. Does redshift work with scheduled times to change settings? – Redbob Sep 22 '17 at 12:18
  • @Redbob As far as I know, redshift can not change settings on "scheduled times", but only track sunlight. It does this by calculating the position of the sun based on your location and time. So my answer is more of an alternative; an attempt at answering the OPs underlying desire rather than his exact question. – marcelm Sep 22 '17 at 13:25
  • Great, @marcelm. Catch my vote... I installed in my computer (lubuntu), but it's seeking for 'geoclue2' and won't go ahead. My network is proxied, that's why I can run it. – Redbob Sep 22 '17 at 13:43
  • I don't want a different colour temperature, otherwise I'd use one of the many programs that already do that. – Piney Sep 26 '17 at 07:28
  • @Piney I explicitly addressed this in my answer: "You could configure it to do just brightness, if that's what you want." – marcelm Oct 01 '18 at 19:53
0

echo $(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}') gives no output in Ubuntu 18.04. So I just did echo $DISPLAY inside the script and the output showed :0 then I added export DISPLAY=:0 and my cron job worked! My final script looks like this:

#!/bin/bash
# export DISPLAY=$(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}')
# echo $DISPLAY
export DISPLAY=:0
xrandr --output $1 --brightness $2
0

Another option would be to use xbacklight if you use xrand like this: xrandr --output HDMI-1 --brightness .3 && xrandr --output HDMI-2 --brightness .3 && xrandr --output HDMI-3 --brightness .3 this command will fail if you have VGA output.

You can install it with sudo apt install xbacklight. I use xbacklight with collaboration with redshift together they are the best.

  • Hi, Urosjarc, how we can use these features? Please elaborate your answer and give an example of usage. – pa4080 Sep 29 '17 at 08:35