Skip to content

Instantly share code, notes, and snippets.

@jpeyret
Last active September 29, 2015 22:04
Show Gist options
  • Save jpeyret/a34792e6bf142b90c0ea to your computer and use it in GitHub Desktop.
Save jpeyret/a34792e6bf142b90c0ea to your computer and use it in GitHub Desktop.
small Python script to diagnose vagrant chef installations. plop in some things you want to check for and it'll export them in directory /vagrant/diag.out, as seen from the guest.
#!/usr/bin/env python
import os
import subprocess
import shutil
import pdb
import pprint
from subprocess import Popen, PIPE
from shlex import split
dn_out = "/vagrant/diag.out"
dn_conf = "/vagrant/diag.conf"
try:
os.makedirs(dn_out)
except OSError:
pass
pp = pprint.PrettyPrinter(indent=4)
class module_settings(object):
USE_PDB = True
def debug(o, msg=""):
print(msg)
pp.pprint(o)
def do_tree(dn_in):
try:
li = dn_in.split()
dn = li[0]
flag = " ".join(li[1:])
except Exception, e:
if module_settings.USE_PDB: pdb.set_trace()
raise
s_out = dn.strip("/").replace("/",".")
if s_out:
s_out = ".%s" % (s_out)
fn_o = "tree%s.txt" % (s_out)
# debug(locals(),"do_tree")
# return
if not os.path.isdir(dn):
fn_o = "missing.%s" % (fn_o)
fnp_o = os.path.join(dn_out, fn_o)
with open(fnp_o, "w") as fo:
pass
return
fnp_o = os.path.join(dn_out, fn_o)
cmd = "tree %s %s" % (dn, flag)
try:
exitcode = subprocess.call(cmd.split(),
shell=False,
# executable="/bin/bash",
stdout=open(fnp_o, 'w'),
)
except OSError, e:
try:
exitcode = subprocess.call("tree")
except OSError, e2:
#ok, tree doesnt seem installed.
os.remove(fnp_o)
fnp_o = os.path.join(dn_out, "not_installed.tree.txt")
with open(fnp_o, "w") as fo:
fo.write("has the tree utility been installed?")
def do_copy():
fnp_i = os.path.join(dn_conf, "copy.txt")
dn_o = os.path.join(dn_out, "copy")
try:
os.makedirs(dn_o)
except OSError:
pass
# except Exception, e:
# if module_settings.USE_PDB: pdb.set_trace()
# raise
with open(fnp_i) as fi:
for line in fi.readlines():
fnp_i = line.split("#")[0].strip()
if not fnp_i:
continue
dn, fn = os.path.split(fnp_i)
# print "locals:"
fn_prefix = dn[1:].replace("/",".")
fn_o = "%s.%s" % (fn_prefix, fn)
fnp_o = os.path.join(dn_o, fn_o)
# debug(locals(), "locals:")
try:
shutil.copyfile(fnp_i, fnp_o)
except IOError:
fnp_o = os.path.join(dn_o, "missing.%s" % fn_o)
# debug(fnp_o)
with open(fnp_o, "w") as dummy:
pass
# break
def fmt_line(line):
line = line.split("#")[0].strip()
return line
def get_commands(fnp_i):
li_res = []
with open(fnp_i) as fi:
for line in fi.readlines():
line = fmt_line(line)
if line:
li_res.append(line)
return li_res
def do_ls_1(dn):
dn_n = "dir.%s.txt" % dn.strip("/").replace("/", ".")
if not os.path.isdir(dn):
fnp_o = os.path.join(dn_out, "missing.%s" % dn_n)
with open(fnp_o, "w") as fo:
pass
return
fnp_o = os.path.join(dn_out, dn_n)
cmd = "ls -lan %s" % (dn)
proc = subprocess.Popen(
cmd.split(),
shell=False,
stdout=subprocess.PIPE
)
with open(fnp_o, "w") as fo:
while True:
line = proc.stdout.readline()
if line != '':
#the real code does filtering here
# print "test:", line.rstrip()
li_field = line.split()
perm, fn = li_field[0], li_field[-1]
line_o = "\n%s %s" % (perm, fn)
# debug(locals(),"do_ls_1.locals")
# debug(li_field, "li_field")
fo.write(line_o)
else:
break
def do_listdir():
fnp_i = os.path.join(dn_conf, "listdir.txt")
with open(fnp_i) as fi:
for line in fi.readlines():
dn_watch = line.split("#")[0].strip()
if not dn_watch:
continue
do_ls_1(dn_watch)
def do_trees():
fnp_i = os.path.join(dn_conf, "tree.txt")
li_tree = get_commands(fnp_i)
for dn_tree in li_tree:
do_tree(dn_tree)
def do_find_proc():
fnp_i = os.path.join(dn_conf, "proc.txt")
li = get_commands(fnp_i)
for i in li:
find_proc(i)
def find_proc(procname, comment=""):
#ps -ef | grep "[r]unsvdir"
fn = "proc.%s.txt" % (procname)
# fnp_o = os.path.join(dn_out, fn_o)
cmd = "pgrep -lf %s " % (procname)
proc = subprocess.Popen(
cmd.split(),
shell=False,
# executable="/bin/bash",
stdout=subprocess.PIPE,
)
li = []
while True:
line = proc.stdout.readline()
if line != '':
li.append(line)
else:
break
if not li:
fn = "missing.%s" % (fn)
fnp_o = os.path.join(dn_out, fn)
with open(fnp_o, "w") as fo:
[fo.write("\n%s" % line) for line in li]
def do_command(cmd, comment=""):
s_cmd = cmd.strip().replace(" ", ".").replace("/",".")
fn = "command.%s.txt" % (s_cmd)
fnp_o = os.path.join(dn_out, fn)
try:
proc = subprocess.Popen(
cmd.split(),
shell=False,
# executable="/bin/bash",
stdout=open(fnp_o, "w"),
)
except OSError, e:
os.remove(fnp_o)
fnp_o = os.path.join(dn_out, "error:%s" % fn)
with open(fnp_o, "w") as fo:
fo.write(e)
def do_commands():
fnp_i = os.path.join(dn_conf, "command.txt")
li = get_commands(fnp_i)
for i in li:
do_command(i)
def main():
do_trees()
# return
do_listdir()
do_copy()
do_find_proc()
do_commands()
if __name__ == '__main__':
main()
@jpeyret
Copy link
Author

jpeyret commented Sep 29, 2015

This is the general idea of how to use it:


configuration in diag.conf:


diag.conf
├── command.txt
├── copy.txt
├── listdir.txt
├── proc.txt
└── tree.txt

0 directories, 5 files


diag.conf/command:


run these commands and save their ouput

redis-cli ping


diag.conf/listdir.txt:


list the contents of directories

/var/run
/sbin
/usr/local/bin
/etc/service
/etc/runit
/etc/supervisor.d/


diag.conf/proc.txt:


list running processes using pgrep

runsvdir
foobar #this one will be missing


diag.conf/tree.txt:


run the tree command, if available and save the output

/ -I proc
/srv/bemyerp/current


diag.conf/copy.txt:


copy the contents of these files out.

/etc/redis/redis.conf
/etc/redis/dummy.will_be_missing
/etc/supervisord.conf

sample usage:

(but of course the point is to be able to inspect things at leisure
on your dev machine.
)

vagrant@vagrant:$ rm -rf /vagrant/diag.out && /vagrant/diag.py
vagrant@vagrant:
$ tree /vagrant/diag.out
/vagrant/diag.out
├── command.redis-cli.ping.txt
├── dir.etc.service.txt
├── dir.sbin.txt
├── dir.usr.local.bin.txt
├── dir.var.run.txt
├── copy
│   ├── etc.redis.redis.conf
│   ├── missing.etc.redis.dummy.will_be_missing
│   └── missing.etc.supervisord.conf
├── missing.dir.etc.runit.txt
├── missing.dir.etc.supervisor.d.txt
├── missing.proc.foobar.txt
├── missing.tree.srv.bemyerp.current.txt
├── proc.runsvdir.txt
└── tree.txt

1 directory, 14 files

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