Alerting on Process Completion


Most of my technical endeavours have something to do with enabling me to work as little as possible for as much reward as possible. And yet, paradoxically, in a pursuit of doing less I often end up doing more. I have this idea that in the long term this will eventually lead me to doing much less. I’m not sure if that’s true, but it’s a nice thought and keeps me going. Plus, I learn a lot of fun things along the way.

Whenever I have a long-running process on my home-lab I start it in a screen session. I check back on it occasionally to see if it has completed. The same could be true of something I’m running on my local machine, though, in that case, it is in a live terminal session. The latter is usually during the course of my day-job and is somewhat of an easier problem to solve since I am at my machine for the duration of the process.

For my local machine (which is a MacBook), I use the say command extensively. It’s trivial to add a say "Done" at the end of a command chain to aurally inform me of a task’s completion. But that wasn’t quite spicy enough for me, so I came up with something more interesting.

➜  ~ which sdd
sdd () {
	if [ $# -eq 0 ]
	osascript -e "display notification \"$text\" with title \"$title\"" && afplay ~/Documents/star-wars-b1-battle-droid_kampfdroide-roger-roger-sound.mp3

Behold the sdd function I add to the end of every script and command chain. I can invoke it with a title and an optional message, or invoke it with nothing and let it default to “Done” and “Done”. When invoked, I will be shown a notification on my screen along with an audible “Roger! Roger!”


I have no idea if this is required. I find copyright laws almost maliciously confusing. Anyway, just to cover my backside:

I do not own any rights to the “Roger, Roger” voice line, which is associated with the Star Wars franchise created by George Lucas and owned by Lucasfilm Ltd. and The Walt Disney Company. This phrase is used here under the principles of fair use for educational or informational purposes only.

This is all fine and dandy for my local machine, but what about my home-lab? I don’t want to keep a live SSH session running all the time, nor do I want to have to check back on it at odd intervals. Nor am I at a terminal all the time!

The solution to that comes from my Home Assistant setup (look out for another post that talks about my Home Assistant and dryer smartification journey).

I have created an Automation that listens to a webhook and sends a notification to my phone whenever that webhook fires.

alias: Notify Sharpie
description: ""
  - platform: webhook
      - POST
    local_only: false
    webhook_id: "<webhook-id>"
condition: []
  - service: notify.mobile_app_sharpie
      title: Notification
      message: "{{ trigger.json.message }}"
mode: single

Sharpie is the name of my phone.

Now I can curl from any device anywhere and receive a notification on my phone!

curl -i -H "Content-Type: application/json" -d "{\"message\": \"Sup?\"}" https://<home-assistant-server>/api/webhook/<wehook-id>


I can plop this down at the end of any command chain or script and be notified when it completes.

But I figured out all this after the fact. During the fact (is that even a phrase?), I had already started a long-running process that I wanted to monitor and be informed of when it terminated. So there was no way for me to append a notification curl at the end of the chain without stopping the process.

Enter the ps command with the -p flag. This can be passed a process ID and gives you information about the process.

➜  ~ echo $$
➜  ~ ps -p 266386
    PID TTY          TIME CMD
 266386 pts/1    00:00:00 zsh
➜  ~ echo $?

$$ is the PID of the current shell process.

Note that the exit code returned by the ps -p command is 0. If we were to try a PID that does not exist, we will get a 1.

➜  ~ ps -p 42069
    PID TTY          TIME CMD
➜  ~ echo $?

Thus, without knowing the exact details or output of using ps -p on our target process, we can check the exit code and find out if the process is running. This leads us to this helper function.

# Check if the process with PID exists
process_exists() {
    ps -p $1 > /dev/null 2>&1

Checking if our target process is still running, now becomes a matter of a sleepy loop (to avoid spamming the command).

# Loop until the process no longer exists
while process_exists $PID; do
    sleep 1

echo "Process $PID has stopped."

# Send the notification
send_message $MESSAGE

The send_message function can take advantage of our webhook and notify us when the process completes!

send_message() {
  curl -i -H "Content-Type: application/json" -d "{\"message\": \"$1\"}" https://<home-assistant-server>/api/webhook/<wehook-id>

And with that we have a script that can monitor a process and let us know when it completes.

Wrapping it Up

I hope you enjoyed this brief exploration of figuring out how to monitor a live process. If you were to try something like this yourself, you could, no doubt, switch out the notification part with any number of other services. Perhaps send yourself an SMS or blink the lights in your house on and off 21 times.

More posts like this

Setting up DSMR Meter Readings via a Raspberry Pi

2024-05-23 | #dsmr #electricity #home-assistant #raspberry-pi

The internet is probably full of tutorials on how to do this right, but I had to struggle a bit to figure it out for myself. My Pi randomly crashed, the other day, and I’m having to do some of the setup again and having done this for the first time months ago (and having now mostly forgotten what I did), I decided I should blog about it as I retread my steps and recreate my setup.

Continue reading 

Is it Dry Yet?

2024-04-08 | #home-assistant #home-automation #smart-plugs

Clarification: This is literally about my laundry. I am not being metaphorical. I am not talking about my feelings or my secrets. I am talking about my clothes. Intro Our washing machine is a Samsung something-something that sends me a notification on the SmartThings app when it completes a wash cycle. This is useful since we almost always need to follow up a washing cycle with a drying one and maybe even another load of laundry.

Continue reading 