Nathan Grigg


Productive couple of days for my rather neglected Linode instance. Upgraded the distro from Ubuntu 14.04 to Debian 10. Moved DNS from Amazon to Google. Moved various static sites from S3 to Linode. Somehow it all still works.


Reading feeds in a world of newsletters

I understand the popularity of email newsletters, especially for publishers. It’s a simple way to get paid content out, easier for users than a private RSS feed. But that doesn’t mean I want to read newsletters in my email app.

Feedbin, which I am already using for my regular RSS subscriptions, bridges the gap. As part of my Feedbin account, I get a secret email address, and anything sent to that address ends up in my RSS reader. Problem solved!

But it quickly gets annoying to sign up for newsletters (often creating an account) with an email address that is neither memorable nor truly mine. Fastmail, which I am already using for my regular email, makes it easy to find specified emails sent to my regular address, forward them to my feedbin address, and put the original in the trash.

In fact, Fastmail lets me use “from a member of a given contact group” as the trigger for this automatic rule, which makes the setup for a new newsletter very simple:

  1. Subscribe to the newsletter
  2. Add the sender to my Fastmail address book
  3. Add the newly created contact to my “Feedbin” group

This is very convenient, for newsletters as well as other mail that is more of a notification than an email. Here are some of the emails that I now read as though they were feeds:


I installed homebridge on my Synology so that I could connect my thermostat with HomeKit. Surprisingly easy, minus a few rounds of trial and error on getting the configs right.


In the most recent iOS update, Files app can render html pages. (Before then, only iPadOS could do this.) So now I have an easy way to periodically generate a dashboard or report on my iMac and have it sync via iCloud to my mobile devices.


Maybe Washington Post should separate headlines more clearly; this one had me scratching my head for a while.


I literally bought new AirPods yesterday.


I highly recommend Footpath for planning a running route. Draw your route with your finger and you get mileage and elevation profile.


We have been having so much fun with Zelda at our house. I would usually consider myself a casual gamer, but I can’t put this down.


I really wanted to do a Route 1 road trip this summer, but it seems a shame to detour around Big Sur.


I accidentally called 911 while trying to change my watch band.


Tonight I went to “Into the Woods,” currently on tour in Los Angeles. I’m a fan since I saw the movie version, but it was way better on stage. Amazingly talented people, highly recommended.


This entirely serious LA Times piece could be an Onion article. “Our city depends on a Hispanic population to support our comfortable lifestyle.”


Monitor long-running commands: integrations

This is the fourth and last in a series of posts describing the system I built to monitor long-running commands.

The third post explained my mon script, which together with my twait script from the second post, lights up an LED when a command in a tmux pane or iTerm window completes.

If I want to monitor a command, I use mon twait ID, where ID is the pane or window ID. Or I can run another command only if the first command is successful, by writing twait ID && ./other_command.

Of course it would be annoying to type the window ID manually, so I have two keyboard shortcuts. One to start mon twait ID in a separate window that closes automatically when it is done. The other to open a new window with the text twait ID && followed by a space.

Tmux integration

Tmux can be scripted through the use of unix-like commands, with arguments and options. These can either be run from the command line or assigned keyboard shortcuts.

I use Ctrl-A plus uppercase E for the first.

bind E run "tmux split-window -l 5 \"mon twait #D\""

This splits to form a new window, 5 lines high, and runs mon twait. The #D parameter in a tmux run command gets translated into the pane ID.

I use Ctrl-A plus lowercase E for the second.

bind e run "tmux split-window; tmux send-keys \"twait #D &&\""

iTerm integration

You can do very similar things with iTerm using AppleScript.

To open the monitor in a temporary pane, I use this script. It is possible to control the height of the new pane, but I haven’t figured it out yet.

tell application "iTerm"
  tell current session of current window
    set session_id to id
    split horizontally with default profile ¬
        command "mon twait " & session_id
  end tell
end tell

I prefer new windows over tabs or split windows, so I use this script to open a new window prepped to run a follow-up command.

1
2
3
4
5
6
7
8
9
tell application "iTerm"
    set session_id to id of current session of current window
    set new_window to create window with default profile
    set new_session to current session of new_window
    tell new_session
        select
        write text "twait " & session_id & " && " without newline
    end tell
end tell

Monitor long-running commands: the monitoring script

This is the third in a series of posts describing the system I built to monitor long-running commands.

The second post explained my twait script, which waits for a command in a separate tmux pane or iTerm window to complete, and then exits with the same code.

The easiest way to get notified when twait finishes is to chain the commands:

twait %22; notify

But this ignores the return value, which is a useful part of the notification.

You could solve this by passing the return value as an argument:

twait %22; notify $?

The $? variable contains the return code of the last command.

I mostly use a script called mon that takes the other command as an argument:

mon twait %22

Since mon is running the command, it has access to its exit code. It can also do some prep work before running the command. The downside is that you have to keep the command fairly simple; using pipes, multiple commands, or shell aliases does not work properly.

Here is the code to my monitor script, which lights my blink LED and sends a Pushover notification.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
set -eu

function blink() {
  blink1-tool -m 0 "$@" > /dev/null
}

blink --rgb 170,170,170
echo "Monitoring $@"
"$@"
rc=$?

case $rc in
  0)
    blink --green
    title="Process succeeded"
    ;;
  1)
    blink --red
    title="Process failed"
    ;;
  *)
    blink --blue
    title="Process failed"
    ;;
esac

pushover "$title" "Exited with code $rc"

This sets the LED to a dim white at the beginning of the command, prints a message, and then runs the command. The $@ variable contains all of the arguments to the script, which should be the command to run, followed by its arguments. When we are done with the command, we capture the return code.

Depending on the value of the return code, I turn the LED green, red, or blue, and send a message to my phone and watch.

The pushover script uses curl to send a request to the pushover servers.

1
2
3
4
5
6
7
8
#!/bin/bash
set -eu
curl -s \
  --form-string "token=asdfasdfasdfasdf" \
  --form-string "user=asdfasdfasdfasdff" \
  --form-string "title=$1" \
  --form-string "message=$2" \
  "https://api.pushover.net/1/messages.json" > /dev/null

Those are not my token or userid. You have to get your own from pushover.

The final post in this series will show some tmux and AppleScript integrations to make this monitoring easier to launch.