Tuesday, January 20, 2015

Invoke a shell script via python script and print result

1. Create your shell script.
> vi call.sh
        echo "shell return"


2. Give executable permission to run the script.
> chmod +x call.sh

If you don't give executable permission, following error occurs.
Traceback (most recent call last):
  File "invoke.py", line 4, in <module>
    toPrint2 = check_output(['./call.sh'])
  File "/usr/lib/python2.7/subprocess.py", line 537, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
    raise child_exception
OSError: [Errno 13] Permission denied

3. Create your python script.
> vi invoke.py
from subprocess import check_output

print "-------------------"
toPrint2 = check_output(['./call.sh'])
print toPrint2

4. Run your python script.
> python invoke.py
shell return

Now lets try something advanced. 
Say you have a web server starting in a given port and you want to know as soon as the server comes online.

This is how you do it.

1. Change python script as follows
from subprocess import call
print "-------------------"
call(['./portListener.sh'], shell="True")

2. Create our new shell script to listen to the port
> vi portListener.sh
echo -n Please wait... 
while ! echo exit | nc 9443; do
echo -n '.';
sleep 1; # Scan for every 1 second interval.
echo Server is online on port 9443...

3. Give executable permission to run the script
> chmod +x portListener.sh

4. Run the python script
>  python invoke.py
Please wait.............

Here you can see the progress bar in action waiting for the server to become online.

5. Start your server.
Say that it's ip is and running on port 9443. I have used WSO2 ELB 2.1.0 for my testing in a virtual machine environment.
Also make sure that your python script running instance can access this server's network.

6. Once the server becomes online, the script will be completed saying the given server is online.
Please wait..............................Server is online on port 9443...

Have fun...

Tuesday, January 6, 2015

Puppet create a multi-level directory structure

Lets assume that you currently have your only puppet agent and the puppet master.
In this case you can write your code segment in /etc/puppet/manifests/site.pp file itself under default node definition (This will be applied to all nodes if NO matching node definition is found for the given puppet agent hostname).

node default {

        # create a directory
        $dirpath = '/tmp/dbscripts/mysql'
        exec { "create_dir_structure":
                path        => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
                command => "mkdir -p ${dirpath}",

        # create the file
        file {  "/tmp/dbscripts/mysql/hellopuppet.txt":
                ensure  => file,
                content => 'master says hello to puppet agent',


This will successfully create the directory structure even if parent directory does not exist.

If you attempt to create the directory structure as follows,
# create a directory
file { "/tmp/dbscripts/mysql/":
                ensure => "directory",

You will get the following error.
Error: Cannot create /tmp/dbscripts/mysql; parent directory /tmp/dbscripts does not exist

There has been a suggested feature [1] logged in Puppet Labs yet NOT implemented as of puppet version 3.4.3 master/agent. May be there are smart alternatives as above rather than adding an additional feature... :)

[1] http://projects.puppetlabs.com/issues/86
[2] https://github.com/ghoneycutt/puppet-module-common/blob/master/manifests/mkdir_p.pp