For those who are impatient we request you not to miss the last few paragraphs of this post. For those who are not impatient we want to assure you that we take your time seriously, we highly value your patronage, we want to inform you that we come from the stables of writing highly optimized code, we request you to enjoy every line as each one had to pass our quality scrutiny and the words used are the choicest.
In this post I want to talk about the fun we have been having with bash scripting. If you had been noticing the first few lines in the previous scripts, we are "including" or "sourcing" the main utility script file "include.sh" files from "scripts/include" directory. Just want to mention that these utility script files present in include directory are part of the zip file that we made available to you in our previous post. We shall see the contents of that file and discuss it.
Earlier we used to have "# set -x" in the beginning of every script file. When we wanted to debug the script file we used to open the file and uncomment the line (by deleting the "#" character). Then in the Internet I found a superior solution to enable debugging without editing the script file. The solution was something like
[[ $DEBUG -gt 0 ]] && set -x
It was turning ON the debug for all the scripts executed by the current script resulting in large amount of output. Then I gave it my little touch to control the amount of debug information.
[[ $DEBUG -gt 0 ]] && set -x; export DEBUG=$(($DEBUG - 1))
Here is the source code of "include.sh".
Just by having one line "source include.sh", we wanted all the utility functions to become available. Coming from C/C++ background "include" was a natural choice. This file has only one but a very interesting function getCurScriptPath. I obtained the code from the Internet and modified it. Interesting thing about getCurScriptPath is whether the script is executed from its directory or any other directory or by a softlink to it and located anywhere in the system and finally even if the script is executed because of the PATH environment variable, this function can correctly identify the directory in which the script is located. Once identified the script expects other utility script files such as bash-util, string-util, etc and "includes" them.
string-util.sh currently provides Pad and Trim functions. We intend to keep collecting many more utility string functions as and when the need arises so that at some point this file contains all the useful string functions similar to String class of Java, CString class of Microsoft Foundation Classes (MFC) or String class of C++ Standard Template Library (STL).
Similarly bash_util.sh provides several utility functions needed by other scripts. The idea is to keep enhancing this script file with more and more utility functions so that just by opening this file one could get introduced to various powerful linux commands and their usage.
If you execute "source include.sh" from your shell prompt then all these functions become available in your shell. Then for example you could type and execute "getIPOfURL hudku.com" to get the IP address for an URL. This is just a tip on making use of these useful functions instead of typing a lengthy line containing piped list of commands.
In our scripts you would find that we are using two forms of bash "if" statement.
1. if [ $? -ne 0 ]; then
2. if ([ $? -ne 0 ]) then
That's because I first learnt the syntax listed first. Coming from C/C++/Java and C# trying to put the semicolon in the middle of a statement instead of at the end felt like I was about to commit a debauchery. Grit my teeth and carried on with my work until I stumbled upon the second syntax. It was like a god send, with those opening and closing parenthesis, looked a lot closer to the syntax of the languages I am familiar with and was relieved to know that the same syntax could be used in while & for loops also. Hell with sticking it in the middle. I mean sticking "semicolon" in the middle.
Also instead of using the grave accent character ` (the character below the ~ (tilde) to the left of "1" key on keyboard) we prefer to use $(). For example
echo It is now `date`
echo It is now $(date)
We found the second form more readable and can be used wherever the first form is used.
Alright. Now we are ready to start with the Amazon Elastic Beanstalk automation starting from its configuration files.
But few thoughts have been pressurizing me to be laid out as a blog post before I continue the journey with AWS Elastic Beanstalk. These thoughts are struggling to gush out and begging me to bring them into existence. Instead of getting pestered by them continuously, I decided to heed to their requests and allow them to prove their worthiness which they are claiming to be capable of. As those thoughts belong to a different topic I felt it might help to spice up the blog site by providing variety.
Hence my next post is going to be on a topic from database / RDBMS, another favourite subject of mine and I have been its student since 1989. The thoughts on this topic seem to have got really excited with my decision, are brimming with confidence that they would make one cracker of a blog post and they believe that they could be shocking to the readers as they want to strike at the base of a commonly and widely held belief / practice in the database world.
I definitely do not recommend it for the faint hearted. I just want to ensure that those thoughts get aligned properly in my next blog post without tripping over each other due to their enthusiasm.
Please stay tuned.
Presenting the source code of string-util.sh and bash-util.sh
In this post I want to talk about the fun we have been having with bash scripting. If you had been noticing the first few lines in the previous scripts, we are "including" or "sourcing" the main utility script file "include.sh" files from "scripts/include" directory. Just want to mention that these utility script files present in include directory are part of the zip file that we made available to you in our previous post. We shall see the contents of that file and discuss it.
Earlier we used to have "# set -x" in the beginning of every script file. When we wanted to debug the script file we used to open the file and uncomment the line (by deleting the "#" character). Then in the Internet I found a superior solution to enable debugging without editing the script file. The solution was something like
[[ $DEBUG -gt 0 ]] && set -x
It was turning ON the debug for all the scripts executed by the current script resulting in large amount of output. Then I gave it my little touch to control the amount of debug information.
[[ $DEBUG -gt 0 ]] && set -x; export DEBUG=$(($DEBUG - 1))
Here is the source code of "include.sh".
#!/bin/bash #set -x # # Includes all the utility functions. # Usage: include.sh # function getCurScriptPath() { local scriptPath pushd . > /dev/null scriptPath="${BASH_SOURCE[0]}"; # Handle if symbolic link is used if ([ -h "${scriptPath}" ]) then while ([ -h "${scriptPath}" ]) do cd $(dirname "$scriptPath") > /dev/null scriptPath=$(readlink "${scriptPath}") done fi cd $(dirname ${scriptPath}) > /dev/null scriptPath=$(pwd); popd > /dev/null echo $scriptPath } # Obtain the path of 'this' script file curScriptPath=$(getCurScriptPath) # Now include all the utility scripts source $curScriptPath/bash-util.sh source $curScriptPath/string-util.sh
Just by having one line "source include.sh", we wanted all the utility functions to become available. Coming from C/C++ background "include" was a natural choice. This file has only one but a very interesting function getCurScriptPath. I obtained the code from the Internet and modified it. Interesting thing about getCurScriptPath is whether the script is executed from its directory or any other directory or by a softlink to it and located anywhere in the system and finally even if the script is executed because of the PATH environment variable, this function can correctly identify the directory in which the script is located. Once identified the script expects other utility script files such as bash-util, string-util, etc and "includes" them.
string-util.sh currently provides Pad and Trim functions. We intend to keep collecting many more utility string functions as and when the need arises so that at some point this file contains all the useful string functions similar to String class of Java, CString class of Microsoft Foundation Classes (MFC) or String class of C++ Standard Template Library (STL).
Similarly bash_util.sh provides several utility functions needed by other scripts. The idea is to keep enhancing this script file with more and more utility functions so that just by opening this file one could get introduced to various powerful linux commands and their usage.
If you execute "source include.sh" from your shell prompt then all these functions become available in your shell. Then for example you could type and execute "getIPOfURL hudku.com" to get the IP address for an URL. This is just a tip on making use of these useful functions instead of typing a lengthy line containing piped list of commands.
In our scripts you would find that we are using two forms of bash "if" statement.
1. if [ $? -ne 0 ]; then
2. if ([ $? -ne 0 ]) then
That's because I first learnt the syntax listed first. Coming from C/C++/Java and C# trying to put the semicolon in the middle of a statement instead of at the end felt like I was about to commit a debauchery. Grit my teeth and carried on with my work until I stumbled upon the second syntax. It was like a god send, with those opening and closing parenthesis, looked a lot closer to the syntax of the languages I am familiar with and was relieved to know that the same syntax could be used in while & for loops also. Hell with sticking it in the middle. I mean sticking "semicolon" in the middle.
Also instead of using the grave accent character ` (the character below the ~ (tilde) to the left of "1" key on keyboard) we prefer to use $(). For example
echo It is now `date`
echo It is now $(date)
We found the second form more readable and can be used wherever the first form is used.
Alright. Now we are ready to start with the Amazon Elastic Beanstalk automation starting from its configuration files.
But few thoughts have been pressurizing me to be laid out as a blog post before I continue the journey with AWS Elastic Beanstalk. These thoughts are struggling to gush out and begging me to bring them into existence. Instead of getting pestered by them continuously, I decided to heed to their requests and allow them to prove their worthiness which they are claiming to be capable of. As those thoughts belong to a different topic I felt it might help to spice up the blog site by providing variety.
Hence my next post is going to be on a topic from database / RDBMS, another favourite subject of mine and I have been its student since 1989. The thoughts on this topic seem to have got really excited with my decision, are brimming with confidence that they would make one cracker of a blog post and they believe that they could be shocking to the readers as they want to strike at the base of a commonly and widely held belief / practice in the database world.
I definitely do not recommend it for the faint hearted. I just want to ensure that those thoughts get aligned properly in my next blog post without tripping over each other due to their enthusiasm.
Please stay tuned.
Presenting the source code of string-util.sh and bash-util.sh
#!/bin/bash #set -x # # Usage: source string-util.sh # # Usage: padLeft sInput padLength padChar function padLeft { local word="$1" while [ ${#word} -lt $2 ]; do word="$3$word"; done; echo "$word"; } # Usage: padRight sInput padLength padChar function padRight { local word="$1" while [ ${#word} -lt $2 ]; do word="$word$3"; done; echo "$word"; } # Usage: trimLeft sInput [charsToTrim] function trimLeft() { local sInput=$1 local charsToTrim=$2 local result if [ -z $charsToTrim ]; then charsToTrim=" \\t\\r\\n" fi result=$(echo -e $sInput | sed -e "s/^[$charsToTrim]*//") echo $result } # Usage: trimRight sInput [charsToTrim] function trimRight() { local sInput=$1 local charsToTrim=$2 local result if [ -z $charsToTrim ]; then charsToTrim=" \\t\\r\\n" fi result=$(echo -e $sInput | sed -e "s/[$charsToTrim]*$//") echo $result }
#!/bin/bash #set -x # # Usage: source bash-util.sh # # Usage: die Message function die() { local message message=$1 if [ -z "$message" ]; then msg="Error: Operation failed." fi echo -e "$message" exit 1 } # Usage: getFileOrDirCount Path-or-FileName # Description: bash -f or -e fail if wildcard is used in the name and it results in more than one entry # See Also: exists function getFileOrDirCount() { local count count=$(ls -1 $1 2> /dev/null | wc -l) echo $count } # Usage: exists Path-or-FileName # See Also: getFileOrDirCount function exists() { [ $(getFileOrDirCount "$1") -gt 0 ] } # Usage: getNonEmptyFileCount dirName fileNamePattern # See Also: existsNonEmptyFile function getNonEmptyFileCount() { local count count=$(find $1 -size +0 -name "$2" 2> /dev/null | wc -l) echo $count } # Usage: existsNonEmptyFile dirName fileNamePattern # See Also: getNonEmptyFileCount function existsNonEmptyFile() { [ $(getNonEmptyFileCount "$1" "$2") -gt 0 ] } # Usage: getHTTPResponseStatus URL function getHTTPResponseStatus() { local result result=$(curl -s -o /dev/null -I -w "%{http_code}" "$1") echo $result } # Usage: getIPOfURL URL function getIPOfURL() { local ip if [ ! -z "$1" ]; then # In case if dig lists CNAME then take the last line ip=$(dig $1 +short | tail -1) fi echo $ip } # Usage: getProcessPID processName function getProcessPID() { echo $(ps -ef | grep "$1" | head -1 | grep -v grep | awk '{print $2}') } # Usage: isProcessRunning processName function isProcessRunning() { [ ! -z "$(getProcessPID \"$1\")" ] } # Usage: isPortOpen portNumber function isPortOpen() { local result if [ ! -z "$1" ]; then result=$(netstat -ln --tcp | grep "$1\s.*\sLISTEN") fi [ ! -z "$result" ] } # Usage: Prompt user making it easy to say no function promptDefaultNo() { local msgPrompt local answer msgPrompt=$1 if [ -z "$msgPrompt" ]; then msgPrompt="Continue (Yes/no)?" fi while true; do read -p "$msgPrompt" answer case "$answer" in Yes ) echo "y"; break;; n|N|no|No ) echo "n"; break;; * ) echo "Please answer Yes or no.";; esac done } # Usage: Prompt user making it easy to say yes function promptDefaultYes() { local msgPrompt local answer msgPrompt=$1 if [ -z "$msgPrompt" ]; then msgPrompt="Continue (yes/No)?" fi while true; do read -p "$msgPrompt" answer case "$answer" in y|Y|yes|Yes ) echo "y"; break;; No ) echo "n"; break;; * ) echo "Please answer yes or No.";; esac done } # Usage: sendEmail emailList emailSubject emailMessage function sendEmail() { echo -e "\"$3\"" | mail -s "$2" "$1" }