Skip to content

Instantly share code, notes, and snippets.

@eminence
Created December 19, 2012 22:58
Show Gist options
  • Save eminence/4341366 to your computer and use it in GitHub Desktop.
Save eminence/4341366 to your computer and use it in GitHub Desktop.
SMoshS -- start mosh via an SMS!

SMoshS - Stop/stop mosh via SMS!

This script allows you to start/stop mosh via text messages (SMS)! It connects to the SMS network via the excellent Twilio. After you buy a phone number from Twilio, any calls or SMSs will be POSTd to the URL of your choice. This script provides a webserver that will respond to those Twilio POSTs, so simply start it up, enter the correct URL into the Twilio control panel, and you're off!

#!/home/achin/devel/envs/smoshs/bin/python
import BaseHTTPServer
from pprint import pprint
from twilio import twiml
from urlparse import parse_qs
import subprocess
import re
import os
import signal
class SmoshsHandler(BaseHTTPServer.BaseHTTPRequestHandler):
mosh_map = {}
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type","text/plain")
self.end_headers()
self.wfile.write("Hello!")
self.wfile.close()
def _send_reply(self, msg, data):
r = twiml.Response()
r.sms(msg, to=data['From'][0], sender=data['To'][0])
s = str(r)
self.send_response(200)
self.send_header("Content-Type","text/xml")
self.send_header("Content-Length",len(s))
self.end_headers()
self.wfile.write(s)
def do_POST(self):
pprint(self.path)
if not self.path.startswith("/smoshs"):
self.send_response(404)
self.send_header("Content-Type","text/plain")
self.end_headers()
self.wfile.write("404")
return
pprint(self.headers)
length = int(self.headers.get("Content-Length"))
data = parse_qs(self.rfile.read(length))
fromnumber = data['From'][0]
pprint(data)
body = data['Body'][0].lower().split()
if body[0] != "mosh":
return self._send_reply("bad command", data=data)
if len(body) < 2:
return self._send_reply("sub commands: start, kill, status", data=data)
if body[1] == "status":
if fromnumber in self.mosh_map:
pid = self.mosh_map[fromnumber]['pid']
try:
exe = os.readlink("/proc/%d/exe" % pid)
print "Mosh exe process looks like", exe
except:
exe=""
if not exe.endswith("mosh-server"):
print "Mosh seems to have died, cleaning up"
del self.mosh_map[fromnumber]
return self._send_reply("Your mosh process has died", data=data)
return self._send_reply("Mosh is still running", data=data)
else:
return self._send_reply("No mosh processes running for you", data=data)
elif body[1] == "kill":
msg = ""
if fromnumber in self.mosh_map:
pid = self.mosh_map[fromnumber]['pid']
os.kill(pid, signal.SIGINT)
del self.mosh_map[fromnumber]
return self._send_reply("Mosh-server processed killed", data=data)
else:
return self._send_reply("No mosh processes running for you", data=data)
elif body[1] == "start":
msg = ""
if fromnumber in self.mosh_map:
pid = self.mosh_map[fromnumber]['pid']
try:
exe = os.readlink("/proc/%d/exe" % pid)
print "Mosh exe process looks like", exe
except:
exe=""
if not exe.endswith("mosh-server"):
print "Mosh seems to have died, cleaning up"
del self.mosh_map[fromnumber]
msg = "You had a mosh-server process, but it died. I'll start a new one. "
else:
return self._send_reply("You already have a mosh-server running. Send \"mosh kill\" to kill it", data=data)
p = subprocess.Popen(["mosh-server", "new"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p.wait()
moshout = p.stdout.read()
# get PID
moshpid = moshport = moshkey = None
for line in moshout.split("\n"):
m = re.search(r"\[mosh-server detached, pid = (\d+)\]", line)
if m:
moshpid = int(m.group(1))
m = re.search(r"MOSH CONNECT (\d+) (\S+)", line)
if m:
moshport = int(m.group(1))
moshkey = m.group(2)
print "mosh is running as pid %d on port %d with key %s" % (moshpid, moshport, moshkey)
self.mosh_map[fromnumber] = dict(pid=moshpid, port=moshport, key=moshkey)
return self._send_reply(msg + "Mosh started on port %d with key %s" % (moshport, moshkey), data=data)
def run(server_class=BaseHTTPServer.HTTPServer,
handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
server_address = ('', 8080)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
if __name__ == "__main__":
run(handler_class=SmoshsHandler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment