Create Your Own Web App to Execute Linux Command

Let say you need to run a command (which you use frequently) on your headless Linux box, such as, copying files, start/stop services, reboot, etc. However too lazy to go to the physical machine or open a ssh command from another pc.
Would it be nice if we have a web application that can easily be accessed through a web browser (even from a mobile web browser), to execute those commands. All we have to to is type the url (http://my-server-ip-address:myportnumber), and click on a link.
All these could easily be achieved using very simple service using Python.

1. Create a simple Python script. The Python script will be using WSGI to serve HTTP request/response.

vi mypythonscript.py

2. A sample of the Python script below:

import os
from cgi import parse_qs, escape

def hello_world(environ, start_response):
    parameters = parse_qs(environ.get('QUERY_STRING', ''))
    if 'type' in parameters:
        mycommand = escape(parameters['command'][0])
    else:
        mycommand = ''
    start_response('200 OK', [('Content-Type', 'text/html')])

    if mycommand == 'copyfile1':
	#your linux command here. Example below
	os.system('cp myfile1.txt mynewfile.txt')
    elif mycommand == 'copyfile2':
	os.system('cp myfile2.txt mynewfile.txt')

    return ['''Command to execute:  %(mycommand)s 
    <a href='?command=copyfile1'>Copy file 1</a>
    <a href='?command=copyfile2'>Copy file 2</a>
    ''' % {'mycommand': mycommand}]

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    #put your own server ip address and port here
    srv = make_server('127.0.0.1',81, hello_world)
    srv.serve_forever()

3. Make the Python script run on every startup. Create a bash script for this:
vi myserver

4. Here’s the script for the bash file:

#! /bin/sh
# /etc/init.d/myserver
#

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting myserver "
    python /home/username/mypythonscript.py&
    echo "[OK]"
    ;;
  stop)
    echo "Stopping myserver "
    kill -9 `pidof python`
    echo "[OK]"
    ;;
  *)
    echo "Usage: /etc/init.d/myserver {start|stop}"
    exit 1
    ;;
esac

exit 0

5. make the bash script executable.
chmod +x myserver

6. copy myserver script to /etc/init.d
sudo cp /wherever/you/saved/myserver /etc/init.d/myserver

7. update the startup folders to include the new script.
sudo update-rc.d myserver defaults

8. To test your Python web app, open a web browser, and type:
http://my-server-ip-address:81

How to Queue Torrents in Transmission

Currently there’s no queue features in Transmission. Luckily we can improvise this with the help of transmission-remote, a command based client for transmission, and along with some Linux bash scripting.

Below I have created a simple bash script:

1. Install transmission remote:
sudo apt-get install transmission-cli

2. Copy the script below, and save as my_script_name.sh , (or whatever name you prefer, but note the .sh extension).

#!/bin/sh
 
# *************
# Configuration
REMOTE="/usr/bin/transmission-remote"
USERNAME="my_username"
PASSWORD="my_password"
MAXDOWN="max_number_of_torrent_to_download"
MAXACTIVE="max_active_torrent"
CONFIG="/my_location_to_transmission_config_file/settings.json"
TRANSOPTS="127.0.0.1:my_port_number"
 
# *************
# Set-up variables
CMD="$REMOTE $TRANSOPTS --auth $USERNAME:$PASSWORD"
LOGCMD="/usr/bin/logger -t transmission-queue "
MAXRATIO=$(cat $CONFIG | grep \"ratio-limit\":)
MAXRATIO=${MAXRATIO#*\"ratio-limit\": }
MAXRATIO=${MAXRATIO%*, }
 
# *************
# deal with downloads
DOWNACTIVE="$($CMD -l | tail --lines=+2 | grep -v 100% | grep -v Sum | grep -v Stopped | grep -v Verifying | grep -v Will\ Verify | wc -l)"
if [ $MAXDOWN -lt $DOWNACTIVE ]; then
    DOWNTOSTOP="$($CMD -l | tail --lines=+2 | grep -v 100% | grep -v Sum | grep -v Stopped | grep -v Verifying | grep -v Will\ Verify | tail -n $(expr $DOWNACTIVE - $MAXDOWN) | awk '{ print $1; }')"
    for ID in $DOWNTOSTOP; do
        NAME="$($CMD --torrent $ID --info | grep Name:)"
        $LOGCMD "< << $ID: ${NAME#*Name: }"
        $CMD --torrent $ID --stop >> /dev/null 2>&1
    done
else
    [ $(expr $MAXDOWN - $DOWNACTIVE) -gt 0 ] && (
    DOWNINACTIVE="$($CMD -l | tail --lines=+2 | grep -v 100% | grep Stopped | wc -l)"
    [ $DOWNINACTIVE -gt 0 ] && (
        DOWNTOSTART="$($CMD -l | tail --lines=+2 | grep -v 100% | grep Stopped | head -n $(expr $MAXDOWN - $DOWNACTIVE) | awk '{ print $1; }')"
        for ID in $DOWNTOSTART; do
            NAME="$($CMD --torrent $ID --info | grep Name:)"
            $LOGCMD ">>> $ID: ${NAME#*Name: }"
            $CMD --torrent $ID --start >> /dev/null 2>&1
        done
        )
    )
fi
# Then deal with total active
ACTIVE="$($CMD -l | tail --lines=+2 | grep -v Sum | grep -v Stopped | grep -v Verifying | grep -v Will\ Verify | wc -l)"
if [ $MAXACTIVE -lt $ACTIVE ]; then
    TOSTOP="$($CMD -l | tail --lines=+2 | grep 100% | grep -v Stopped | grep -v Verifying | grep -v Will\ Verify | tail -n $(expr $ACTIVE - $MAXACTIVE) | awk '{ print $1; }')"
    for ID in $TOSTOP; do
        NAME="$($CMD --torrent $ID --info | grep Name:)"
        $LOGCMD "< << $ID: ${NAME#*Name: }"
        $CMD --torrent $ID --stop >> /dev/null 2>&1
    done
else
    [ $(expr $MAXACTIVE - $ACTIVE) -gt 0 ] && (
    SEEDINACTIVE="$($CMD -l | tail --lines=+2 | grep 100% | grep Stopped | awk -v ratio=$MAXRATIO '{ if (strtonum(substr($0,52,4)) < ratio) print $0 ;}' | wc -l)"
    [ $SEEDINACTIVE -gt 0 ] && (
        TOSTART="$($CMD -l | tail --lines=+2 | grep 100% | grep Stopped | awk -v ratio=$MAXRATIO '{ if (strtonum(substr($0,52,4)) < ratio) print $0 ;}' | head -n $(expr $MAXACTIVE - $ACTIVE) | awk '{ print $1; }')"
        for ID in $TOSTART; do
            NAME="$($CMD --torrent $ID --info | grep Name:)"
            $LOGCMD ">>> $ID: ${NAME#*Name: }"
            $CMD --torrent $ID --start >> /dev/null 2>&1
        done
        )
    )
fi

Save the script on any location you prefer.

3. Create a cron job to run the script. Open the entry to crontab:
crontab -e

4. Let say you want to run the script 5 minutes, the entry on your cron job should be as below:
*/5 * * * * sh /location_to_my_script/my_script_name.sh

Script courtesy of www.4geeksfromnet.com

Extend Transmission Torrent with Scripts

Transmission is one of my favourite bittorrent client. However, it’s lack the feature of running command(s) before or after you have finished downloading. Luckily we can improvise this with the help of transmission-remote, a command based client for transmission, and along with some Linux bash scripting.

Below I have created a simple bash script. What it does is, converting all of the finished avi’s to wmv. The conversion is via ffmpeg. The script below is easily modified to suit your needs, such as:
i – Copying the finished torrent to another location.
ii – Doing any conversion to your media.
iii – Send you mail notifying the torrent have finished downloading.
iv – etc, etc.

So, let’s get started.
Continue reading

Python: Executing a Program on a Remote 64-bit Windows Machine

Executing a program, exe’s, services on a remote Windows machine can be accomplished very easily, with a very few lines of code in Python. The task is similar to Psexec. However, in Python, one of the ways is using Windows Management Instrumentation (WMI).

From Tim Golden’s Python Stuff:

Windows Management Instrumentation (WMI) is Microsoft’s implementation of Web-Based Enterprise Management (WBEM), an industry initiative to provide a Common Information Model (CIM) for pretty much any information about a computer system.

Executing remote program using WMI needs the win32 extensions from Mark Hammond. Below are one of the sample code that I’ve used on a 32-bit target machine:

c = wmi.WMI ('my_remote_windows_machine')
process_id, result = c.Win32_Process.Create (CommandLine="Notepad.exe")
    for process in c.Win32_Process (ProcessId=process_id):
        returnvalue = str(process.ProcessId) + " " + str(process.Name)

    if result == 0:
        returnvalue = "Process started successfully: %s" % returnvalue
    else:
        raise RuntimeError, "Problem creating process: %s" % str(result)
    print returnvalue

 

However, when it comes to 64-bit target machines, I’m getting errors below:

  File "C:\Python26\lib\wmi.py", line 1181, in connect
    return _wmi_namespace (obj, find_classes)
  File "C:\Python26\lib\wmi.py", line 821, in __init__
    self.classes.update (self.subclasses_of ())
  File "C:\Python26\lib\wmi.py", line 843, in subclasses_of
    for c in self._namespace.SubclassesOf (root):
  File "C:\Python26\Lib\site-packages\win32com\client\util.py", line 84, in next

    return _get_good_object_(self._iter_.next(), resultCLSID = self.resultCLSID)

 

The solution:

c = wmi.WMI ('my_remote_windows_machine', find_classes=False)
process_id, result = c.Win32_Process.Create (CommandLine="Notepad.exe")
    for process in c.Win32_Process (ProcessId=process_id):
        returnvalue = str(process.ProcessId) + " " + str(process.Name)

    if result == 0:
        returnvalue = "Process started successfully: %s" % returnvalue
    else:
        raise RuntimeError, "Problem creating process: %s" % str(result)
    print returnvalue

Notice the extra parameter find_classes=False when instantiating the WMI object.
Some of the good examples on WMI in Python:
Tim Golden’s Python Stuff
WMI Cookbook

Python Programming Language

It has been almost a month now since I’ve started application development in Python. Before this, I’ve already started playing with it in my spare time. (Yeah, instead of doing important stuff like mowing the lawn, fixing the light bulb, or playing with my children, I’ve decided to learn a new programming language! I really need to set my priorities straight).

Before this my encounter with Python is merely just a few samples, consists of some web forms and web pages, using mod_python configured on Apache running on my headless CentOS box (VM actually). Run a few queries against MySQL using MySQLdb module, returns a few results, display it on the web apps, and that’s it! The experience is limited, but enough to learn it’s syntax and flow.

Now I’m developing actual program in Python at work. (Finally, something to add to my resume :)). It’s more of a client-server application, but involves a lot of components and API’s to get around with. I’ve been using win32api’s, win32net, Windows Services, WMI for remote execution, etc, etc. At times I felt my head is going to explode. But, it’s fun! At least I have something to wake up every morning to.

Wiki:

Python is a general-purpose, high-level programming language. Its design philosophy emphasizes programmer productivity and code readability. Python’s core syntax and semantics are minimalistic, while the standard library is large and comprehensive. Its use of whitespace as block delimiters is unusual among popular programming languages.

Python supports multiple programming paradigms (primarily object oriented, imperative, and functional) and features a fully dynamic type system and automatic memory management, similar to Perl, Ruby, Scheme, and Tcl. Like other dynamic languages, Python is often used as a scripting language.

Useful Links For Python:
Python Tutorials (Lots of tutorial, from beginners to advanced)
code.activestate.com (My favorite. Lots of actual running source codes)
Python 101 Cheat Sheet

IDE of Choice:
Komodo IDE
Komodo Edit (Free)
Aptana Pydev (Free)

Organizations using Python: Yahoo Maps, Yahoo Groups, Google, YouTube

Any experience or opinions on Python? What your IDE of choice? For those who’re interested, expect more post regarding Python soon. Source codes, samples and more.