Tuesday 25 February 2014

aws python api with boto note1

* How to install boto:
1. Need python.
2. download boto [ https://github.com/boto/boto/downloads/ ]
3. Install boto:
2a. tar xfz boto-2.1.tar.gz
2b. cd boto-2.1
2c. sudo python setup.py install

other way:
1. sudo apt-get install python-setuptools
2. sudo easy_install boto

NOTE: Some time few of the boto function don't work, e:g: boto 1.9 don't have instance.tags support, in that case you have to update the boto.

How to update boto: [ I am using easy_install: part of "python-setuptools: "
easy_install -U boto

To see your current boto version:
$python
>>> import boto
>>> boto.Version
'2.27.0'



example of setting the /etc/boto.cfg file:

[Credentials]
aws_access_key_id = ABCDEFGHIJK
aws_secret_access_key = ABCDEFASDFAS123ASF123


########### Example #########
import boto.ec2

# NOTE: if you don't put the key at conn then it will search for
# your profile file, if not /etc/boto.cfg if not your varible 'BOTO_CONFIG=/file/path'

conn=boto.ec2.connect_to_region('us-east-1')
#conn=boto.ec2.connect_to_region('us-east-1',aws_access_key_id='access_key' , aws_secret_access_key='secret_key')

# Following is the prod key: [ Full access ]
#AWS_ACCESS_KEY_ID = 'access_key'
#AWS_SECRET_ACCESS_KEY = 'secret_key'


reservations = conn.get_all_instances()
for res in reservations:
    for inst in res.instances:
            print "%s " % (inst.tags['Name'])
            print "%s  %s " % ("publicDnsName:", inst.public_dns_name)
            print "%s  %s " % ("internalDnsName:", inst.private_dns_name)
            print "%s  %s " % ("publicIP:", inst.ip_address)
            print "%s  %s " % ("internalIP:", inst.private_ip_address)
            print "%s  %s " % ("architecture:", inst.architecture)
            print "%s  %s " % ("image_id:", inst.image_id)
            print "%s    %s " % ("instance_type", inst.instance_type)
            print ""


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

$ to see help with in boto:
>>>help(boto)

>>> dir(boto)
['BUCKET_NAME_RE', 'BotoConfigLocations', 'BucketStorageUri', 'Config', 'ENDPOINTS_PATH', 'FileStorageUri', 'GENERATION_RE', 'InvalidUriError', 'NullHandler', 'TOO_LONG_DNS_NAME_COMP', 'UserAgent', 'VERSION_RE', 'Version', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', 'auth', 'auth_handler', 'boto', 'cacerts', 'compat', 'config', 'connect_autoscale', 'connect_beanstalk', 'connect_cloudformation', 'connect_cloudfront', 'connect_cloudsearch', 'connect_cloudtrail', 'connect_cloudwatch', 'connect_directconnect', 'connect_dynamodb', 'connect_ec2', 'connect_ec2_endpoint', 'connect_elastictranscoder', 'connect_elb', 'connect_emr', 'connect_euca', 'connect_fps', 'connect_glacier', 'connect_gs', 'connect_ia', 'connect_iam', 'connect_kinesis', 'connect_mturk', 'connect_opsworks', 'connect_rds', 'connect_rds2', 'connect_redshift', 'connect_route53', 'connect_s3', 'connect_sdb', 'connect_ses', 'connect_sns', 'connect_sqs', 'connect_sts', 'connect_support', 'connect_swf', 'connect_vpc', 'connect_walrus', 'connection', 'datetime', 'ec2', 'exception', 'gs', 'handler', 'https_connection', 'init_logging', 'log', 'logging', 'os', 'perflog', 'platform', 'plugin', 'provider', 'pyami', 're', 'regioninfo', 'resultset', 's3', 'set_file_logger', 'set_stream_logger', 'storage_uri', 'storage_uri_for_key', 'sys', 'urlparse', 'utils']

>>> dir(boto.connect_ec2)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

>>> dir(boto.connect_ec2.__get__)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__name__', '__new__', '__objclass__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

>>> dir(boto.ec2)
['EC2Connection', 'RegionData', 'RegionInfo', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'address', 'attributes', 'blockdevicemapping', 'bundleinstance', 'connect_to_region', 'connection', 'ec2object', 'get_region', 'get_regions', 'group', 'image', 'instance', 'instanceinfo', 'instancestatus', 'instancetype', 'keypair', 'launchspecification', 'load_regions', 'networkinterface', 'placementgroup', 'regioninfo', 'regions', 'reservedinstance', 'securitygroup', 'snapshot', 'spotdatafeedsubscription', 'spotinstancerequest', 'spotpricehistory', 'tag', 'volume', 'volumestatus', 'zone']

>>> dir(boto.ec2.connect_to_region)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']


* Installing easy_install to install rest of the python package.
1.  sudo apt-get install python-setuptools
2. sudo easy_install paramiko [ ssh2 like tool. ]
3. sudo apt-get install -y euca2ools [ same as aws command line tools. ]

* aws credentials for boto:
1. at the code itself:  [example: ]
>>> import boto
>>> ec2 = boto.connect_ec2(aws_access_key_id='my_access_key',
aws_secret_access_key='my_secret_key')

2. at the system variable: as:
~/.bashrc:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY

3. Boto configuration files:
3a. ~/.boto
3b. /etc/boto.cfg
3c. set the varible 'BOTO_CONFIG=/file/path'
with following format:
[Credentials]
aws_access_key_id = your_access_key
aws_secret_access_key = your_secret_key

##### to test the above settings: ######
##### the /etc/boto.cfg file should have the read access for the Credentials ]
>>> import boto
>>> ec2 = boto.connect_ec2()
>>> ec2.get_all_zones()
[Zone:us-east-1a, Zone:us-east-1b, Zone:us-east-1c, Zone:us-east-1d, Zone:us-east-1e]

>>> ec3 = boto.connect_ec2()
>>> ec3.get_all_zones()
[Zone:us-east-1a, Zone:us-east-1b, Zone:us-east-1c, Zone:us-east-1d, Zone:us-east-1e]

>>> boto.ec2.regions()
[RegionInfo:eu-west-1, RegionInfo:sa-east-1, RegionInfo:us-east-1, RegionInfo:ap-northeast-1, RegionInfo:us-west-2, RegionInfo:us-west-1, RegionInfo:ap-southeast-1, RegionInfo:ap-southeast-2]

default region for boto is "us-east-1"


If you want to connect to a different regions, then:
import boto.ec2
ec_conn = boto.ec2.connect_to_region('eu-west-1')
>>> ec_conn.get_all_zones()
[Zone:eu-west-1a, Zone:eu-west-1b, Zone:eu-west-1c]

NOTE: If you want by default to connect to some other region then you can update your boto config file as:
[Boto]
ec2_region_name = eu-west-1


Q) If I have multiple aws account, then ?:
I can think of set the variable BOTO_CONFIG = /path/to/file/account1 [ on boto scripts. ]


############
[1] Following is one of the python code to get few of the param of the instances:

import boto.ec2
conn=boto.ec2.connect_to_region('us-east-1', aws_access_key_id='<access_key>', aws_secret_access_key='<secret key>')
reservations = conn.get_all_instances()
for res in reservations:
    for inst in res.instances:
        if 'Name' in inst.tags:

            print "%s (%s) [%s]" % (inst.tags['Name'], inst.id, inst.state)
        else:
            print "%s [%s]" % (inst.id, inst.state)



[2] In following example, the script is accessing the variable details from the profile file to get the access and the secret key:

import boto.ec2
conn=boto.ec2.connect_to_region("us-east-1")
reservations = conn.get_all_instances()
for res in reservations:
    for inst in res.instances:
        if 'Name' in inst.tags:

            print "%s (%s) [%s]" % (inst.tags['Name'], inst.id, inst.state)
        else:
            print "%s [%s]" % (inst.id, inst.state)



Thursday 20 February 2014

monitoring

Some monitoring software:  [ Need to update the following topics: ]

Sensu

Graphite

Flapjack

Statsd

Logstash

cacti

ganglia

zabbix

munin

Zenoss


explain-brace-expansion-in-cp-mv-bash-shell-commands


$ touch {1..10}.txt

$ ls
10.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt

## The following command will rename fileName.txt to fileName.bak

$ for i in {1..10};do mv $i.{txt,bak}; done 

$ ls
10.bak  1.bak  2.bak  3.bak  4.bak  5.bak  6.bak  7.bak  8.bak  9.bak




$ man bash

NOTE:

Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to filename expansion, but the file names generated need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a seqeunce expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.


Ref Link:

http://www.cyberciti.biz/faq/explain-brace-expansion-in-cp-mv-bash-shell-commands/

How to: http://www.cyberciti.biz/faq/

Friday 14 February 2014

Artifactory Repository Notes

Url link on how to install Artifactory:

1. Downloaded the binary file from sourceforge:
 $ wget http://sourceforge.net/projects/artifactory/files/latest/download

2. Rename the file [ It will be named as download ]
$ mv download artifactory-3.1.1.zip

3. For my use I moved the same file to /opt dir.
$ sudo mv artifactory-3.1.1.zip /opt

4. Extracted the zip file
$ unzip artifactory-3.1.1.zip

Documentation I am following as of now:

http://www.jfrog.com/confluence/display/RTF/Installing+on+Linux+Solaris+or+Mac+OS

http://www.jfrog.com/confluence/display/RTF/Installing+on+Linux+Solaris+or+Mac+OS#InstallingonLinuxSolarisorMacOS-ManualInstallation










*) What you need: 

NOTE: You need to hava java 1.7. So if you don't have the java 1.7, download the jre tar file from oracle site [ We prefer to have oracle java then openjava. ]. Need not to have JDK. JRE should be enough.

*) lets say you don't have java1.7: on that case:

5a. Download the jar1.7 from oracle site.
5b. I have extracted the same at /opt/ [ you can do at your wish. ]


6a. Go to your the artifactory extracted path [ example /opt/artifactory-3.1.1 for me] then "bin" dir and run "sudo sh installService.sh" ... This will install the artifactory as a service... so that you can use... sudo service artifactory {start|stop}

6b. After the above command: [ do the following: NOTE: if you don't have JAVA1.7 only. ]
sudo vi /etc/opt/jfrog/artifactory/deault

and update the JAVA_HOME [ For me as per the example: export JAVA_HOME=/opt/jre1.7.0 ]

Then you can do: sudo service artifactory start.

Do a netstat: and you can do a quick check on what port your artifactory is running. 

For me it started on port 8081 [ Make sure you don't have any firewall blocking that port.]

http://localhost:8081/artifactory   <--- here you have your artifactory running.



log in to artifactory at the above url: default login [ admin / password ]


Default log location: [ tail -f $ARTIFACTORY_HOME/logs/artifactory.log ]



*) How do I configure rest at artifactory:

URL: http://www.jfrog.com/confluence/display/RTF/Administering+Artifactory

7a. Once you login to the artifactory UI page, you can select "ADMIN" tab to configure rest of the conigurations.



parallel-scp


parallel-scp:

NOTE: you might consider doing: dos2unix <filename> to convert the file from windows/mac developer to unix format, before hosting the file into the unix servers.


[ you need install pssh for parallel-scp ]

$ parallel-scp -h <FileWithServersList> -x "-i key -P port" -l ubuntu path_to_source_file  <remote_path/[file_name]>



example:

$ parallel-scp -r -h List_of_server.txt -x "-i server_private_key -P ssh_port" -l username /home/amitmund/source_file /absolute/path/for/remote/file



example script:


#!/bin/bash

echo" This command will take the following inputs and run the parallel scp command"

read -p "Please enter the host file where you have all the host: " HostsFile
read -p "Please enter the key details: " AwsKey
read -p "Please enter the source_file_path: " source_file
read -p "please enter the remote_path_where_to_scp: " remote_path

/usr/bin/parallel-scp -r -h $HostsFile -x "-i $AwsKey -P PORT" -l ubuntu ${source_file} ${remote_path}


parallel-ssh



parallel-ssh:

[ you need install pssh for parallel-ssh ]

Following are few of the features:

1. In the following command you are passing user@host:port and the ssh option after -x "for example the ssh key" and later the command. It will run the command on the remote system and put the output on the screen:

$ parallel-ssh -i -H "user@server:port" -x "-i key" "command"

Following is the command example if you have to pass the key, port and user parameter:
 
$ parallel-ssh -i -h <FileWithServersList> -x "-i key -p port" -l ubuntu "command"


Run a long command without timing out:
              pssh -i -h hosts.txt -t 0 sleep 10000



parallel-ssh --help
Usage: parallel-ssh [OPTIONS] command [...]

Options:
  --help                show this help message and exit
  -h HOST_FILE, --hosts=HOST_FILE
                        hosts file (each line "[user@]host[:port]")
  -H HOST_STRING, --host=HOST_STRING
                        additional host entries ("[user@]host[:port]")
  -l USER, --user=USER  username (OPTIONAL)
  -p PAR, --par=PAR     max number of parallel threads (OPTIONAL)
  -o OUTDIR, --outdir=OUTDIR
                        output directory for stdout files (OPTIONAL)
  -e ERRDIR, --errdir=ERRDIR
                        output directory for stderr files (OPTIONAL)
  -t TIMEOUT, --timeout=TIMEOUT
                        timeout (secs) (0 = no timeout) per host (OPTIONAL)
  -O OPTION, --option=OPTION
                        SSH option (OPTIONAL)
  -v, --verbose         turn on warning and diagnostic messages (OPTIONAL)
  -A, --askpass         Ask for a password (OPTIONAL)
  -x ARGS, --extra-args=ARGS
                        Extra command-line arguments, with processing for

                        spaces, quotes, and backslashes
  -X ARG, --extra-arg=ARG
                        Extra command-line argument
  -i, --inline          inline aggregated output for each server 

  -I, --send-input      read from standard input and send as input to ssh
  -P, --print           print output as we get it

Example: pssh -h hosts.txt -l irb2 -o /tmp/foo uptime



For timeout issue think of trying the following options:



As per the --help option:


-t TIMEOUT, --timeout=TIMEOUT
                        timeout (secs) (0 = no timeout) per host (OPTIONAL)


-I, --send-input      read from standard input and send as input to ssh
 
$ cat command1 | parallel-ssh -o Out1 -h prod36AS -x "-i jvxadm-oper-keypair.pem -p 1717" -l ubuntu -I
 

-t 0

Can also try the following:

parallel-ssh -t -1 [ timeout disable options ]

parallel-ssh -t -1 -h servers list "command"

How about trying with the ssh -o options?:

parallel-ssh -i -h prod36AS -x "-o ConnectTimeout=10 -i key -p 1717" -l ubuntu "sleep 12"

 
 
example script:


#!/bin/bash

echo" This command will take the following inputs and run the parallel ssh command"

read -p "Please enter the host file where you have all the host: " HostsFile
read -p "Please enter the key details: " AwsKey
read -p "Please enter the command that you want to run on remote servers: " RemoteCommands

/usr/bin/parallel-ssh -i -h $HostsFile -x "-i $AwsKey -p PORT" -l ubuntu "$RemoteCommands"



You might need to use rsync for quick update along with the backup of the file:


/usr/bin/sudo /usr/bin/rsync -vvrlb --backup-dir=/mnt/rsync-backup/ /source/{dir|file} /dest/{dir|file}
 
So,
 
Along with parallel-ssh:
 
/usr/bin/parallel-ssh -i -h $HostFile -x "-i $AwsKey -p port" -l <user> " 
/usr/bin/sudo /usr/bin/rsync -vvrlb --backup-dir=/mnt/rsync-backup/ /source/{dir|file} /dest/{dir|file}"
 
Few rsync options details again:
 
-v : copy symlinks as symlinks
-r : copy symlinks as symlinks
-l : copy symlinks as symlinks
-b: make backups (see --suffix & --backup-dir)
            --backup-dir=DIR        make backups into hierarchy based in DIR
  
 
 Further help:
 
$ parallel-ssh --help
$ man parallel-ssh 

Sunday 9 February 2014

bash script with help options example

## Version 2:

#!/bin/bash

## Usage function declaration:

usage () {
  echo "Usage:"
  echo "Syntax: $0 [-s SOURCE_PATCH_DIR] [-d DESTINATION_DIR] -k PUBLIC_KEY -l FILE_HAVING_LIST_OF_SERVERS (-C Command_FIle OR -c \"COMMAND[;COMMAND2;COMMANDn])\"\n"
  echo "Options:"
  echo "-s: source patch folder"
  echo "-d: Destination directory where you want to copy the patch folder."
  echo "-k: Public key to access the remote hosts"
  echo "-l: File where we have hosts, with new line char."
  echo "NOTE: We except only one input command options either -C and filename or -c command(s)"
  echo "NOTE: If you provide both the command input options then we will take the last command input option's values"
  echo "-C: Path of the command file. Commands need to in new line"
  echo "-c: Input command(s) separated by \";\" on remote system(s) and MUST be inside a \"\"\n"
  echo "Example:"
  echo " sh $0 -k key.pem -l serverS.txt -C commandFile.txt"
  echo "$0 -s /home/ubuntu/Burg2/patch1 -d /mnt/PatchBackup/ -k /home/ubuntu/key.pem -l /home/ubuntu/serverList.txt -c \"uptime;hostname;ls -l | grep -i test\""
}



#Get the arguments passed
while getopts ":s:d:k:l:c:C:h:help" args; do
  case $args in
    h)
      usage;
      exit 0;
      ;;
    help)
      usage;
      exit 0;
      ;;
    s)
      SRC_FOLDER="${OPTARG}";;
    d)
        DES_FOLDER="${OPTARG}";;
    k)
      KEY_FILE="${OPTARG}";;
    l)
      SERVER_LIST="${OPTARG}";;
    C)
    CMD_FILE1="${OPTARG}";
    # The following sed command will remove the new line from the input file and update the command.
    # You can also try [ tr '\n' ';' ] ' But over here at the end you will see ; again '
    CMD_FILE=`sed ':a;N;$!ba;s/\n/;/g' ${CMD_FILE1}`;
    COMMAND=`echo ${CMD_FILE}`;;
    c)
        #COMMAND="${OPTARG}";;
        COMMAND1="${OPTARG}";
            # The following command will take multiple command with ; separated.
        COMMAND=`echo ${COMMAND1}|awk -F";" '{print $0}'`;;
       
    :)
      usage;
      exit 1;
      ;;
    ?)
      usage;
      exit 1;
      ;;
  esac
done


#if [ ! -e "${KEY_FILE}" && ! -f "${SERVER_LIST}" && -z "${COMMAND}" ]; then
#    echo "\n Error: Required input missing."
#    exit 1;
#fi

# Key file exists?
if [ ! -e "${KEY_FILE}" ]; then # [ -e FILE ]    True if FILE exists.
  echo "\nError: Key not found. Please provide absolute path of the key.\n";
  usage;
  exit 1;
fi

# server list exists?
if [ ! -f "${SERVER_LIST}" ]; then # [ -f FILE ]    True if FILE exists and is a regular file.
  echo "\nError: File not found. Please provide absolute path of the server_list files\n";
  usage;
  exit 1;
fi

# command provided?
if [ -z "${COMMAND}" ]; then # [ -z STRING ]    True of the length if "STRING" is zero.
  echo "\nError: Input command not found:\n";
  usage;
  exit 1;
 fi

## Executation of deployment.
for machine in `cat ${SERVER_LIST}`;
    do
      echo "\nStart: processing on  ${machine}...\n";
        if [ -d "${SRC_FOLDER}" ] ; then # [ -d FILE ]    True if FILE exists and is a directory.
            #echo "Source Folder: ${SRC_FOLDER}";
            ssh -pport -i ${KEY_FILE} ubuntu@${machine} "sudo mkdir -p ${DES_FOLDER}; sudo chown ubuntu:ubuntu ${DES_FOLDER}";
              scp -r -Pport -i ${KEY_FILE} ${SRC_FOLDER} ubuntu@${machine}:${DES_FOLDER};
        fi
      ssh -pport -i ${KEY_FILE} ubuntu@${machine} "${COMMAND}";
  done
  #ssh -pport -i ${KEY_FILE} ubuntu@${machine} "uptime";
# sudo rsync -vvrlb --backup-dir=/mnt/rsync-backup/patchNumber --exclude=README AbsolutePatchPath/* RemotePath/
  echo "\nFinished...";
  echo "";


-------------------------------------------------------------------------------------------



## Version 1:


#!/bin/bash

## Usage function declaration:

## Following is the usage functions
usage () {
  echo "Usage:"
  echo "Syntax: $0 -s SOURCE_PATCH_DIR -k PUBLIC_KEY -l FILE_HAVING_LIST_OF_SERVERS -c COMMAND[;COMMAND2;COMMANDn]\n"
  echo "Options:"
  echo "-s: source patch folder"
  echo "-k: Public key to access the remote hosts"
  echo "-l: File where we have hosts, with new line char."
  echo "-c: Input command(s) separated by \";\" on remote system(s)\n"
  echo "Example:"
  echo "$0 -s FILE_TO_COPY -k PATH_TO_PRIVATE_KEY -l FILE_HAVING_SERVER_NAME -c uptime;hostname;ls -l | grep -i test"
  echo "Above example will take the patch1 and use the private key and do the patch\
  on all the server that is listed on serverList.txt file and run all the provided command(s).\n"
}


#Get the arguments passed
# : for arg, Its good to have "h" and "help" at the end of the getopts options.
while getopts ":s:k:l:c:h:help" args; do
  case $args in
    h)
      usage;
      exit 0;
      ;;
    help)
      usage;
      exit 0;
      ;;
    s)
     ## Take the argument that is provided after -s with OPTARG
      SRC_FOLDER="${OPTARG}";;
    k)
      KEY_FILE="${OPTARG}";;
    l)
      SERVER_LIST="${OPTARG}";;
    c)
    COMMAND1="${OPTARG}";
# The following command will take multiple command with ; separated.
    COMMAND=`echo ${COMMAND1}|awk -F";" '{print $0}'`;;
   
    :)
      usage;
      exit 1;
      ;;
    ?)
      usage;
      exit 1;
      ;;
  esac
done



# Source folder has to be passed
if [ -z "${SRC_FOLDER}" ]; then # [ -z STRING ] True of the length if "STRING" is zero.
  echo "\nError: Source folder not found. Please provide absolute path of the source folder.\n";
  usage;
  exit 1;
fi

if [ ! -d "${SRC_FOLDER}" ] ; then # [ -d FILE ] True if FILE exists and is a directory.
  echo "\nError: Source need to be a valid folder.";
  usage;
  exit 1;
fi

# Key file exists?
if [ ! -e "${KEY_FILE}" ]; then # [ -e FILE ] True if FILE exists.
  echo "\nKey not found. Please provide absolute path of the key.\n";
  usage;
  exit 1;
fi

# server list exists?
if [ ! -f "${SERVER_LIST}" ]; then # [ -f FILE ] True if FILE exists and is a regular file.
  echo "\nFile not found. Please provide absolute path of the server_list files\n";
  usage;
  exit 1;
fi

# command provided?
if [ -z "${COMMAND}" ]; then # [ -z STRING ] True of the length if "STRING" is zero.
  echo "\nInput command not found:\n";
  usage;
  exit 1;
 fi

## Displaying the current values.
echo "Source Folder: ${SRC_FOLDER}";
echo "Key File: ${KEY_FILE}";
echo "Server list file: ${SERVER_LIST}";
echo "Command: ${COMMAND}";


## Executation of deployment.
for machine in `cat ${SERVER_LIST}`;
do
 echo "Start: Patch deployment on  ${machine}...";
  ssh -pPORT -i ${KEY_FILE} user@${machine} "${COMMAND}";
  done
#ssh -pPORT -i ${KEY_FILE} user@${machine} "uptime";
# sudo rsync -vvrlb --backup-dir=/mnt/rsync-backup/patchNumber --exclude=README AbsolutePatchPath/* RemotePath/
  echo "Finished.";
  echo "";