Cloud User Shell (cush) is a multi-call executable (like BusyBox) that combines many useful cloud computing utilities into a single utility, bringing cushy, RESTful cloud control to the command line.
It follows Unix principles, seamlessly blending cloud resources into existing working environments. In addition to bringing basic HTTP verbs (get, put, post, delete) to the shell, it allows URLs to be ‘dereferenced’ and software pipelines of server side software to be created.
Most people will create a link to cush for each function they wish to use and cush will act like whatever it was invoked as, but it can also be called directly and passed the command as the first parameter.
Web
linux
python
shell
computing
internet
webservices
cloud
cloud-computing
I am utilizing Google’s project hosting to host software which I create and feel is useful or want to keep track of. I called the project Brock’s Tools. The code that led me to create this project was a command I am calling prepend 1.1. (UPDATE: See this post on sponge as its a better general case tool.)
prepend, prepend’s files or standard input to a file. For example, you have three files:
$ echo BROCK > a $ echo DAVID > b $ echo NOLAND > c
And you want to combine them into one file:
$ echo "My name is:" | prepend - a b c $ cat c My name is: BROCK DAVID NOLAND
Or lets say you just want to append a file to itself:
$ cat a BROCK $ cat a >> a cat: a: input file is output file
prepend does this:
$ prepend a $ cat a BROCK BROCK
I come across the a situation where this would be useful quite often. Of course prepend’ing can be done in the shell:
$ { echo "My name is:"; cat a b c; } > tmp && mv -f tmp c
$ cat c
My name is:
BROCK
DAVID
NOLAND
However, that is unsafe and I have lost data that way. I perform this operation most often when dealing with XML. In this example, its trivial to open the file in an editor, but with a large file, its quite nasty to do so:
$ cat something.xml <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> $ echo "</entries>" >> something.xml $ cat something.xml <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> </entries> $ echo "<entries>" | prepend - something.xml $ cat something.xml <entries> <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> </entries>
I just read the following post Python - Script - Which Webserver Does That Site Run? by blogger Corey Goldberg.
I prefer the shell version:
$ what-http-server() { curl -s -I "http://$1" | awk -F': ' '/^Server:/ {print $2}'; }
$ what-http-server www.pylot.org
Apache/2.0.52
$ what-http-server() { curl -s -I "$@" | awk -F': ' '/^Server:/ {print $2}'; }
$ what-http-server www.pylot.org google.com bashcurescancer.com
Apache/2.0.52
gws
Apache/2.2.6 (Unix)
That works but this version is more correct:
what-http-server() { curl -s -I $(for h in "$@"; do printf "http://%s " "$h"; done) | awk -F': ' '/^Server:/ {print $2}'; }
In the version which works for multiple hosts, we are letting curl assume the protocol is HTTP. This works fine most of the time. However, there are exceptions:
If you specify URL without protocol:// prefix, curl will attempt to guess what protocol you might want. It will then default to HTTP but try other protocols based on often-used host name prefixes. For example, for host names starting with “ftp.” curl will assume you want to speak FTP. - man curl
The web services paradigm of development is based on the Unix philosophy of “small is good”. Web services should do one job, and do it well, allowing users to develop complex solutions by combining small, reliable and proven services.
Why not then, expose the power of familiar Unix commands like sort, grep, gzip… to the web?
Here is a proof of concept python script (Python 2.3 version) to demonstrate.
Start services:
$ ./to_web.py -p8008 sort & Thu Mar 27 13:45:54 2008 sort server started - 8008 $ ./to_web.py -p8009 gzip & Thu Mar 27 13:46:29 2008 gzip server started - 8009
Use the services:
$ for i in {1..10}; do echo ${RANDOM:0:2}; done | \
> curl –data-binary @- “http://swat:8008/sort+-nr” | \
> curl –data-binary @- “http://swat:8009/gzip” | \
> gunzip
97
37
23
23
21
18
11
11
10
10
In my position, we have a database with host information - which has a command line interface. This tool has dependencies which are a painful to resolve. With to_web.py, we can turn the command line tool into a web service and access the data without having to satisfy those additional dependencies.
This is guest post by my esteemed colleague Adam Fokken. He can be reached here: Sadly, he does not have a blog.
There are situations where, if you want a Python, PERL, PHP, etc script to be portable among a few different servers, it makes sense to wrap the script in shell. A few years ago I was trying to use the Python cx_Oracle module. This module is a wrapper for the native Oracle database driver. However, it requires the driver library directory be in the LD_LIBRARY_PATH environment variable.
No problem I thought. I’ll use the os.environ dict to set the variable. Example script:
$ cat python-only.sh
#!/usr/bin/python
import sys, os
sys.path.append("/usr/local/lib/python2.4/site-packages/")
if not os.environ.has_key('LD_LIBRARY_PATH'):
os.environ['LD_LIBRARY_PATH'] = "/home/noland/oracle-lib"
else:
os.environ['LD_LIBRARY_PATH'] = "/home/noland/oracle-lib:" + os.environ['LD_LIBRARY_PATH']
print "LD_LIBRARY_PATH looks OK in Python: LD_LIBRARY_PATH = ", os.environ['LD_LIBRARY_PATH']
os.system('echo LD_LIBRARY_PATH looks OK via os.system: LD_LIBRARY_PATH = $LD_LIBRARY_PATH')
try:
import cx_Oracle
print "Imported cx_Oracle! LD_LIBRARY_PATH was set correctly."
except ImportError, e:
print "Woops, LD_LIBRARY_PATH was not set correctly: ", e
This method does not work:
$ ./python-only.sh LD_LIBRARY_PATH looks OK in Python: LD_LIBRARY_PATH = /home/noland/oracle-lib LD_LIBRARY_PATH looks OK via os.system: LD_LIBRARY_PATH = /home/noland/oracle-lib Woops, LD_LIBRARY_PATH was not set correctly: libclntsh.so.10.1: cannot open shared object file: No such file or directory
This seems to be a common problem. However, when I was dealing with this a few years ago, I could not find a good resource on Google. I bite the bullet and wrote a separate shell script wrapper - hating invocation of the shell script. However, there is absolutely no reason I needed a separate shell script. I could have embedded the Python within a shell script. Example:
$ cat python-and-bash.sh
#/bin/bash
export LD_LIBRARY_PATH=/home/noland/oracle-lib:$LD_LIBRARY_PATH
/usr/bin/python<<END_OF_PYTHON
import sys
sys.path.append("/usr/local/lib/python2.4/site-packages/")
try:
import cx_Oracle
print "Imported cx_Oracle! LD_LIBRARY_PATH was set correctly."
except ImportError, e:
print "Woops, LD_LIBRARY_PATH was not set correctly: ", e
END_OF_PYTHON
Ahh, much better:
$ ./python-and-bash.sh Imported cx_Oracle! LD_LIBRARY_PATH was set correctly.
Of course I could have just set this variable in my profile. However, this creates an additional external dependency - which is what I was trying to avoid.