Receive Raspberry Pi’s ip address on boot

I do a lot of Raspberry Pi projects – often creating them in one place and using them in another. While it is easy enough to use SSH, VNC or HTML to access a device, if it’s being moved from one network to another, it can be challenging to know its ip address. Sure, you may be able to log into a local router and look it up, but I thought it would be easier if I just had the RPi email me with its current ip address.

Thankfully, Cody Giles created a tutorial on outlining how to do this. His Python script runs on the RPi on startup, finds its ip address(es) and then emails this information to a predetermined address. I’ve replicated his project (and code) below to ensure I’ll have access to it in the future.

In order to allow a Python script to send email through a Gmail account, you may need to enable an “App Password” for your sending account.

Step #1: Create the Python Script

Copy the following and paste it into a text editor. You must change the ‘to’ address, as well as the ‘gmail_user’ and ‘gmail_password’ for the sending account in the lines below the pound sign lines about 25 lines from the top. Save this file as a python script in the home directory named

__author__ = 'Cody Giles'
__license__ = "Creative Commons Attribution-ShareAlike 3.0 Unported License"
__version__ = "1.0"
__maintainer__ = "Cody Giles"
__status__ = "Production"

import subprocess
import smtplib
from email.mime.text import MIMEText
import datetime

def connect_type(word_list):
    """ This function takes a list of words, then, depeding which key word, returns the corresponding
    internet connection type as a string. ie) 'ethernet'.
    if 'wlan0' in word_list or 'wlan1' in word_list:
        con_type = 'wifi'
    elif 'eth0' in word_list:
        con_type = 'ethernet'
        con_type = 'current'

    return con_type

## Change the 'to' address,'gmail_user', and 'gmail_password' below.  ##
to = '' # Email to send to.
gmail_user = '' # Email to send from. (MUST BE GMAIL)
gmail_password = 'gmailpassword' # Gmail password.
smtpserver = smtplib.SMTP('', 587) # Server to use.

smtpserver.ehlo()  # Says 'hello' to the server
smtpserver.starttls()  # Start TLS encryption
smtpserver.login(gmail_user, gmail_password)  # Log in to server
today =  # Get current time/date

arg='ip route list'  # Linux command to retrieve ip addresses.
# Runs 'arg' in a 'hidden terminal'.
data = p.communicate()  # Get data from 'p terminal'.

# Split IP text block into three, and divide the two containing IPs into words.
ip_lines = data[0].splitlines()
split_line_a = ip_lines[1].split()
split_line_b = ip_lines[2].split()

# con_type variables for the message text. ex) 'ethernet', 'wifi', etc.
ip_type_a = connect_type(split_line_a)
ip_type_b = connect_type(split_line_b)

"""Because the text 'src' is always followed by an ip address,
we can use the 'index' function to find 'src' and add one to
get the index position of our ip.
ipaddr_a = split_line_a[split_line_a.index('src')+1]
ipaddr_b = split_line_b[split_line_b.index('src')+1]

# Creates a sentence for each ip address.
my_ip_a = 'Your %s ip is %s' % (ip_type_a, ipaddr_a)
my_ip_b = 'Your %s ip is %s' % (ip_type_b, ipaddr_b)

# Creates the text, subject, 'from', and 'to' of the message.
msg = MIMEText(my_ip_a + "\n" + my_ip_b)
msg['Subject'] = 'IPs For RaspberryPi on %s' % today.strftime('%b %d %Y')
msg['From'] = gmail_user
msg['To'] = to
# Sends the message
smtpserver.sendmail(gmail_user, [to], msg.as_string())
# Closes the smtp server.

Step #2: Make the script executable.

Using Terminal, navigate to the home directory and make the script executable.

cd ~
sudo chmod +x

Setp #3: Run the Script on Startup.

We’ll add a line to boot.rc to run the script whenever the RPi boots.

sudo nano /boot/boot.rc

Add the following lines to boot.rc

python /home/pi/Code/

Now, reboot the Pi and in about a minute, you should receive an email with your device’s IP address.

Forcing DNS on macOS in Recovery Mode

When resetting a 2020 MacBook Air, we ran into an issue where the device just wouldn’t connect to Apple’s servers. It felt like a DNS issue, but I couldn’t find a way to see or set DNS values. After some searching, I came across this Stack Overflow post with the solution. As that site was sold to a tech investment firm in June, 2021 (promising not to change a thing), I thought it best to preserve it here.

Here it is:

Usually DNS-server setup in the shell is done with sudo networksetup ... – a tool not available in the Base OS X System of the Recovery Mode.

You should still be able to change the DNS server with scutil in

  1. Open in the menubar > Utilities
  2. Enter scutil --dns to get your current DNS config
  3. Enter scutil to reach interactive mode
  4. Enter list to get a list of all keys in the data store
  5. If you have several interfaces (you’ve found several State:/Network/Service/SERVICE_ID/IPv4 entries) determine the one connected to the Internet (based on e.g. your router and its internal network IP settings) – example:get State:/Network/Service/EB40E2FC-8248-48F2-8567-257D940A31EB/IPv4 Example output:<dictionary> { Addresses : <array> { 0 : } ConfigMethod : Manual SubnetMasks : <array> { 0 : } } If your router has the IP-address this should be the proper interface. If your router has e.g. the IP address the interface found above would be the wrong one and you have to search for an interface with an IP in the range
  6. Enter get State:/Network/Service/EB40E2FC-8248-48F2-8567-257D940A31EB/DNS use the service ID of the interface connected to the Internet you have found previously (here EB40E2FC-8248-48F2-8567-257D940A31EB)Entering should show something like:<dictionary> { SearchDomains : <array> { 0 : some.domain } ServerAddresses : <array> { 0 : } } Depending on the DHCP setup of your router the SearchDomains entry and array may be missing.
  7. Enter d.add ServerAddresses * – add one or more DNS-server (here Google’s and quad9’s
  8. Enter set State:/Network/Service/EB40E2FC-8248-48F2-8567-257D940A31EB/DNS
  9. Enter to check the modified dict entry. It should show something like:<dictionary> { SearchDomains : <array> { 0 : some.domain } ServerAddresses : <array> { 0 : 1 : } }
  10. Enter quit to leave the interactive mode of scutil and return to the shell.
  11. Enter scutil --dns or dig to verify your new DNS config.

Remove Jamf framework

To remove JAMF’s Self Service App and all jamf components, enter the following in a Terminal window:

sudo /usr/local/bin/jamf removeFramework

Keep in mind that this will also remove things like any WiFi passwords that were installed using Jamf policies.


An old version of our MDM setup disabled student access to the Terminal app. Getting it back takes some doing:

  1. Create a new Admin user account.
  2. Log into the new Admin account.
  3. In Applications > Utilities, copy the Terminal app and paste a copy on the Desktop.
  4. Rename the Desktop Terminal app to T2.
  5. Run the T2 app.
  6. paste “sudo /usr/local/bin/jamf removeFramework” in the T2 app and press return.
    (This should remove the JamfFramework, MDM settings and Self Service app.)
  7. If successful, log out and log back into the student’s account and delete the just-created admin account.

Use INDEX with MATCH instead of VLOOKUP in Spreadsheets

VLOOKUP returns janky values if the value you’re looking up doesn’t exist in the lookup column. Combine INDEX and MATCH for more reliable results.

For the long explanation, head over to Ablebits. If you’re Paul and just looking for a reminder of the format, here it is:
=INDEX (column to return a value from, MATCH (lookup valuecolumn to lookup against, 0))

NWEA MAP Import and Export from PowerSchool

This post was shamelessly stolen from PSUG-Asia and is posted here only in case the referenced post disappears. [note to Paul: search your Google Drive for “NWEA MAP Rosters Directions” for a helpful spreadsheet]

This content is from Douglas Sirkka, Educational Technology Coordinator and PowerSchool Administrator from St. Mary’s International School.

You can download the PowerSchool Export Template File Here: MAPExportMap

Or Copy the code below and make your own:


School Name ^(decode;^([schools]name);<<your school names here>>
Instructor Last Name [teachers]last_name
Instructor Middle Initial
Student First Name [students]first_name
Student Gender [students]gender
Previous Instructor ID
Period (Delete)
Expression Instructor ID [teachers]teachernumber
Instructor First Name [teachers]first_name
User Name [teachers]Email_addr
Email Address [teachers]Email_addr
Class Name [courses]course_name
Student ID [students]student_number
Student Date Of Birth [students]DOB
Student Grade [students]grade_level
Student Ethnic
Group Name
Student Last Name [students]last_name
Previous Student ID
Student Middle Initial
*Where it says ‘Bus_Stop’ that’s where I needed a blank in the file. With the TSV file above you can sort by SEQ field.

MAP Testing CRF Import In PowerSchool

  1. select the students who you need to create/update on NWEA.
    1. This will usually be the entire ES, the entire MS, or grades 9 and 10.
  2. In Group Functions, select Export Using a Template Type of Export: Student Schedules
  3. Export template: MapsCourseInforExport
    1. Select Only schedules for the selected… and Submit.
  4. Save the resulting export file and then open.
  5. Filter and select courses you want to associate with student profiles.
  6. Delete Period/Expression column at the end of the file. (this is for sorting/filtering purposes)
  7. Save as CSV (required)
  8. Login to NWEA Select Import Profiles
  9. Select Start New Import Select Combined
  10. Select the appropriate term.
  11. Add the Roster File.
  12. Click Next Check the data (Check student DOB this sometimes gets changed to a number) Reconcile Errors (Beyond scope of theses instructions but pretty straight forward)
  13. I think there is an error in the Export Template the needs a capital S in Not Specified… RP (Grade_Level 0) needs to be reconciled with K.
  14. Post the valid records.

Hope this makes your job a little easier.

Get your Global Entry Approval (and TSA Pre✓ authorization) Fast

Global Entry LogoA few years ago I signed up for the US Custom and Border Patrol (CBP) Global Entry Program available to Americans and others. Getting approved and acquiring a “Known Traveler Number” (KTN) allows me to skip the lines at passport control in the US, using Global Entry kiosks instead. Adding my KTN number to my airline accounts also results in the “TSA Pre” stamp automagically appearing on my boarding passes. This lets me take the faster, shorter lanes at TSA checkpoints, leaving my laptop in its case, shoes on my feet and belt on my jeans.

I arranged an appointment at O’Hare airport for about 6 weeks in the future, the earliest available appointment at the time. I burned frequent flyer miles to fly down from my local airport just for the appointment. Unfortunately, when I got to the CBP office at O’Hare, I realized I had flown down one day too early. The CBP agent at the counter had me stick around and about an hour later they fit me in between appointments. I had a short interview, they took my picture and sent me on my way. My card and KTN arrived a few weeks later in the mail.

I was reminded of this experience today when I ran across a Lifehacker article suggesting that you might try just walking in when you have an extended layover in an airport with a CBP Enrollment Center. You’ll want to make sure you’ve gone through the steps outlined in the “How to Apply” page first. But then try walking in and getting in without an appointment.

Cheap Passport Photos

Sooner or later, you’re going to need passport photos. Get them now and have them when you need them. I do this by filling an 8×10 print with passport photos and sending it to the local Walgreens photo department. This gives me 20 2×2 passport photos for $3.99 rather than 2 passport photos for $13.99 using Walgreens passport photo service. If you need information for visa photo requirements for a specific country, check

The following instructions are for US passport photos (2″ x 2″) but can be adapted for other photo sizes. First, get a headshot photo that satisfies the necessary requirements. Then get the photo into PhotoShop or your favorite photo editing program and crop it to a square to look something like this:

Dwight D Eisenhower Portrait
Dwight D Eisenhower

Next, resize the image to 2 inches square and set the canvas size to 8 inches by 10 inches. Duplicate the 2×2″headshot three times and arrange the image four layers across the top of the canvas. You should have one row complete, looking something like this:

Then merge those four image layers into one and duplicate it four more times, arranging them to fill the 8×10:

Now just flatten the image, save it as a jpg file and upload it to your Walgreens Photo account. Print it as an 8×10 for $3.99 and pick it up in an hour or just have it mailed to you for $0.99 more.

Pro tip: Check the Walgreens Photo Promo page, look for the current month’s special discount code. There’s often a 40% off or free 8×10 code you can enter at checkout for an even better deal.

Google Fi – Cellular and Data for the World Traveler

[Updated: May 20,2019]
Google Fi is an international phone and data service that works almost everywhere in the world (Non-Fi countries listed at the end of this post). Previously, only Nexus, Pixel and Moto X4 phones worked with Project Fi. Now, most phones (Android and iOS) can activate and use the service.

Google Fi service costs $20/month and $10 per GB of data (after the first 6GB data – the next 9GB are free). International calls cost an additional $0.20/minute, but I just use Skype, Messenger, WhatsApp or Hangouts and call for free using data. Add another line for an additional $15/month (in this case the free data doesn’t kick in until 10GB). You can also add a data-only SIM card for a tablet or compatible phone for free; just pay $10 for each GB of data it uses.

Google Fi works in most countries and there’s no need to switch settings or cards when traveling. Land in another country, turn off airplane mode and you’re online within a few minutes. Anyone calling your US number reaches you regardless of what country you’re in.

Fi also allows you to suspend service for up to three months at a time. Some people get the service just for travelling. They use a local cellular contract, suspending the Fi service when they’re at home and re-enabling it  when they travel. In this case, many couples also use just one line and get an additional data-only SIM card for the other spouse.

There are a few downsides. First, using Project Fi means I have a US number and not a local Korean number. This isn’t a big problem for me as virtually all of my communication is via messaging services.  Second, when I do make a phone call from outside the US, it costs $0.20/minute. But, if I need to make a lengthy call, I’ll usually use Skype or Hangouts and use data or Wi-Fi instead. Third, many Korean institutions expect users to have a Korean cell phone number to receive SMS messages. I finally relented and got a super cheap prepaid Korean SIM just for this purpose.

Crunching the numbers, I find that I’m paying a little more on average while in Korea than I would with a locally available plan (about $70/month vs. approx. $55). But in the summer, I’m no longer paying $120 for 2 months of AT&T’s prepaid plan while still paying for my $55/month Korean plan. I’m also not paying $20-50 to get a prepaid card every time I land in another country. I just keep paying about $70/month to burn through an average of 5GB of data through Google Fi. Due to the 6GB cap on data cost, my bill is never over $80 (plus tax).

If you’re interested in using the service, just head over to and feel free to use this referral code to get a $20 credit on your account.

Non-Fi Countries as of May, 2019

Roughneck Totes as Checked Baggage

Rubbermaid’s 25 gallon Roughneck Tote is the best container to use as checked baggage when transporting a lot of stuff via intercontinental flights. The length + width + height dimensions are the maximum allowed by airlines, maximizing the volume per piece of baggage, they stack nicely on airport carts and the handles make loading and unloading convenient. I have used this method since 2008, moving back and forth from the U.S. to Kuwait, Nigeria and South Korea, taking a couple dozen of these totes on several dozen flights. I’ve never had a problem and never lost a tote or lid.

They’re available at most Ace Hardware stores. On, the shipping charges are prohibitive. But if you visit my favorite hometown Blain’s Farm and Fleet, you can get 4 of them shipped just about anywhere in the US for around $20 each. While you’re there, throw in your 14″ zip ties, colored duct tape, packing tape, and Sharpie.

The only challenge is closing them up to remain sealed during travel. But, there is an easy way of handling this. I use a 5/16″ drill bit (8mm) to put 12 holes strategically placed around the lid which accept plastic zip-ties or 16 gauge solid-core copper wire to keep the tote sealed.

It’s important to put the holes in the right place so that if you use several totes, any lid will be able to be used on any tote with the lid and tote holes lining up perfectly. Check out my video for the details:

Shady – for super granular control of your Macbook screen brightness

On a recent trans-Pacific flight, I was doing some work on my Macbook. All was fine with the in-flight WiFi working pretty well. But when they turned off the lights after dinner, my screen was painfully bright-even on it’s lowest setting.

You can use shift-option-F1/F2 to gain some fine-tuning control over your screen’s brightness, but if you need more, there’s Shady – a tiny li’l utility that basically writes a variably transparent grey layer over your screen. That’s all. It’s great. Get it.

Shady - screen shader