Skip to content

Instantly share code, notes, and snippets.

@esarver
Last active May 2, 2017 12:28
Show Gist options
  • Select an option

  • Save esarver/899dc9c02f9bf12326fef0f1a958b3c6 to your computer and use it in GitHub Desktop.

Select an option

Save esarver/899dc9c02f9bf12326fef0f1a958b3c6 to your computer and use it in GitHub Desktop.
Socket-based IP Updater

Install code on respective boxes. On the server, install in /opt/ip-updater/. On the client install in /opt/ip-updater-node. Remove CLIENT- or SERVER- from the filenames.

Make sure that the IP addresses, host names, and file paths are all filled in. Don't forget to make the *.sh files executable.

Copy the *.service and *.socket files into /etc/systemd/system/ and run systemctl daemon-reload and systemctl enable ip_updater... on all of your boxes. Note: Symlinks will not work

These services should be available upon reboot.

Note: The machine with a static IP must be the server and must be fully running before the clients boot to make sure the message makes it to the hosts file of the server with the static IP.

[Unit]
Description=Client Side of the IP Updater
After=network-online.target
[Service]
Type=oneshot
ExecStart=/opt/ip-updater-node/ip_updater_node.sh
[Install]
WantedBy=multi-user.target
#!/bin/bash
echo "<ENTER HOST NAME HERE>" | nc <ENTER NAME/IP ADDRESS OF COMPUTER WITH STATIC IP HERE> 9999
#!/usr/bin/python
#modified from https://gist.github.com/drmalex07/333d8a88c4918954e8e4
from SocketServer import TCPServer, StreamRequestHandler
import socket
import logging
import subprocess
class Handler(StreamRequestHandler):
def handle(self):
self.data = self.rfile.readline().strip()
logging.info("From <%s>: %s" % (self.client_address, self.data))
subprocess.call(["/opt/ip-updater/ip_updater.sh", self.data, self.client_address[0]])
class Server(TCPServer):
SYSTEMD_FIRST_SOCKET_FD = 3
def __init__(self, server_address, handler_cls):
# Invoke base but omit bind/listen steps (performed by systemd activation)
TCPServer.__init__(
self, server_address, handler_cls, bind_and_activate=False)
# Override Socket
self.socket = socket.fromfd(
self.SYSTEMD_FIRST_SOCKET_FD, self.address_family, self.socket_type)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
HOST, PORT = "localhost", 9999 # not really needed here
server = Server((HOST, PORT), Handler)
server.serve_forever()
[Unit]
Description=IP Updater
After=network-online.target ip_updater.socket
Requires=ip_updater.socket
[Service]
Type=simple
ExecStart=/opt/ip-updater/ip_updater.py
TimeoutStopSec=5
[Install]
WantedBy=multi-user.target
#!/bin/bash
hostsfile=<ENTER LOCATION OF HOSTS FILE HERE>
logfile=/opt/ip-updater/ip_updater.log
echo "-------------------------" >> $logfile
echo "\"$line\""
read -ra arr <<<"$1"
hostname=${arr[0]}
ipaddr=${arr[1]}
echo "Hostname: \"$hostname\"" >> $logfile
echo "IP Addr: \"$ipaddr\"" >> $logfile
if grep -q $hostname "$hostsfile"; then
echo "It's in $hostsfile." >> $logfile
echo "Updating $hostsfile..." >> $logfile
sed -r "s/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +$hostname)/$ipaddr\1/" -i "$hostsfile"
echo "Updated $hostsfile!" >> $logfile
else
echo "It's not in $hostsfile." >> $logfile
echo "Adding to $hostsfile..." >> $logfile
echo "$ipaddr $hostname" >> $hostsfile
echo "Added to $hostsfile." >> $logfile
fi
echo "Exiting IP Updater." >> $logfile
[Unit]
Description=IP Updater Socket
PartOf=ip_updater.service
[Socket]
ListenStream=9999
[Install]
WantedBy=sockets.target
@esarver
Copy link
Author

esarver commented May 2, 2017

I updated it with some changes that I made. I think that should set it up for success (it works on my machines) so give it a try and let me know if it works for you!

Things I'd still like to do to improve this software:

  • Put the hostname of the client and server boxes in a separate text file for easy deployment
  • Simplify server code to one file (not the systemd stuff, but add the modification of the /etc/hosts files to the python script)
  • Write easy installer script to simplify installation/deployment instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment