Saturday, February 11, 2012

Mixed language (bash/python) function to deal with stdin pipes

often i find the need to be able to use one of my bash scripts to process data from a stdin pipe like:

somecommand |myscript


the standard way is to 'cat /dev/stdin' but alone doesnt do what is needed. for instance perhaps you are not piping output to the script (however this is simple to deal with as an 'if ! [ -t 0 ] ' statement). sometimes options/argument can get mixed into the pipe. the standard solution is to read (ie: 'cat /dev/stdin') using a non-breaking(/blocking, i forget) stty, but this kind of reading of stdin is tricky, and confusing, and /dev/stdin may not be available in all systems (chrooted hosting accounts for instance).

a simple solution is to create a bash function calling python (most systems that include bash also include python) to read stdin, and write directly back to stdout (in essence a simple python pager called as a bash function). this function looks like:

getstdin (){
python -c "from sys import *
if not stdin.isatty():stdout.write(stdin.read())
else:exit(1)"
}


note: ';else:exit(1)' isnt strictly required, but gives a standard error code if nothing on the stdin pipe, which is useful to further script logic (determining the error codes of commands to decide what functionality to produce)

this function takes care of the previously mentioned method's pitfalls. include this function in your own bash script, and deal with (or ignore) stdin pipe easily. a simple example bash script using this function:

#!/bin/bash
#  mystdin.sh
#  by - nairb <c0d3@nairb.us>
#  purpose: to add the text "RECIEVED: " and return stdin pipe

getstdin (){
python -c "from sys import *
if not stdin.isatty():stdout.write(stdin.read())
else:exit(1)"
}

stdin=$(getstdin)
if [ $stdin ];then
  echo "RECEIVED: $stdin"
else
  echo "didnt get anything on stdin, doing something else"
fi


you could run the above example script with a command like:

echo "this is some text" | bash mystdin.sh


the above function is also an example of the standard way to read from a stdin pipe in python scripts (not just calling python in bash).

--
hope someone finds this post useful,
- nairb

No comments:

Post a Comment