About some scripts I made this week

An AI image. You aren't missing anything.
An AI image depicting the time that I blogged about some scripts.

Jobber: a job/task runner bot

There is a UNIX system utility called cron. It runs tasks at specified times or intervals. It is an old archaic program that will NOT run a task if the computer is off or sleeping, because UNIX computers were expected to always be on. It doesn't check to see if it has missed any tasks either. I consider it to be useless because of this. So I made my own task runner that NEVER misses a job! It was quite simple, actually.

[Update July 13: Ok, I understand to "never say never". I will explore some of the things that can go wrong at a later date. Anacron won't miss a job, but it won't run the jobs often enough for my intended use, so it is a different kind of useless. I won't be using it. Systemd might be an option. I might show how to use it, and then not use it. I have my reasons. I also have a much simpler solution to the reminder task that will be featured in an upcoming blog post. ]

jobber.py is a program that checks a csv file for available jobs by time and date. If the current time is equal to or past the job time, jobber.sh calls jobber.py which calls a script to run the job. jobber.sh then sleeps for ten minutes, wakes up, and repeats the cycle.

#id, datetime,            script,      scriptargs
101, 2025-08-08 03:30:00, reminder.py, simon@home.arpa, "Get 50% off"  , "Get some savings."

Right now, the only task script I have for it is "reminder.py", a script that sends an email reminder, but this is the main reason I wrote jobber, so I am pleased.

Jobber keeps a log of jobs referenced by a job-id. The job completion time is recorded as well as the return code (a report gets generated based on this).

To start and stop jobber, I use the desktop session. In Gnome, I use a startup script to start jobber.py (which is easy to do) and gendsession https://github.com/backloop/gendsession to detect the desktop logoff and shut down jobber.py .

What I learned?

  • csv files written by Python have Windows/DOS line endings.
  • How to daemonize a process, and then how to do it correctly.

Moon phase report ultra extreme

I used the pyEphem library https://rhodesmill.org/pyephem to compute the locations of Moon and Sun. The moon phase was computed by taking the difference of the angle between the Moon and Sun. pyEphem gives the illumination percentage directly, but I don't know how it computes this, so I used the angles for classifying the moon phase. The program uses my venv technique (described in this blog post) to install pyEphem into a Python venv. For ease-of-use, the symbolic link moonphase is used to call my Python venv wrapper moonphase.sh that then calls moonphase-ultra.py with the correct args for the user's location:

#                  location  lat     long     timezone
moonphase-ultra.py "Detroit" "42.33" "-83.04" "US/Eastern"
$ moonphase 
Location: Detroit
Date: 2025/07/11 08:57 PM
Moon Phase: Waning Gibbous
Age of the moon: 16 days
Illumination: 98%
Next new moon is on 2025/07/24 03:11 PM:
  12 days, 18 hours, 13 minutes from now.

I heard you like reports, so I made a reporting script that runs reports and reports on the reports.

Report generation is really easy. You can just write the software in a straight line from start to finish. I should have done this sooner.

$ report -h
Usage: report [options]
 Options:
  -h, --help       Show this help message.
  -e, --emoji      Use emojis.
  -w, --weather    Show weather information.
  -j, --jobs       Check status of jobber jobs.
  -p, --postfix    Check mail daemon status.
  -m, --mail       Check for unread mail.
  -l, --lunar      Show moon phase report.

The default report:

$ report -e
✅ Jobber is running.
   Jobber PIDs:
     jobber.sh 151860
✅ All completed jobs were successful.
✅ Postfix service: running
✅ Mail queue is empty.
✅ No Postfix errors or warnings in the last 2 days.
✅ 0 emails.

The moonphase report adds a warning for the full moon:

$ report -e -l
❌ What a terrible night to have a curse.
   Location: Detroit
   Date: 2025/07/10 07:39 PM
   Moon Phase: Full Moon
   Age of the moon: 15 days
   Illumination: 100%
   Next new moon is on 2025/07/24 03:11 PM:
     13 days, 19 hours, 32 minutes from now.

So, I did this and it changed my life.