1. 22

A follow up to this post about @tedu’s sct utility.

It’s color setting is fairly close to the “redshift” app’s defaults.

#!/bin/sh

# Copyright (c) 2017 Aaron Bieber <aaron@bolddaemon.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

S=4500
INC=2
SCT=$(which sct)

if [ ! -e "$SCT" ]; then
    echo "Please install sct!"
    exit 1;
fi

function setHM {
    H=$(date +"%H" | sed -e 's/^0//')
    M=$(date +"%M" | sed -e 's/^0//')
    HM=$((${H}*60 + ${M}))
}

setHM

if [ $HM -gt 720 ]; then
    for i in $(jot $((1440 - $HM)));  do
        S=$((${S}+${INC}))
    done
else
    for i in $(jot $HM); do
        S=$((${S}+${INC}))
    done
fi

while true; do
    setHM

    if [ $HM -gt 720 ]; then
        S=$((${S}-${INC}))
    else
        S=$((${S}+${INC}))
    fi

    $SCT $S

    sleep 60
done
  1.  

  2. 4

    You could simplify a bit and eliminate the two calls to jot(1) and the two for loops by doing this:

    if [ $HM -gt 720 ]; then
        S=$(( $S + $INC * (1440 - $HM) ))
    else
        S=$(( $S + $INC * $HM ))
    fi
    

    Running once a minute with an increment of 2 is a bit much since sct rounds the number to a precision of 500, so the sct call in the while loop will only do something once every 250 runs, i.e. roughly every 4 hours.

    Finally, since it wasn’t mentioned yet: jung@ polished it a bit and created an OpenBSD port of sct about a year ago.

    1. 1

      Nice, thanks for the feedback!

      1. 1

        Now sct is packaged for void linux as well, thanks to @duncaen. So it should be equally easy to get as the port.

      2. 2

        Very small nitpick: this only works if /bin/sh is bash (or something that supports $((...))). Works like a charm after telling it to run with bash.

        I missed the original sct thread, and redshift felt heavy, so this little script + sct will be of great use to me. Thanks!

        1. 4

          Piling on the nitpick wagon, error messages should go to stderr rather than stdout:

          - echo "Please install sct!"
          + echo >&2 "Please install sct!"
            exit 1;
          
          1. 2

            FWIW, dash handles this properly as well:

            % file /bin/sh
            /bin/sh: symbolic link to dash
            % sh
            $ echo $((1440 - 720))
            720
            

            OpenBSD’s ksh, same goes for zsh:

            $ echo $((1440 - 720))
            720
            

            So I guess on the majority of systems you’d run X on, this won’t be an issue ;)

            Now, my own nitpick - I’ve ran shellcheck and fixed some warnings:

            #!/bin/sh
            
            # Copyright (c) 2017 Aaron Bieber <aaron@bolddaemon.com>
            #
            # Permission to use, copy, modify, and distribute this software for any
            # purpose with or without fee is hereby granted, provided that the above
            # copyright notice and this permission notice appear in all copies.
            #
            # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
            # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
            # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
            # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
            # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
            # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
            # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
            
            S=4500
            INC=2
            SCT=$(which sct)
            
            if [ ! -e "$SCT" ]; then
                echo "Please install sct!"
                exit 1;
            fi
            
            setHM() {
                H=$(date +"%H" | sed -e 's/^0//')
                M=$(date +"%M" | sed -e 's/^0//')
                HM=$((H*60 + M))
            }
            
            setHM
            
            if [ $HM -gt 720 ]; then # t > 12:00
                for _ in $(jot $((1440 - HM)));  do
                    S=$((S+INC))
                done
            else # t <= 12:00
                for _ in $(jot $HM); do
                    S=$((S+INC))
                done
            fi
            
            while true; do
                setHM
            
                if [ $HM -gt 720 ]; then
                    S=$((S-INC))
                else
                    S=$((S+INC))
                fi
            
                $SCT $S
            
                sleep 60
            done
            

            Also note that on linux systems, the jot binary is often not available (I just discovered it today, it’s an OpenBSD utility). At least on void linux one can install it with the outils package.

            Either way, very useful - no need to run sct by hand now :)

            1. 2

              Odd, my dash at home barfed on the script. I now checked again, and it errors out on function setHM { .. }: it wants setHM () { ... } instead.

              Not quite sure why I remember $((...)) being a problem…

              1. 1

                function, even though technically a bashism, originated in ksh.

                In terms of $((...)) being a problem, you are most likely referring to ((...)) which is indeed a bashism. Alternatively, you might have come across ++ or -- in $((...)), which are not required by POSIX.

              2. 1

                for _ in $(jot $((1440 - HM))); do

                huh, I had no idea _ was a thing, neat!

                1. 1

                  $_ holds the last argument of the preivously run command. Overwriting it does no harm here and in similar places, so I occasionally make use of it (both to silence shellcheck and to signal the value won’t be used). It’s possible though some folks might object :)

                2. 1

                  Also note that on linux systems, the jot binary is often not available (I just discovered it today, it’s an OpenBSD utility).

                  You can use seq instead of jot on linux.

                3. 1

                  In similar vein, I’d suggest to replace [ with [[ because the latter is a bash/zsh/dash builtin.

                  1. 1

                    Its a myth, you can check it with type [, both are builtin, [[ is only available in larger shells, [ is POSIX. The [ should be preferred for #!/bin/sh portability.

                  2. 1

                    $((…)) is very much POSIX.