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 elinux.com 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 started with his code, but ended up changing it to meet my needs. My version sends an email, but also sends the Pi’s IP addresses as a Telegram Chat message.

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 startupNotifier.py.

# Written for Raspberry Pi, but likely works with other Linux versions.
# Send device IP addresses via Telegram and email on startup.
import subprocess
import smtplib
from email.mime.text import MIMEText
import datetime
import smtplib
import requests
from requests.structures import CaseInsensitiveDict
import sys
import os
import time

time.sleep(10)

# Retrieve interfaces and IP addresses.
arg='ip route list'  
#Run 'arg' in a 'hidden terminal'.
p=subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)  
data1 = p.communicate()  # Get data from 'p terminal'.

# Uncomment these 4 lines for troubleshooting
#print(' ')
#print('data1[0] = ')
#print(data1[0])
#print(' ')

# Split text block into lines.
ip_lines = data1[0].splitlines()
# Get device hostname
hostname = os.uname()[1]
message = 'IP Addresses for '+hostname+':\n'
# Find the interface names and IP addresses.
# Each line looks something like: 
# b'default via 172.31.1.1 dev eth0 proto dhcp src 65.108.91.248 metric 100 \
# Interface is between 'dev' and 'proto', IP address comes just after 'src'
for l in ip_lines:
	if ('link' in str(l)):
		temp = str(l)
		print(temp)
		print(temp.index('dev'))
		print(temp.index('proto'))
		print('temp = ' + temp)
		tempmsg01 = temp[int(temp.index('dev ')+4):int(temp.index('proto ')-1)]
		tempmsg02 = temp[int(temp.index('src ')+4):int(temp.index('src ')+19)].replace(' ','').replace('m','').replace('e','').replace('t','').replace('r','').replace('i','').replace('c','')
		print('tempmsg = ' + tempmsg01 + ': ' + tempmsg02)
		message = message + tempmsg01 + ': ' +tempmsg02 + '\n'

################################ Send Telegram message
token ='<YOUR TELEGRAM TOKEN>'
url2 = f'https://api.telegram.org/bot{token}/sendMessage'
data = {'chat_id': '<YOUR CHAT ID,', 'text': message} 
requestText = requests.post(url2, data).json()
print(requestText)

#Create the text, subject, 'from', and 'to' for the email message.
to = '<The email address you want to send to>'
gmail_user = '<Gmail address of sending account>'
gmail_password = '<Sending account's app password>'
smtpserver = smtplib.SMTP('smtp.gmail.com', 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(gmail_user, gmail_password)
today = datetime.date.today()
msg = MIMEText(message)
msg['Subject'] = 'IPs for '+hostname+' - %s' % today.strftime('%b %d %Y')
msg['From'] = gmail_user
msg['To'] = to

################################# Send the email
smtpserver.sendmail(gmail_user, [to], msg.as_string())
#Close the smtp server.
smtpserver.quit()

Step #2: Make the script executable.

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

cd ~
sudo chmod +x startupNotifier.py

Setp #3: Run the Script on Startup.

We’ll add a line to the crontab to run the script whenever the device reboots.

crontab -e

Add the following lines to the crontab

@reboot /usr/bin/python3 /home/admin/Desktop/startupNotifier.py

Now, reboot the Pi and in about a minute, you should receive an email and Telegram message 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 Terminal.app:

  1. Open Terminal.app 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 d.show Example output:<dictionary> { Addresses : <array> { 0 : 192.168.0.8 } ConfigMethod : Manual SubnetMasks : <array> { 0 : 255.255.255.0 } } If your router has the IP-address 192.168.0.1 this should be the proper interface. If your router has e.g. the IP address 192.168.1.1 the interface found above would be the wrong one and you have to search for an interface with an IP in the range 192.168.1.2-192.168.1.254.
  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 d.show should show something like:<dictionary> { SearchDomains : <array> { 0 : some.domain } ServerAddresses : <array> { 0 : 192.168.0.1 } } Depending on the DHCP setup of your router the SearchDomains entry and array may be missing.
  7. Enter d.add ServerAddresses * 8.8.8.8 9.9.9.9 – add one or more DNS-server (here Google’s 8.8.8.8 and quad9’s 9.9.9.9)
  8. Enter set State:/Network/Service/EB40E2FC-8248-48F2-8567-257D940A31EB/DNS
  9. Enter d.show to check the modified dict entry. It should show something like:<dictionary> { SearchDomains : <array> { 0 : some.domain } ServerAddresses : <array> { 0 : 8.8.8.8 1 : 9.9.9.9 } }
  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.