Shell scripting
We have tried to write a reference guide for Linux and Unix Admins.
Getting started
Starting an script.
The folling code is the typical "helloWorld" program writen in shell scripting:
#!/bin/bash # do something like echo "hello world!!!" exit 0
The first line contains the shebang declaration. It declares which interpreter is going to be used in order to execute the script.
The second line contains a comment. It is used to write things that help others to understand what was going on your head when you where writting the script.
Third line contains a reserved word because contains the "echo" command. This command takes the first argument given and dumps it to the standard output.
Forth line the exit status mainly
"0": means okey
other value: means something went wrong...
Linux variables
Shell variables.
$$ = The PID number of the process executing the shell.
$? = Exit status variable.
$0 = The name of the command you used to call a program.
$1 = The first argument on the command line.
$n = The nth argument on the command line.
$* = All the arguments on the command line.
$# The number of command line arguments.
Environment variables
$PATH=contains the path where commands are stored.
$RANDOM= obtains a random number value
$USER=contains the variable where the logged on user is stored.
$SHELL=conatins the execution shell in use
$TERM= the type of terminal
Other environment variables
On any shell or any script there are a lot of variables set. You can have a list of them typing "env" on the command line. The result will contain a pair of key and value list. The left side will be the key and the rigth side will be the value.
LESSKEY=/etc/lesskey.bin NNTPSERVER=news INFODIR=/usr/local/info:/usr/share/info:/usr/info MANPATH=/usr/share/man:/usr/local/man HOSTNAME=nodo1 XKEYSYMDB=/usr/share/X11/XKeysymDB HOST=nodo1 TERM=xterm SHELL=/bin/bash PROFILEREAD=true HISTSIZE=1000 SSH_CLIENT=10.25.4.216 4706 22 MORE=-sl SSH_TTY=/dev/pts/1 USER=root LS_COLORS=no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40; 33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32 :*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00; 31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00; 31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01; 35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35: *.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35: *.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32: *.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32: XNLSPATH=/usr/share/X11/nls ENV=/etc/bash.bashrc HOSTTYPE=x86_64 FROM_HEADER= PAGER=less CSHEDIT=emacs XDG_CONFIG_DIRS=/etc/xdg MINICOM=-c on MAIL=/var/mail/root PATH=/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin: /usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib/mit/bin:/usr/lib/mit/sbin CPU=x86_64 INPUTRC=/etc/inputrc PWD=/root LANG=POSIX PYTHONSTARTUP=/etc/pythonstart QT_SYSTEM_DIR=/usr/share/desktop-data SHLVL=1 HOME=/root LESS_ADVANCED_PREPROCESSOR=no OSTYPE=linux LS_OPTIONS=-A -N --color=tty -T 0 XCURSOR_THEME=DMZ WINDOWMANAGER=/usr/bin/gnome LESS=-M -I MACHTYPE=x86_64-suse-linux LOGNAME=root XDG_DATA_DIRS=/usr/share:/etc/opt/kde3/share:/opt/kde3/share LC_CTYPE=en_US.UTF-8 SSH_CONNECTION=10.25.4.216 4706 10.25.2.64 22 LESSOPEN=lessopen.sh %s INFOPATH=/usr/local/info:/usr/share/info:/usr/info LESSCLOSE=lessclose.sh %s %s G_BROKEN_FILENAMES=1 COLORTERM=1 _=/usr/bin/env
Variables
Variables are containers where the information of the program is stored.
First the program needs to initialize the value.
Then we can work with them.
name="santiago" echo $name
To initialize the variables, type a non reserved word and assign them a value.
Afterwards, do something with them like printing the value, storing them in disk...
Operating with variables: Bash
Addition
export res="0" export res=$((${res}+1))
Substraction
export res="10" export res=$((${res}-1))
Pipes, redirection and other stuff...
Redirection.
Each process has three type of descriptors:
- stdin: Standard Input
- stdout: Standard Output
- stderr: Standard Error
Stdin
Is the input that the process receives. It's expressed with the integer 1:
Stdin can be handled with the sign "<"
mknod /tmp/passwd p echo "admin123">/tmp/passwd & echo "admin123">/tmp/passwd & passwd bigadmin</tmp/passwd
You can read it with the command read <name_var>
read nombre echo "tu nombre es ${nombre}"
Stdout
asdfasdfa
Stderr
asdfasdfa
Pipes.
asdfasdfa
asdfasdfa
Conditional statements
OPERATORS.
test -f file
- True if the file is a plain file
test -d file
- True if the file is a directory
test -r file
- True if the file is readable
test -w file
- True if the file is writable
test -x file
- True if the file is executable
test -s file
- True if the file contains something
test -g file
- True if setgid bit is set
test -u file
- True if setuid bit is set
test s1 = s2
- True if strings s1 and s2 are equal
test s1 != s2
- True if strings s1 and s2 are unequal
test x -eq y
- True if the integers x and y are numerically equal
test x -ne y
- True if integers are not equal
test x -gt y
- True if x is greater than y
test x -lt y
- True if x is less than y
test x -ge y
- True if x>=y
test x -le y
- True if x <= y
!
- Logical NOT operator
-a
- Logical AND
-o
- Logical OR
Note that an alternate syntax for writing these commands if to use the square brackets, instead of writing the word test.
[ $x -lt $y ] "==" test $x -lt $y
Just as with the arithmetic expressions, Bash 2.x provides a syntax for conditionals which are more similar to Java and C. While arithmetic C-like expressions can be used within double parentheses, C-like tests can be used within double square brackets.
[[ $var == "OK" || $var == "yes" ]]
This C-like syntax is not allowed in the Bourne shell, but is equivalent to
[ $var = "OK" -o $var = "yes" ]
which is valid in both shells.
Arithmetic C-like tests can be used within double parentheses so that under Bash 2.x the following tests are equivalent:
[ $x -lt $y ] "==" (( x < y ))
IF ELSE
if [ param operator param2 ]
then
<bloque codigo>
else
<bloque codigo>
fi
ELIF
if [ bl1]
then
[code1]
elif [bl2]
then
[code2]
elif [bl3]
then
[code3]
fi
Switch/Case
case $variable-name in pattern1) command ... .. command;; pattern2) command ... .. command;; patternN) command ... .. command;; *) command ... .. command;; esac
Loops
for.
#!/bin/bash for i in $( ls ); do echo item: $i done
#!/bin/bash for ((i=100;i<=115;i+=1)); do echo $i sleep 1 echo $i > /dev/ttyS1 done
#!/bin/bash for i in `seq 1 10`; do echo $i done
while
while true do echo $aa done
#!/bin/bash for i in $( ls ); do echo item: $i done
#!/bin/bash for ((i=100;i<=115;i+=1)); do echo $i sleep 1 echo $i > /dev/ttyS1 done
#!/bin/bash for i in `seq 1 10`; do echo $i done
Must know commands.
Vi
awk grep cat
bc
echo mknod sort
seq date test
seq
Generates a sequence of numbers. Example:
dfasdf
date
Outputs the current system date.
afsdfa
test
Evaluates an expression returning true or false. Example:
( EXPRESSION ) EXPRESSION is true ! EXPRESSION EXPRESSION is false EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true -n STRING the length of STRING is nonzero STRING equivalent to -n STRING -z STRING the length of STRING is zero STRING1 = STRING2 the strings are equal STRING1 != STRING2 -h FILE FILE exists and is a symbolic link (same as -L) -k FILE FILE exists and has its sticky bit set -L FILE FILE exists and is a symbolic link (same as -h) -O FILE FILE exists and is owned by the effective user ID -p FILE FILE exists and is a named pipe -r FILE FILE exists and read permission is granted -s FILE FILE exists and has a size greater than zero -S FILE FILE exists and is a socket -t FD file descriptor FD is opened on a terminal -u FILE FILE exists and its set-user-ID bit is set -w FILE FILE exists and write permission is granted -x FILE FILE exists and execute (or search) permission is granted -b file True if file exists and is a block special file. -c file True if file exists and is a character special file. -d file True if file exists and is a directory. -e file True if file exists. -f file True if file exists and is a regular file. -g file True if file exists and its set-group-ID flag is set. -h file True if file exists and is a symbolic link. -L file True if file exists and is a symbolic link. -n string True if the length of string is non-zero. -p file True if file is a FIFO. -r file True if file exists and is readable. True shall indicate that permission to read from file will be granted, as defined in File Read, Write, and Creation . -S file True if file exists and is a socket. -s file True if file exists and has a size greater than zero. -t file_descriptor True if the file whose file descriptor number is file_descriptor is open and is associated with a terminal. -u file True if file exists and its set-user-ID flag is set. -w file True if file exists and is writable. True shall indicate that permission to write from file will be granted, as defined in File Read, Write, and Creation . -x file True if file exists and is executable. True shall indicate that permission to execute file will be granted, as defined in File Read, Write, and Creation . If file is a directory, true shall indicate that permission to search file will be granted. -z string True if the length of string string is zero. string True if the string string is not the null string. s1 = s2 True if the strings s1 and s2 are identical. s1 != s2 True if the strings s1 and s2 are not identical. n1 -eq n2 True if the integers n1 and n2 are algebraically equal. n1 -ne n2 True if the integers n1 and n2 are not algebraically equal. n1 -gt n2 True if the integer n1 is algebraically greater than the integer n2. n1 -ge n2 True if the integer n1 is algebraically greater than or equal to the integer n2. n1 -lt n2 True if the integer n1 is algebraically less than the integer n2. n1 -le n2 True if the integer n1 is algebraically less than or equal to the integer n2. expression1 -a expression2 True if both expression1 and expression2 are true. The -a binary primary is left associative. It has a higher precedence than -o. expression1 -o expression2 True if either expression1 or expression2 is true. The -o binary primary is left associative.
Gui for command line
dialog is a command line util that allows us to improve the look of a shellscript
dialog --title "Linux Dialog Utility Infobox" --backtitle "Linux Shell Script\
Tutorial" --infobox "This is dialog box called infobox, which is used \
to show some information on screen, Thanks to Savio Lam and\
Stuart Herbert to give us this utility. Press any key. . . " 7 50 ; read
Linux Console Formatting
Linux Console (Screen)
How can I write colorful message on Linux Console? , mostly this kind of question is asked by newcomers (Specially those who are learning shell programming!). As you know in Linux everything is considered as a file, our console is one of such special file. You can write special character sequences to console, which control every aspects of the console like Colors on screen, Bold or Blinking text effects, clearing the screen, showing text boxes etc. For this purpose we have to use special code called escape sequence code. Our Linux console is based on the DEC VT100 serial terminals which support ANSI escape sequence code.
What is special character sequence and how to write it to Console?
By default what ever you send to console it is printed as its. For e.g. consider following echo statement,
$ echo "Hello World"
Hello World
Above echo statement prints sequence of character on screen, but if there is any special escape sequence (control character) in sequence , then first some action is taken according to escape sequence (or control character) and then normal character is printed on console. For e.g. following echo command prints message in Blue color on console
$ echo -e "\033[34m Hello Colorful World!"
Hello Colorful World!
Above echo statement uses ANSI escape sequence (\033[34m), above entire string ( i.e. "\033[34m Hello Colorful World!" ) is process as follows
1) First \033, is escape character, which causes to take some action
2) Here it set screen foreground color to Blue using [34m escape code.
3) Then it prints our normal message Hello Colorful World! in blue color.
Note that ANSI escape sequence begins with \033 (Octal value) which is represented as ^[ in termcap and terminfo files of terminals and documentation.
You can use echo statement to print message, to use ANSI escape sequence you must use -e option (switch) with echo statement, general syntax is as follows
Syntax
echo -e "\033[escape-code your-message"
In above syntax you have to use\033[ as its with different escape-code for different operations. As soon as console receives the message it start to process/read it, and if it found escape character (\033) it moves to escape mode, then it read "[" character and moves into Command Sequence Introduction (CSI) mode. In CSI mode console reads a series of ASCII-coded decimal numbers (know as parameter) which are separated by semicolon (;) . This numbers are read until console action letter or character is not found (which determines what action to take). In above example
\033Escape character[Start of CSI3434 is parametermm is letter (specifies action)
Following table show important list of such escape-code/action letter or character
Character or letterUse in CSIExampleshSet the ANSI modeecho -e "\033[h"lClears the ANSI modeecho -e "\033[l"mUseful to show characters in different colors or effects such as BOLD and Blink, see below for parameter taken by m.echo -e "\033[35m Hello World"qTurns keyboard num lock, caps lock, scroll lock LED on or off, see below.echo -e "\033[2q"sStores the current cursor x,y position (col , row position) and attributesecho -e "\033[7s"uRestores cursor position and attributesecho -e "\033[8u"
m understand following parameters
ParameterMeaningExample0Sets default color scheme (White foreground and Black background), normal intensity, no blinking etc. 1Set BOLD intensity$ echo -e "I am \033[1m BOLD \033[0m Person"
I am BOLD Person
Prints BOLD word in bold intensity and next ANSI Sequence remove bold effect (\033[0m)2Set dim intensity$ echo -e "\033[1m BOLD \033[2m DIM \033[0m"5Blink Effect$ echo -e "\033[5m Flash! \033[0m"7Reverse video effect i.e. Black foreground and white background in default color scheme$ echo -e "\033[7m Linux OS! Best OS!! \033[0m"11Shows special control character as graphics character. For e.g. Before issuing this command press alt key (hold down it) from numeric key pad press 178 and leave both key; nothing will be printed. Now give --> command shown in example and try the above, it works. (Hey you must know extended ASCII Character for this!!!)$ press alt + 178
$ echo -e "\033[11m"
$ press alt + 178
$ echo -e "\033[0m"
$ press alt + 178
25Removes/disables blink effect 27Removes/disables reverse effect 30 - 37Set foreground color
31 - RED
32 - Green
xx - Try to find yourself this left as exercise for you :-)$ echo -e "\033[31m I am in Red"40 - 47Set background color
xx - Try to find yourself this left as exercise for you :-)$ echo -e "\033[44m Wow!!!"
q understand following parameters
ParametersMeaning0Turns off all LEDs on Keyboard1Scroll lock LED on and others off2Num lock LED on and others off3Caps lock LED on and others off