Sunday, December 21, 2014

Shell Scripting : Why closing a terminal kills all the programs running in it?

When a terminal is closed, it is sent SIGHUP signal. Before terminal exits, it sends SIGHUP to all jobs, which are either running or stopped in it. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.  

To prevent the shell from sending a SIGHUP signal to a particular job, the job should be removed from the jobs table using disown builtin command.

Shell Scripting : Why directory change can't be made in a separate process?

While executing cd command, if a new process is forked as a child process of the current shell, then after the cd command execution is completed, the control would revert back to the parent process(the current shell) and the original directory would be restored back. Hence, it would be impossible to change directories.

Hence cd command is executed within the current shell process itself.

Shell scripting : Shell Builtin commands

Shell builtin commands do not fork(spawn) a new process and these commands are executed in the current shell itself.

Good examples are the commands like cd, echo, variable assignment like a=2.
These commands when executed do not generate a new process, and are executed directly in the current shell itself. Hence, these commands execute much faster as there is no overhead of spawning new process. 

Shell Scripting : Length of a string

In shell scripting, to find the length of a string

#!/bin/bash
line="to do"

echo "Length of string is ${#line}

Shell Scripting : Integer comparison

integer comparison
-eq
is equal to
if [ "$a" -eq "$b" ]
-ne
is not equal to
if [ "$a" -ne "$b" ]
-gt
is greater than
if [ "$a" -gt "$b" ]
-ge
is greater than or equal to
if [ "$a" -ge "$b" ]
-lt
is less than
if [ "$a" -lt "$b" ]
-le
is less than or equal to
if [ "$a" -le "$b" ]
<
is less than
(("$a" < "$b"))
<=
is less than or equal to
(("$a" <= "$b"))
>
is greater than
(("$a" > "$b"))
>=
is greater than or equal to (within double parentheses)
(("$a" >= "$b"))

Shell Scripting : AND, OR operators

To use AND, OR operators in shell scripting, there are two ways to do this

1) -a for AND
    -o for OR

the usage is  [ exp1 -a exp2 ] , [ exp1 -o -exp2 ]
Single square bracket for using -a, -o

2) && for AND
    ||      for OR

the usage is [[ exp1 && exp2 ]] , [[exp1 || exp2]]
Double square bracket for using &&, ||


Eg1:

#!/bin/bash

a=4
b=5

if [ "$a" -ne "$b" -a "$a" -lt "$b" ]
then
   echo "$a is not equal to $b"

fi

Eg2:

#!/bin/bash

a=4
b=5

if [[ "$a" -ne "$b" && "$a" -lt "$b" ]]
then
   echo "$a is not equal to $b"
fi

Thursday, December 18, 2014

Shell Scripting : How to find the value of the last argument passed to a shell script?

Curly Bracket notation {} for positional parameters helps in identifying the value of the last argument passed to a shell script

#!/bin/bash
#argcheck.sh

args=$#          #Specifies the number of arguments passed to the script

lastarg=${!args} #Specifies the value of the last argument passed to the script

# lastarg=${!#} is another way to get the last argument value

echo $args

echo $lastarg

If the above script is run as

./argcheck.sh 10 20 30

3  - Specifies the number of arguments passed to the function
30 - Specifies the value of the last argument

Shell Scripting : How to specify positional parameters greater than 9?

In shell scripting, the positional parameters are specified by $0, $1, $2, $3, $4, $5, $6, 47, $8, $9

To specify positional parameters greater than 9, it can done by enclosing in curly brackets as follows ${10}, ${11} and so on.

$0 is the name of the script itself, $1 is the first argument, $2 is the second argument and so on

Shell Scripting : How to store output of a command to a variable in shell script?

To store the output of a command to a variable in shell script(also called as command substitution),  there are two methods possible

1) Using backquotes ``
2) Using $( )

Let us see how

# arch=`uname -m`
# echo $arch
x86_64

# arch=$(uname -m)
# echo $arch
x86_64

Wednesday, December 17, 2014

Shell Scripting : > &> >&

scriptname >filename redirects the output of scriptname to file filename. Overwrite filename if it already exists.

command &>filename redirects both the stdout and the stderr of command to filename.

command >&2 redirects stdout of command to stderr.

Tuesday, December 16, 2014

Shell Scripting : How to truncate a file to zero length, without changing permissions?

To truncate a file to zero length without changing permissions, here are the options

1) cp /dev/null file.xxx
2) : > file.xxx

In the second option involving colon(:), the : being a shell built-in command, no new process is forked.

Monday, December 15, 2014

Shell Scripting: What if shebang(#!) is followed by path of the command /bin/rm i.e #! /bin/rm

What will happen if the following script, test.sh, is executed?

#!/bin/rm

echo "Hi"

./test.sh when executed, will remove the file test.sh

Shell scripting : What if there are two shebang(#!) lines in the shell script?

Suppose if there are two she-bang (#!) lines in a shell script

#!/bin/bash

echo "First line"

#!/bin/csh

echo "Second line"

When we run the above script, will /bin/bash be the interpreter for executing the command echo "First Line"  and later  /bin/csh be the interpreter for executing the command echo "Second line"?

No. Only the first line is #!/bin/bash is the interpreter for the whole script. The second interpreter beginning with # is considered as a comment. Any line beginning with # following the first shebang line is considered as a comment.


Shell Scripting : Which gets executed - shell specified in shebang(#!) or shell specified in command line

Suppose I have an executable script, test.sh as follows

#!/bin/bash

readlink /proc/$$/exe

When I run the above script as ./test.sh, then I know that bash shell executes the script. Then the output of above script is

$ ./test.sh
/bin/bash

If I run the above script as follows

$ /bin/csh test.sh

Which shell will execute the script - csh(specified in the command line) or bash(specified in the shebang)?

The output of the the above command is /bin/csh.

So why does /bin/csh execute the script instead of /bin/bash specified in the script?

Here is the answer,

Whenever a shell script is executed, a new shell(process) is spawned(forked) and the commands in the scripts are executed. The child shell becomes the parent process of commands in the script.
The shebang, #!, is used by the exec() family of functions to determine whether the file to be executed is a binary or script. If the shebang(#!) is present, then exec() will run the executable specified after the shebang - in the above case it is /bin/bash. she-bang is actually a two byte magic number that designates a file type. Immediately following the she-bang(#!) is the path name - this is the path to the program that interprets the commands in the script whether it be a shell, programming language or a utility. This command interpreter then executes the commands in the script starting at the top(following the shebang #! line), ignoring commands.

Now if you run the script by specifying the shell in the command line, like /bin/csh test.sh, the exec() will execute the shell interpreter, /bin/csh specified in the command line instead of looking into the script for shell interpreter specified in shebang line.


Thursday, December 11, 2014

SIGNALS: Use Signal Names or Signal Numbers with KILL command?

While passing signals to kill command, it is always better to use signal names rather than their numbers because the same signal is sometimes represented by different names on SVR4 and BSD systems.

Wednesday, December 10, 2014

How to copy a specific file type keeping the folder structure intact in the destination directory

By using cpio command in pass through mode, files can be copied to the destination directory with the same path structure as in the source directory

find /source_path/of/files -name "<regex_of_filetype>" | cpio -pdm /destination_directory_path

Eg: To copy all files of type "*.sh" in /home/bob to /tmp/jim, keeping the source directory path of files in destination intact


find /home/bob -type f -name "*.sh" | cpio -pdm /tmp/jim

How to find the version of cloudera Hadoop

Read the following file

# cat /usr/lib/hadoop/cloudera/cdh_version.properties

# Autogenerated build properties
version=2.0.0-cdh4.1.2
git.hash=f0b53c81cbf56f5955e403b49fcd27afd5f082de
cloudera.hash=f0b53c81cbf56f5955e403b49fcd27afd5f082de
cloudera.base-branch=cdh4-base-2.0.0
cloudera.build-branch=cdh4-2.0.0_4.1.2
cloudera.pkg.version=2.0.0+552
cloudera.pkg.release=1.cdh4.1.2.p0.27
cloudera.cdh.release=cdh4.1.2
cloudera.build.time=2012.11.02-00:01:31GMT

cloudera.pkg.name=hadoop

The Hadoop version installed is 2.0.0-cdh4.1.2, which means that Cloudera version installed is based on Apache Hadoop 2.0.0 release.