How to Monitor Ip Address Changes




Problem Situation

For work I have both a desktop (Mac Mini) and a laptop (MacBook Pro). As one would expect I use the laptop when I need to be away from my desk and the desktop computer. A considerable amount of my work happens in the terminal. By using tmux I’m able to create a session on the desktop and then remotely access it from my laptop.

This work fantastically, until the desktop gets a new IP address and I can’t remote in. If I’m at home I can walk to the other computer, and check its IP address. Annoying but no big deal. When I’m not at home, I’m stuck.

Solution

I created a bash script that checks the current IP address against a saved one. If they match nothing happens. If they are different the script creates a draft email that has the new IP address in it. And it posts a notification that the IP address has changed.

I used a draft email since I can access my mailbox from either computer; no need to send it, just open the draft and copy the new IP address.

The script is managed through a Launch Agent. It runs every five minutes. Worst case scenario is I’d have to wait 5 minutes to get the updated IP address. I think the only time I lose the current IP address is when my Aruba RAP (remote access point) loses power and reboots, so I’m not expecting to get IP address changes email drafts too often.

The script

Here’s the bash script. It needs to be on the PATH and executable for this to work.

 1#!/usr/bin/env bash
 2# vim: ft=bash
 3
 4# File to store previous IP
 5IP_FILE="$HOME/.current_ip"
 6
 7# Get current local IP (adjust interface if needed)
 8CURRENT_IP=$(ipconfig getifaddr en0)
 9
10# Fallback if en0 doesn’t work (e.g., on Ethernet it might be en1 or enX)
11if [ -z "$CURRENT_IP" ]; then
12  CURRENT_IP=$(ipconfig getifaddr en1)
13fi
14
15# Read stored IP
16if [ -f "$IP_FILE" ]; then
17  STORED_IP=$(cat "$IP_FILE")
18else
19  STORED_IP=""
20fi
21
22# Compare and notify
23if [ "$CURRENT_IP" != "$STORED_IP" ]; then
24  echo "$CURRENT_IP" > "$IP_FILE"
25
26  # Create and save a draft email with the IP address
27  osascript <<EOF
28tell application "Mail"
29    set newMessage to make new outgoing message with properties {subject:"Desktop IP Changed", content:"The new IP address is $CURRENT_IP", visible:true}
30    tell newMessage
31        make new to recipient at end of to recipients with properties {address:"mhn@ksu.edu"}
32    end tell
33end tell
34EOF
35
36  osascript -e "display notification \"IP changed to $CURRENT_IP\" with title \"IP Monitor\""
37fi

Launch Agent Plist

Instead of using a cron job to manage the running of the script, the MacOS preferred way is to use a Launch Agent.

The Launch Agent requires a plist file to define it.

 1<?xml version="1.0" encoding="UTF-8"?>
 2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertiesList-1.0.dtd">
 3<plist version="1.0">
 4<dict>
 5  <key>Label</key>
 6  <string>com.user.ipmonitor</string>
 7
 8  <key>ProgramArguments</key>
 9  <array>
10    <string>/Users/USERID/bin/bash/ip_monitor</string>
11  </array>
12
13  <key>StartInterval</key>
14  <integer>300</integer>
15
16  <key>RunAtLoad</key>
17  <true/>
18
19  <key>StandardOutPath</key>
20  <string>/tmp/ipmonitor.log</string>
21
22  <key>StandardErrorPath</key>
23  <string>/tmp/ipmonitor.err</string>
24</dict>
25</plist>

You’ll need to substitute your account ID for USERID on line 10.

The plist defines the script location, sets the interval for how often to execute it (5 minutes (300 seconds)), and defines locations for logging and error messages.

Managing the Launch Agent

The plist needs to be copied to the user’s Library/LaunchAgent directory. I had to create this directory on my computer.

cp com.user.ipmonitor.plist ~/Library/LaunchAgents/com.user.ipmonitor.plist

To launch the agent:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.user.ipmonitor.plist

The start/enable the service:

launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.user.ipmonitor.plist

To check if the service is running:

launchctl list | grep ipmonitor

To kick the service, if it is already loaded:

launchctl kickstart gui/$(id -u)/com.user.ipmonitor

Logs can be viewed:

tail -f /tmp/ipmonitor.log /tmp/ipmonitor.err

Troubleshooting

Make sure the plist file path is correct. Verify with:

ls -la ~/Library/LaunchAgents/com.user.ipmonitor.plist

Verify you updated the user name in the plist.

Check plist syntax

plutil -lint ~/Library/LaunchAgents/com.user.ipmonitor.plist

Ensure the script is executable:

chmod +x ip_monitor

If you still get errors after bootstrap, run:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.user.ipmonitor.plist 2>&1

This will show the actual error message, which will help troubleshoot the issue.

Repository

I have a Git repository with the script, plist, and a detailed README: ip_monitor