Sunday, May 19, 2013

Persistent SSH Sessions - using SSHFS and AUTOSSH

In this example, we can establish persistent SSHFS mounts using AUTOSSH - advantage being that even if SSH session dies, AutoSSH will re-establish the SSHFS session

Question: What is so cool about this ?

Answer:

Assume that the IP address of my PC is 199.199.199.100. Now, I wish to access/edit files on 10.0.0.170. I want to edit those files using my favourite text editor (such as SUBLIME TEXT 2).


This cool editor is installed on my PC, but not on the remote machine. Even though I can edit it using "vim", I wish to edit the file using SUBLIME TEXT 2.

So, what I do is I mount the remote directory locally via SSH protocol.

Old way of doing things:

Usually, I do "ssh giridhar@10.0.0.170" , then do a "cd /home/giridhar/data/" and then edit via the usual command: "vim source.py".

New way of doing things:

Now that I have SUBLIME TEXT 2 on my PC, I mount it via SSH:

On my PC :

"mkdir -p /home/bhujanga/SSH_MOUNT_POINTS/giridhar-10.0.0.170"

Note: my home directory on my PC is /home/bhujanga

Then I run :

"sshfs giridhar@10.0.0.170:/home/giridhar /home/bhujanga/SSH_MOUNT_POINTS/giridhar-10.0.0.170"

What the above commands does is - it mount's my home directory /home/giridhar on the remote machine 10.0.0.170 on my PC locally in the directory /home/bhujanga/SSH_MOUNT_POINTS/giridhar-10.0.0.170

Now I can fire up SUBLIME TEXT 2 editor and edit the file /home/bhujanga/SSH_MOUNT_POINTS/giridhar-10.0.0.170/data/source.py

as though it was a local file. But it is actually a file on the remote machine /home/giridhar/data/file.py mounted locally via SSH protocol

Now to enable persistent SSH sessions - modify the following Python Script to your requirements and run it to have the SSHFS sessions running all the time !

mount_details array below has a arrays as elements - first one being the user@host, second being the remote directory to mount locally, third being local directory on which the remote directory is mounted

#!/usr/bin/python

import os
import sys
import commands
import traceback

mount_details = [\
    ["root@10.0.37.1",      "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.37.1"      ],\
    ["root@10.0.37.3",      "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.37.3"      ],\
    ["root@10.0.0.95",      "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.0.95"      ],\
    ["giridhar@10.0.0.170", "/", "/Users/giri/SSH_MOUNT_POINTS/giridhar-10.0.0.170" ],\
    ["root@10.0.14.14",     "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.14.14"     ],\
    ["root@10.0.14.18",     "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.14.18"     ]\
]

#["root@10.0.18.128",    "/", "/Users/giri/SSH_MOUNT_POINTS/root-10.0.18.128"    ],\
def exe(cmd_to_exe):
    print "Executing command : [%s]" % (cmd_to_exe)
    status,output = commands.getstatusoutput(cmd_to_exe)
    if status == 0:
        print "Successful !"
    else:
        print "Failed !"

    # for now, lets comment the output of the commands
    '''
    print "Output:"
    print output
    '''
    return status,output

def do_mounts():
    try:
        for item_array in mount_details:
            dir_path = item_array[2]
            exe("mkdir -p %s" % (dir_path))
            mnt_cmd = "sshfs -o reconnect,compression=yes,"\
            "transform_symlinks,"\
            "ServerAliveInterval=30,"\
            "ServerAliveCountMax=30,"\
            "ssh_command='autossh -M 0' %s:%s %s" % (item_array[0],item_array[1],item_array[2])
            exe(mnt_cmd)
    except Exception,ex:
        print "Exception: %s" % (ex)
        print "%s" % (traceback.format_exc())

def main():
    do_mounts()

if __name__ == "__main__":
    main()

# shfs -o reconnect,compression=yes,transform_symlinks,ServerAliveInterval=30,ServerAliveCountMax=30,ssh_command='autossh -M 0' username@server:/ /mnt/remote"

Wednesday, May 15, 2013

My ~/.bashrc File

Here is my recent ~/.bashrc file

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    # We have color support; assume it's compliant with Ecma-48
    # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
    # a case would tend to support setf rather than setaf.)
    color_prompt=yes
    else
    color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

alias _1='ssh root@10.0.37.1'
alias _2='ssh root@10.0.37.2'
alias _old='cd /mnt/SATA-OLD/giri/'
alias __='echo $PWD > /tmp/__PWD__;ssh root@localhost'
alias ___='ssh root@localhost'
alias _b='ssh -X giridhar@10.0.0.170'
alias ll='ls -ltrh'
alias ...='ssh root@199.199.199.120'
alias ..='cd ..'
alias _v='gvim >/dev/null 2>&1'

export PATH=$PATH:/home/giri/bin

export PS1="\[\033[01;33m\]\h\[\033[01;34m\] \W \$\[\033[00m\] "

export PATH=$PATH:/opt/TurboVNC/bin

alias do_all_mounts='/home/giri/do_ssfs_mounts_10.0.37.2.sh; /home/giri/do_ssfs_mounts_10.0.0.170.sh'

alias cd_build='/home/giri/do_ssfs_mounts_10.0.0.170.sh; cd /home/giri/REMOTE/giridhar-10.0.0.170'
alias cd_idb='/home/giri/do_ssfs_mounts_10.0.37.2.sh; cd /home/giri/REMOTE/root-10.0.37.2'

function setup_public_key()
{
    if [ -f "$HOME/.ssh/id_rsa.pub" ]; then
        pubkey=`cat $HOME/.ssh/id_rsa.pub`
        ssh "$1"@"$2" "echo \"$pubkey\" >> ~/.ssh/authorized_keys"
    else
        echo "File [ $HOME/.ssh/id_rsa.pub ] does not exist !"
        echo "To generate this, please run \"ssh-keygen -t rsa\" command first"
    fi
}

alias _pub=setup_public_key

## fix below assumes you have root login enabled ##

fix_1="mkdir -p ~/.ssh; touch ~/.ssh/id_rsa ; touch ~/.ssh/id_rsa.pub ; touch ~/.ssh/authorized_keys ; touch ~/.ssh/known_hosts"

fix_2="chmod 700 ~/.ssh ; chmod 600 ~/.ssh/id_rsa ; chmod 644 ~/.ssh/id_rsa.pub ; chmod 644 ~/.ssh/authorized_keys ; chmod 644 ~/.ssh/known_hosts"

fix_3="sed -i 's/#UseDNS\ yes/UseDNS\ no/' /etc/ssh/sshd_config;sed -i 's/GSSAPIAuthentication\ yes/GSSAPIAuthentication\ no/' /etc/ssh/sshd_config;service sshd restart"

function fix_ssh()
{
    if [ -f "$HOME/.ssh/id_rsa.pub" ]; then
        pubkey=`cat $HOME/.ssh/id_rsa.pub`
        ssh "$1"@"$2" "$fix_1"
        ssh "$1"@"$2" "$fix_2"
        ssh "$1"@"$2" "$fix_3"
    else
        echo "File [ $HOME/.ssh/id_rsa.pub ] does not exist !"
        echo "To generate this, please run \"ssh-keygen -t rsa\" command first"
    fi
}

alias _sshfix=fix_ssh

alias _sshfs='sh /home/giri/sshfs_do_umount_and_mount.sh'
# export EDITOR="/usr/local/sublime/sublime_text"
export EDITOR="/usr/bin/vim"

export _JAVA_OPTIONS="-Dawt.useSystemAAFontSettings=on -Dswing.aatext=true"

alias py='nohup /home/giri/Applications/PyCHARM/Linux/pycharm-2.7.1/bin/pycharm.sh >/dev/null 2>&1 &'

alias 150='ssh root@10.0.0.150'
alias 170='ssh giridhar@10.0.0.170'

alias 37-1='ssh root@10.0.37.1'
alias 37-2='ssh root@10.0.37.2'
alias 37-3='ssh root@10.0.37.3'

alias 95='ssh root@10.0.0.95'

alias sub='nohup sublime >/dev/null 2>&1 &'
alias 127='ssh root@10.0.18.127'
alias 128='ssh root@10.0.18.128'

alias 53-1='ssh root@10.0.53.1'
alias 53-2='ssh root@10.0.53.1'
alias 82-1='ssh root@10.0.82.1'

alias MBG='giridhar@10.0.0.170'
alias MBGTMP='giridhar@10.0.0.170:/tmp'

function sshfs_mkdir()
{
mkdir -p /home/giri/SSH_MOUNT_POINTS/giridhar-10.0.0.170/home/giridhar; \
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/reverse_tunnel; \
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/MS-SQL; \
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1_root; \
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.0.150/home/rpm_path/GIRI; \
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.0.95/root.build_rpm.MYSQL.CHICKEN_CURRY;
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.18.128/slash
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.14.14/slash
mkdir -p /home/giri/SSH_MOUNT_POINTS/root-10.0.14.18/slash
}

function sshfs_umount()
{
fusermount -u /home/giri/SSH_MOUNT_POINTS/giridhar-10.0.0.170/home/giridhar; \
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/reverse_tunnel; \
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/MS-SQL; \
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1_root; \
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.0.150/home/rpm_path/GIRI; \
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.0.95/root.build_rpm.MYSQL.CHICKEN_CURRY;
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.18.128/slash;
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.14.14/slash
fusermount -u /home/giri/SSH_MOUNT_POINTS/root-10.0.14.18/slash
}

function sshfs_mount()
{
sshfs giridhar@10.0.0.170:/home/giridhar /home/giri/SSH_MOUNT_POINTS/giridhar-10.0.0.170/home/giridhar;
sshfs root@10.0.37.1:/root/reverse_tunnel /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/reverse_tunnel;
sshfs root@10.0.37.1:/root/MS-SQL /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1/root/MS-SQL;
sshfs root@10.0.37.1:/root /home/giri/SSH_MOUNT_POINTS/root-10.0.37.1_root;
sshfs root@10.0.0.150:/home/rpm_path/GIRI /home/giri/SSH_MOUNT_POINTS/root-10.0.0.150/home/rpm_path/GIRI;
sshfs root@10.0.0.95:/root/build_rpm/MYSQL/CHICKEN_CURRY /home/giri/SSH_MOUNT_POINTS/root-10.0.0.95/root.build_rpm.MYSQL.CHICKEN_CURRY;
sshfs root@10.0.18.128:/ /home/giri/SSH_MOUNT_POINTS/root-10.0.18.128/slash
sshfs root@10.0.14.14:/ /home/giri/SSH_MOUNT_POINTS/root-10.0.14.14/slash
sshfs root@10.0.14.18:/ /home/giri/SSH_MOUNT_POINTS/root-10.0.14.18/slash
}

function sshfs_umount_and_mount()
{
    sshfs_mkdir
    sshfs_umount
    killall -9 sshfs;
    sshfs_mount
}

alias _sshfs_umount_mount=sshfs_umount_and_mount

export pass="mypassword123"
alias rdp='nohup rdesktop -u admin -p $pass -g 1915x1055 -x l -a 16 10.0.0.35 >/dev/null 2>&1 &'

alias _tz='tar -zxvf'
alias _tj='tar -jxvf'

function start()
{
    ssh root@10.0.0.$1 "service mysqld start"
}

function stop()
{
    ssh root@10.0.0.$1 "service mysqld stop"
}

alias start='start'
alias stop='stop'

alias 14-14='ssh root@10.0.14.14'
alias 14-18='ssh root@10.0.14.18'

Ubuntu - Make Unity faster

Put this line in ~/.xprofile file

export UNITY_LOW_GFX_MODE=1

~/.Xresources file

This is my ~/.Xresources file

Xft.dpi:        96
Xft.antialias:  true
Xft.rgba:       rgb
Xft.hinting:    true
Xft.hintstyle:  hintslight

Tweak Mouse settings through a script

This 2 liner script can be used to tweak mouse settings - especially Razer Mice

First query the mice present on your system

$ xinput --list
⎡ Virtual core pointer                     id=2 [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer               id=4 [slave  pointer  (2)]
⎜   ↳ PixArt Microsoft USB Optical Mouse       id=8 [slave  pointer  (2)]
⎣ Virtual core keyboard                    id=3 [master keyboard (2)]
    ↳ Virtual core XTEST keyboard              id=5 [slave  keyboard (3)]
    ↳ Power Button                             id=6 [slave  keyboard (3)]
    ↳ Power Button                             id=7 [slave  keyboard (3)]
    ↳ Apple Inc. Apple Keyboard                id=9 [slave  keyboard (3)]
    ↳ Apple Inc. Apple Keyboard                id=10 [slave  keyboard (3)]
    ↳ Eee PC WMI hotkeys                       id=11 [slave  keyboard (3)]

setup_mouse.sh - Microsoft Mouse

#!/bin/bash
xinput set-prop "PixArt Microsoft USB Optical Mouse" "Device Accel Constant Deceleration" 1
xinput set-prop "PixArt Microsoft USB Optical Mouse" "Device Accel Velocity Scaling" 3

Tuesday, May 14, 2013

Python Daemon Example (with Logging)

Here is a small example of a Daemon implemented in Python - with Logging

File: Python-Daemon-Class.py

#!/usr/bin/python

import sys
import time
import os
import atexit
from signal import SIGTERM
import logging

logging.basicConfig(filename='/tmp/my_daemon.log',level=logging.DEBUG)

#logging.debug('This message should go to the log file')
#logging.info('So should this')
#logging.warning('And this, too')

class MyDaemon(object):
    """
        A generic daemon class.
        Usage: subclass the Daemon class and override the run() method
    """
    startmsg = "started with pid %s"

    def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
            self.stdin = stdin
            self.stdout = stdout
            self.stderr = stderr
            self.pidfile = pidfile

    def daemonize(self):
        """
        do the UNIX double-fork magic, see Stevens' "Advanced 
        Programming in the UNIX Environment" for details (ISBN 0201563177)
        http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
        """
        try: 
                pid = os.fork() 
                if pid > 0:
                        # exit first parent
                        sys.exit(0) 
        except OSError, e: 
                sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
                sys.exit(1)

        # decouple from parent environment
        os.chdir(".") 
        os.setsid() 
        os.umask(0) 

        # do second fork
        try: 
            pid = os.fork() 
            if pid > 0:
                # exit from second parent
                sys.exit(0) 
        except OSError, e: 
            sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.exit(1) 
        
        # redirect standard file descriptors
        si = file(self.stdin, 'r')
        so = file(self.stdout, 'a+')
        se = file(self.stderr, 'a+', 0)
        
        pid = str(os.getpid())
        
        sys.stderr.write("\n%s\n" % self.startmsg % pid)
        sys.stderr.flush()

        if self.pidfile:
            file(self.pidfile,'w+').write("%s\n" % pid)
        
        atexit.register(self.delpid)
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

    def delpid(self):
        os.remove(self.pidfile)

    def start(self):
        """
        Start the daemon
        """
        # Check for a pidfile to see if the daemon already runs
        try:
            pf = file(self.pidfile,'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if pid:
            message = "pidfile %s already exist. Daemon already running?\n"
            sys.stderr.write(message % self.pidfile)
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        self.run()

    def stop(self):
        """
        Stop the daemon
        """
        # Get the pid from the pidfile
        try:
                pf = file(self.pidfile,'r')
                pid = int(pf.read().strip())
                pf.close()
        except IOError:
                pid = None

        if not pid:
            message = "pidfile %s does not exist. Daemon not running?\n"
            sys.stderr.write(message % self.pidfile)
            return # not an error in a restart

        # Try killing the daemon process        
        try:
            while 1:
                os.kill(pid, SIGTERM)
                time.sleep(0.1)
        except OSError, err:
            err = str(err)
            if err.find("No such process") > 0:
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
                else:
                    print str(err)
                    sys.exit(1)

    def restart(self):
        """
        Restart the daemon
        """
        self.stop()
        time.sleep(5)
        self.start()

    def run(self):
        """
        You should override this method when you subclass Daemon.
        It will be called after the process has been
        daemonized by start() or restart().
        """

class TaskDaemon(MyDaemon):
    def run(self):
        while True:
            ''' this function below is called every 1 second '''
            try:
                do_my_task()
            except Exception,ex:
                print "Error in doing do_my_task(): %s" % (ex)

            ''' sleep for 1 second before doing stuff again '''
            time.sleep(1)

def do_my_task():
    logging.info("%s" % (time.time()))

def main():

    PIDFILE = '/tmp/my_daemon.pid'
    daemon = TaskDaemon(PIDFILE)
    daemon_name = "TaskDemon"

    if len(sys.argv) == 2:
        #==============================================================
        if 'start' == sys.argv[1]:
            try:
                daemon.start()
            except Exception,ex:
                print "%s start() error: %s" % (daemon_name,ex)
        #==============================================================
        elif 'stop' == sys.argv[1]:
            try:
                daemon.stop()
            except Exception,ex:
                print "%s stop() error: %s" % (daemon_name,ex)
        #==============================================================
        elif 'restart' == sys.argv[1]:
            try:
                daemon.restart()
            except Exception,ex:
                print "%s retart() error: %s" % (daemon_name,ex)
        #==============================================================
        else:
            print "Unknown command"
            sys.exit(2)
        #==============================================================
        sys.exit(0)
    else:
        #==============================================================
        print "usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)
        #==============================================================

if __name__ == "__main__":
    main()
    

Output:


~ $ ./Python-Daemon-Class.py start -------------> Start Daemon

started with pid 28387

~ $ ./Python-Daemon-Class.py stop --------------> Stop Daemon


~ $ ./Python-Daemon-Class.py restart -----------> Restart Daemon

started with pid 28534

~ $ tail -f /tmp/my_daemon.log 
INFO:root:1368539507.14
INFO:root:1368539508.14
INFO:root:1368539509.14
INFO:root:1368539510.14
INFO:root:1368539511.14
INFO:root:1368539512.14
INFO:root:1368539513.14
INFO:root:1368539514.15
INFO:root:1368539515.15

Sunday, May 12, 2013

Multi-Threaded (Socket) Server in Python

Here is a small example of Multi-Threaded Socket Server in Python

Server.py

#!/usr/bin/python

import SocketServer
import subprocess
import sys
from threading import Thread
import time

HOST = 'localhost'
PORT = 21212

############################################################################

def reverse_string(my_str):
    if my_str:
        return my_str[::-1]

############################################################################
'''  One instance per connection.
     Override handle(self) to customize action. '''

class TCPConnectionHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        
        print "SingleTCPHandler::handle()"

        # self.request is the client connection
        data = self.request.recv(1024)  # clip input at 1Kb
        print "handle(): Received data : data =>\n[%s]" % (data)

        reply = reverse_string(data)

        print "handle(): Sending reply [%s]" % (reply)

        if reply is not None:
            self.request.send(reply)
        self.request.close()

############################################################################

class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    # Ctrl-C will cleanly kill all spawned threads
    daemon_threads = True
    # much faster rebinding
    allow_reuse_address = True

    def __init__(self, server_address, RequestHandlerClass):
        SocketServer.TCPServer.__init__(\
        self,\
        server_address,\
        RequestHandlerClass)

############################################################################

if __name__ == "__main__":
    server = Server((HOST, PORT), TCPConnectionHandler)
    # terminate with Ctrl-C
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        sys.exit(0)

############################################################################

Client.py

#!/usr/bin/python

import socket
import random

def client(string):
    HOST, PORT = 'localhost', 21212
    # SOCK_STREAM == a TCP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #sock.setblocking(0)  # optional non-blocking
    sock.connect((HOST, PORT))

    print "sending data => [%s]" % (string)

    sock.send(string)
    reply = sock.recv(16384)  # limit reply to 16K
    print "reply => \n [%s]" % (reply)
    sock.close()
    return reply

def main():
    client('Python Rocks')

if __name__ == "__main__":
    main()

Client side output (Execute ./Client.py)

$ ./Client.py
sending data => [Python Rocks]
reply =>
 [skcoR nohtyP]

Server side output:

 ./Server.py
SingleTCPHandler::handle()
handle(): Received data : data =>
[Python Rocks]
handle(): Sending reply [skcoR nohtyP]

Saturday, May 11, 2013

Python - Passing function itself (and its arguments) as an argument to another function

In this Python program, we are passing function itself as an argument to another function

#!/usr/bin/python

import traceback

def exec_function(function,success_msg,failure_msg,throw,*args):
    print "Function: [%s] , Arguments: [%s]" % (function.func_name,args)
    try:
        ret = function(*args)
        print success_msg
        return ret
    except Exception,ex:
        print failure_msg
        print "\nException : [%s]" % (ex)
        print "\n%s" % (traceback.format_exc())
        if throw:
            raise Exception("%s" % (failure_msg))

def add1(a,b,c):
    return (a+b+c)

def add2(a,b):
    return (a+b)

def divide(a,b):
    return (a/b)

def add_multiply(a,b):
    return ((a+b) , (a*b))

def main():
    r1 = exec_function(add1,"Successfully Added !", "Addition Failed", False, 1,2,3)
    print "r1 => %s" % (r1)

    print "----"

    r2 = exec_function(add2,"Successfully Added !", "Addition Failed", False, 10,20)
    print "r2 => %s" % (r2)

    print "----"

    r3 = exec_function(divide, "Division Successful", "Division Failed", False, 4, 0)
    print "r3 => %s" % (r3)

    print "----"

    r4 = exec_function(add_multiply, "Add & Multiply Successful", "Add & Mutiply Failed !", False, 5,6)
    (result_add, result_multiply) = r4
    print "result_add => %s, result_multiply => %s" % (result_add, result_multiply)

    print "----\n"

if __name__ == "__main__":
    main()

Output:

$ ./test.py 
Function: [add1] , Arguments: [(1, 2, 3)]
Successfully Added !
r1 => 6
----
Function: [add2] , Arguments: [(10, 20)]
Successfully Added !
r2 => 30
----
Function: [divide] , Arguments: [(4, 0)]
Division Failed

Exception : [integer division or modulo by zero]

Traceback (most recent call last):
  File "./PYTHON-Stuff-Tips-and-Tricks.py", line 8, in exec_function
    ret = function(*args)
  File "./PYTHON-Stuff-Tips-and-Tricks.py", line 25, in divide
    return (a/b)
ZeroDivisionError: integer division or modulo by zero

r3 => None
----
Function: [add_multiply] , Arguments: [(5, 6)]
Add & Multiply Successful
result_add => 11, result_multiply => 30
----

Wednesday, May 8, 2013

Automatic Remote Desktop Re-connect in Linux

Here is a small shell script using which we can re-connect the remote desktop session, in case it dies for some reason

As long as the script below is running, the RDP will re-connect back

Typically, we issue the following command to do a remote desktop:

rdesktop -u <username> -p <password> -g <widthPixels x heightPixels> -x <bandwidth/type-of-network> -a <bit-depth> <server-ip>

In the below example, I have set my password in ~/.bashrc (or ~/.bash_profile) by inserting the following line at the end of the file:

export pass="myRemoteDesktopPassword"

Script: "establish_rdp"

Make sure you do chmod 755 establish_rdp and then to run ./establish_rdp to run

#!/bin/bash

#####################################################
#
# Author:
#    Giridhar Bhujanga : giridharmb@gmail.com
#
#####################################################

file="/tmp/__rdppdip.file__"
log_file="/tmp/__rdp__.log"
one_megabyte="1048576"

> $log_file

function get_logfile_size()
{
    size=$(du -s -B 1 $log_file|awk '{print $1}')
    echo $size
}

function rdp_cmd_exec()
{
    nohup rdesktop -u admin -p $pass -g 1900x1035 -x l -a 16 10.0.0.35 >/dev/null 2>&1 &
}

function my_log()
{
    echo "$1" >> $log_file 2>&1
}

function infinite_loop()
{
    for((;;))
    do
        curr_pid=`cat $file`
        ps -p $curr_pid > /dev/null 2>&1
        if [ "$?" = "0" ]; then
            my_log "PID $curr_pid is actually running ! Will (not) re-establish the RDP connection..."
        else
            rdp_cmd_exec
            echo "$!" > $file
        fi
        lfs=$(get_logfile_size)
        my_log "log-file-size: $lfs"
        if [ $lfs -ge $one_megabyte ]; then
            > $log_file
            my_log "Log file was greater than 1MB, so emptied it..."
        fi
        sleep 1
    done
}

curr_pid=`cat $file`

ps -p $curr_pid > /dev/null 2>&1

if [ "$?" = "0" ]; then
    my_log "I think the RDP session is already established ! Not doing anything. Exiting..."
    infinite_loop
else
    my_log "RDP session is not alive ! So, now trying to start it..."
    rdp_cmd_exec
    pid="$!"
    echo "$pid" > $file
    infinite_loop
fi

exit 0

To see what is going on do this:

tail -f /tmp/__rdp__.log

Serialization / De-serialization by writing (/reading) to (/from) disk - in Python

Here is a small example of serializing and de-serializing data using pickle module

In this example, we serialize data and write to disk and then again read it back from the disk and then de-serialize it

#!/usr/bin/python

import cPickle

array_file = "test_array.dat"
dict_file = "test_dict.dat"

def write_obj_to_disk(obj, pickle_file):
    cPickle.dump(obj, open(pickle_file, 'wb'))

def read_obj_from_disk(pickle_file):
    obj = cPickle.load(open(pickle_file, 'rb'))
    return obj


def write_stuff():
    print "write_stuff():"
    my_dict = {}
    my_dict["a"] = "linux"
    my_dict["b"] = "rocks"
    print my_dict
    write_obj_to_disk(my_dict, dict_file)
    print "done writing dictionary..."

    my_array = [1,2,3,4,5]
    print my_array
    write_obj_to_disk(my_array, array_file)
    print "done writing list..."

def read_stuff():
    print "read_stuff()"
    new_list = list(read_obj_from_disk(array_file))
    new_dict = dict(read_obj_from_disk(dict_file))
    return new_list, new_dict

def main():
    print "\n @ Now writing to disk ...\n"
    write_stuff()
    print "\n @ Done writing...\n"
    print "\n @ Now reading from disk ...\n"
    my_list, my_dict = read_stuff()
    print "\n @ Done reading...\n"

    print "---\n main(): After reading data from the files: \n---"
    print "my_list:"
    print my_list
    print "my_dict:"
    print my_dict

if __name__ == "__main__":
    main()

Output:

$ ./read-write.py 

 @ Now writing to disk ...

write_stuff():
{'a': 'linux', 'b': 'rocks'}
done writing dictionary...
[1, 2, 3, 4, 5]
done writing list...

 @ Done writing...


 @ Now reading from disk ...

read_stuff()

 @ Done reading...

---
 main(): After reading data from the files: 
---
my_list:
[1, 2, 3, 4, 5]
my_dict:
{'a': 'linux', 'b': 'rocks'}

Python - Simple Exception Handling (throw/catch)

Here is one of the ways to catch and again throw exceptions

#!/usr/bin/python

import sys
import traceback

def a():
    arr = []
    try:
        arr.insert(0, 'a')
        arr.insert(1, 'b')
        arr.insert(x, 'b') # ERROR here !
        
    except Exception,ex:
        print "Error (1) : %s" %(sys.exc_info()[0])
        print "Exception Msg (1): %s" % str(ex)
        print "Traceback (1): \n-->>\n%s<<--" % (traceback.format_exc())
        raise Exception("## RAISE (1): With Message ## ")
    finally:
        print "a(): finally block"

def b():
    try:
        a()
    except Exception,ex:
        print "Error (2) : Called a() , Got Error !"
        print "Msg(2) : %s" % sys.exc_info()[0]
        print "Exception Msg (2): %s" % str(ex)
        print "Traceback (2): \n-->>\n%s<<--" % (traceback.format_exc())

def main():
    print " $$ Before calling b() "
    b()
    print " $$ After calling b()"

if __name__ == "__main__":
    main()

Output:

$ ./test.py
 $$ Before calling b()
Error (1) : <type 'exceptions.NameError'>
Exception Msg (1): global name 'x' is not defined
Traceback (1):
-->>
Traceback (most recent call last):
  File "./test.py", line 11, in a
    arr.insert(x, 'b') # ERROR here !
NameError: global name 'x' is not defined
<<--
a(): finally block
Error (2) : Called a() , Got Error !
Msg(2) : <type 'exceptions.Exception'>
Exception Msg (2): ## RAISE (1): With Message ##
Traceback (2):
-->>
Traceback (most recent call last):
  File "./test.py", line 23, in b
    a()
  File "./test.py", line 17, in a
    raise Exception("## RAISE (1): With Message ## ")
Exception: ## RAISE (1): With Message ##
<<--
 $$ After calling b()

Sunday, May 5, 2013

Remove the delay in Apple Dock (Show/Hide)

To remove the delay, open Terminal, type or copy and paste the following line and hit return:

defaults write com.apple.Dock autohide-delay -float 0 && killall Dock

To restore the default behavior, enter:

defaults delete com.apple.Dock autohide-delay && killall Dock

Execute a shell command in case a file changes

Here is a small shell script - using which we can execute a shell command in case the file which we are monitoring changes

Usage:

file_changed.sh hello.txt "scp hello.txt root@10.0.37.1:/root"

file_changed.sh : Shell script below

hello.txt : File that we are monitoring (for any changes)

"scp hello.txt root@10.0.37.1:/root" : Command to execute in case the file that we are monitoring changes

File : file_changed.sh(For MacOSX)

#!/bin/bash

rand=$(echo $RANDOM)

tmp_md5sum_file=/tmp/$rand

> $tmp_md5sum_file

# filename to monitor
actual_file="$1"

# command to execute in case the file changes
command_to_exec="$2"

echo "File to monitor : [$1]"
echo "Command to execute if file changes: [$2]"

for((;;))
do
 cat $tmp_md5sum_file|grep "MD5"
 # in case we have already captured the MD5 of the file to monitor
 if [ "$?" = "0" ];then
  # current md5sum of the file
  new_md5=$(md5 $actual_file|grep "MD5"|cut -d '=' -f2|tr -d ' ')
  # old md5sum of the file (previously captured in the tmp file)
  old_md5=$(cat $tmp_md5sum_file|grep "MD5"|cut -d '=' -f2|tr -d ' ')
  # if the old and new md5 are same, don't do anything
  if [ "$new_md5" = "$old_md5" ];then
   echo "file not changed.."
  else
   # in case the md5 has changed, execute the command and
   # capture the new md5sum to the tmp file (save it)
   echo "file changed !"
   $command_to_exec
   md5 $actual_file > $tmp_md5sum_file
  fi
 else
  md5 $actual_file > $tmp_md5sum_file
 fi
 sleep 1
done

File : file_changed.sh(For Linux)

#!/bin/bash

rand=$(echo $RANDOM)

tmp_md5sum_file=/tmp/$rand

> $tmp_md5sum_file

# filename to monitor
actual_file="$1"

# command to execute in case the file changes
command_to_exec="$2"

echo "File to monitor : [$1]"
echo "Command to execute if file changes: [$2]"

for((;;))
do
 cat $tmp_md5sum_file|grep "$1"
 # in case we have already captured the MD5 of the file to monitor
 if [ "$?" = "0" ];then
  # current md5sum of the file
  new_md5=$(md5sum $actual_file|awk '{print $1}'|tr -d ' ')
  # old md5sum of the file (previously captured in the tmp file)
  old_md5=$(cat $tmp_md5sum_file|awk '{print $1}'|tr -d ' ')
  # if the old and new md5 are same, don't do anything
  if [ "$new_md5" = "$old_md5" ];then
   echo "file not changed.."
  else
   # in case the md5 has changed, execute the command and
   # capture the new md5sum to the tmp file (save it)
   echo "file changed !"
   $command_to_exec
   md5sum $actual_file > $tmp_md5sum_file
  fi
 else
  md5sum $actual_file > $tmp_md5sum_file
 fi
 sleep 1
done

How to mount a remote directory locally via SSH

Mounting a remote directory - locally via SSH protocol

Assume you have a directory /home/patrick/data on 192.168.1.100

You have a local directory /home/kate/remote-mounted-dir


How do you access all the files under /home/patrick/data on 192.168.1.100 locally ?

Answer : Pretty Simple ! Use SSHFS command for that ! Run this command locally on your machine:

sshfs patrick@192.168.1.100:/home/patrick/data /home/kate/remote-mounted-dir

How to restore "normal" scroll bars in Ubuntu

$ gsettings set com.canonical.desktop.interface scrollbar-mode normal
$ gconftool-2 --set /apps/metacity/general/button_layout --type string menu:minimize,maximize,close

How to install AMD/ATI Drivers in Linux

sudo apt-get install build-essential cdbs dh-make dkms execstack dh-modaliases linux-headers-generic fakeroot
sudo apt-get install lib32gcc1
sudo apt-get install linux-source fglrx fglrx-amdcccle
wget http://www2.ati.com/drivers/linux/amd-driver-installer-catalyst-13.1-linux-x86.x86_64.zip
unzip amd-driver-installer-catalyst-13.1-linux-x86.x86_64.zip
chmod +x amd-driver-installer-catalyst-13.1-linux-x86.x86_64.run
sudo sh ./amd-driver-installer-catalyst-13.1-linux-x86.x86_64.run --buildpkg Ubuntu/quantal
sudo dpkg -i fglrx*.deb

How to reset Unity in Ubuntu - in case it got screwed up

For Unity If SomeThing Went Wrong Enter following commands to Reset

# apt-get install dconf-tools
# dconf reset -f /org/compiz/ 
# setsid unity
# git clone https://github.com/phanimahesh/unity-revamp.git
# cd unity-revamp
# chmod +x unity-reset.py
# ln -s ./unity-reset.py /usr/bin/unity-reset

Then run in terminal:

# unity-reset
# gconftool-2 --recursive-unset /apps/compiz-1 unity --reset

How to burn ISO to a CD-R/W using command line in Linux

# cdrecord -scanbus

Output:

Cdrecord-Clone 2.01a34 (i686-pc-linux-gnu)
Copyright (C) 1995-2004 Jrg Schilling
scsidev: 'ATA:'
devname: 'ATA'
scsibus: -1 target: -1 lun: -1
Warning: Using badly designed ATAPI via /dev/hd*
interface.
Linux sg driver version: 3.5.27
Using libscg version 'schily-0.8'.
scsibus1:
1,0,0 100) 'SONY' 'CD-Writer' '1.0g'
1,1,0 101) *
1,2,0 102) *
1,3,0 103) *
1,4,0 104) *
1,5,0 105) *
1,6,0 106) *
1.7.0 107) *

In above example, my device name is 1,0,0. Now again use the cdrecord command to burn ISO image:

# cdrecord -v -dao dev=1,0,0 file.iso

You can also specify burning speed:

# cdrecord -v -dao dev=1,0,0 speed=8 file.iso

SSH tips

Here are some tips for SSH logins

This works on the network setup that we have :)

How to generate user's Public Key ?

RSA key:

ssh-keygen -t rsa

Problem: User's ssh directory and files inside it does not have right permissions

Solution:Run this command from where-ever you want (inside your home directory)

mkdir -p ~/.ssh; touch ~/.ssh/id_rsa ; touch ~/.ssh/id_rsa.pub ; touch ~/.ssh/authorized_keys ; touch ~/.ssh/known_hosts
chmod 700 ~/.ssh ; chmod 600 ~/.ssh/id_rsa ; chmod 644 ~/.ssh/id_rsa.pub ; chmod 644 ~/.ssh/authorized_keys ; chmod 644 ~/.ssh/known_hosts

Problem: SSH takes too long to login

Solution:Run this command as "root", only once on the remote SSH server"

sed -i 's/#UseDNS\ yes/UseDNS\ no/' /etc/ssh/sshd_config;sed -i 's/GSSAPIAuthentication\ yes/GSSAPIAuthentication\ no/' /etc/ssh/sshd_config;service sshd restart

Problem: Cannot SSH to the server as "root"

Solution:Run this command as "root", only once on the remote SSH server

sed -i 's/PermitRootLogin no/PermitRootLogin yes'/g /etc/ssh/sshd_config; sudo service sshd restart

Another easy way to SSH without a password !

Assume you are logged in as user "kate" on 192.168.0.10

Now assume you would want to ssh to 192.168.0.123 as user "patrick"

Command you issue to SSH (from kate@192.168.0.10) is:

ssh patrick@192.168.0.123

Now if you want to SSH to 192.168.0.123 as "patrick" without being asked for password, all you have to do is run this command once (when logged in as "kate" on 192.168.0.10)

ssh-copy-id patrick@192.168.0.123

After you run that once, it will not ask you for password the next time you issue this command ssh patrick@192.168.0.123

Automatic VPN Connection

For MacOSX Only

Here is a sample Apple Script - that automatically reconnects the VPN in case of a disconnection

In this example, the name of the VPN connection is "My-VPN"

Create this script in Apple Script editor & export it as application. Make sure you choose "Stay Open" option while exporting the apple script as application

After that, you can run this exported application. Also, you may want to add this application in the list of "start up items" when the user logs is, so that VPN is "always on"

on idle
 tell application "System Events"
  tell current location of network preferences
   set myConnection to the service "My-VPN"
   if myConnection is not null then
    if current configuration of myConnection is not connected then
     connect myConnection
    end if
   end if
  end tell
  return 120
 end tell
end idle

File - [/etc/ppp/ip-up] : Sets up routing after the VPN connects (this is optional - you may or may not need it)

#!/bin/bash
/sbin/route add -net 10.0.0.0/8 10.0.254.37