Linux bash scripting comman usage guide

Jephe Wu - http://linuxtechres.blogspot.com

Objective: When you need to write bash script, you need to follow certain steps, I've summarized some tips which I've been using for the past.



Parameter and print out script usage:
The first thing after #!/bin/sh line should be usage for your script, especially when your script needs the parameters:

if  [ $# -eq 1 ];then echo "$0 username";exit 1;fi

note: your script requires username as command parameter, so above line will force you to give one parameter after the command.

Path definition:
You should export PATH variables first like this:
export PATH=/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin

Common tips in the script:

  • Let history command show date and time
# export HISTTIMEFORMAT="%h/%d - %H:%M:%S "
# history | less
  • check command return code 
command
if [ $? -ne 0 ];then
commands
exit
fi

  • recursive variable
 A="DATABASE/script.sh";B=${A/DATABASE/orcl};echo $B
it will return value: orcl/script.sh
  • while loop to read each line from /path/to/file and process it
while read line
do
echo $line
done < /path/to/file

or while IFS=\| read left right
do
echo $left $right
done < /path/to/filename

# another method
i=1
LINES=`wc -l /path/to/file | awk '{print $1}'`
while [ $i -le $LINES ]
do
iLINE=`sed -n $i'p' /path/to/file`
echo $iLINE
i=$[$i+1]
done

  • specify return value
if [ $? -eq 0 ];then
return 0
exit
else
return 2
exit
fi
  •  seq command usage in for loop
 for i in `seq -w 1 10`;do echo $i;done
01 01 03 04 05 06 07 08 09 10

  • Always use "bash -n scriptname" to verify if your script got any syntax error.
  •  check if the file size is 0
if [ ! -s /path/to/filename ];then commands ;fi
note: if the /path/to/file filesize is not zero, then run commands

  • use mktemp and mkdtemp 
You can use mktemp and mkdtemp to create temporary file or directorie variables
# TMPFILE1=`mktemp`
# TMPDIR1=`mktempdir`
  • how to let ls function as cd
alias ls=cd

or
ls () { builtin cd ; }

note: how to let ccd function as cd;pwd;foo

alias foo=`echo testing builtin`
ccd () { builtin cd "$1";pwd;foo; }

so ccd /tmp command will cd to /tmp, then print current working directory and print string 'testing builtin'


common tips:
  1. batch rename file
rename 1.txt and 2.txt to 1.bat and 2.bat

ls *.txt | sed 's#\(.*\).txt#mv \1.txt \1.bat#'  | sh 
     
    2.  use bc to calculate from CLI

# echo "scale=2;34359730176/1024/1024/1024" | bc
31.99
# echo "ibase=10;obase=16;10" | bc
A
# echo "ibase=16;obase=A;A" | bc
10

  3.  force root user to run script
if [ "$(id -u)" != "0" ]; then
echo "Only root can run this script"
exit 1
fi


4. vmstat with timestamp


#!/bin/sh
# more vmstat.sh
function eg {
  while read line
  do
    printf "$line"
    date '+ %m-%d-%Y %H:%M:%S'
  done
}

find /var/adm/logs/vmstat.log* -type f -mtime +15 -exec rm -f {} \;
vmstat 10 | eg >> /var/adm/logs/vmstat.log.`date +%Y%m%d`

in crontab:

0 0 * * * sleep 1;kill `ps -ef | grep -v  grep  |grep vmstat.sh | awk '{print $2}'`;sleep 3;nohup /home/oracle/bin/vmstat.sh &


5. variables in for loop


servers=("root@server1" "root@server2" )
for server in ${servers[*]}
do
ssh -n $server .....
    balabala
done

or


Files=(
"primary.xml.gz"
)
for file in ${Files[*]}

do
   balah
done

6. create sparse file and detect it


[root@oratest ~]# dd if=/dev/zero of=filea bs=1M count=0 seek=5
0+0 records in
0+0 records out
0 bytes (0 B) copied, 3.8969e-05 seconds, 0.0 kB/s
You have new mail in /var/spool/mail/root
[root@oratest ~]# ls -l filea
-rw-r--r-- 1 root root 5242880 Jul 19 12:25 filea
[root@oratest ~]# du -sm filea
0 filea
[root@oratest ~]# ls -lh filea -s
0 -rw-r--r-- 1 root root 5.0M Jul 19 12:25 filea