Low Orbit Flux Logo 2 F

Bash - Core Skills

Environment and Profiles

Sourcing Scripts

Sourcing a script will execute the script but it will not be executed in a separate shell. It is executed in the same shell. This allows it to be used to setup the environment ( environment variables, shell settings, etc. ). Shared settings are often sourced by scripts. Profiles are also typically sourced when a shell is launched.

Two different ways to source an example script:



source setup.sh
. setup.sh

Profiles

Your milage may vary. Your system may be different.

Interactive login shell:

Interactive non-login shell:

When invoked with the sh command:

Non-interactive / shell script:

These may also be used:

Extra Info

Bourne Shell built-ins:



:, ., break, cd, continue, eval, exec, exit, export, getopts, hash, pwd, readonly, return, set, shift, test, [, times, trap, umask and unset.

Bash built-in commands:



alias, bind, builtin, command, declare, echo, enable, help, let, local, logout, printf, read, shopt, type, typeset, ulimit and unalias.

Executing Scripts



bash -c "echo test"    # run command in string directly
bash test1.sh          # run script
bash -x script1.sh     # debug
./test1.sh             # run script

The very first line in every script is called the shebang and it specifies which interpreter to use. It looks like this. This bassically lets you know that this is a bash script and that it is run with bash.



#!/bin/bash

You can add a dir to your PATH variable like this. Scripts in one of the directories on your path can be run without specifying the full path, just the name of the script. You can run this line by itself for a single shell session or add it to your bashrc file if you want it to be persistent.

~/.bashrc
export PATH="$PATH:~/scripts"

Shell Options

Setting or unsetting shell options



set -x			# activate debugging from here
w               # run a command
set +x			# stop debugging from here

A few useful shell options:

set -f set -o noglob Disable file name generation using metacharacters (globbing).
set -v set -o verbose Prints shell input lines as they are read.
set -x set -o xtrace Print command traces before executing command.

Enable shell options at the beginning of a script:



#!/bin/bash -xv

Comments

Multi-line bash comment:



: '
This is a
very neat comment
in bash
'


: <<'END_COMMENT'
comment1
comment2
comment3
END_COMMENT

Variables

Scope:

Types:

View environment vars or normal vars:



env or printenv    # show environment variables
set                # show all variables and functions ( local and global )

Basic variable usage:



x="abc"
echo $x
unset x     # remove variable

export x="abc"   # export making it an environment variable so child processes can use it

Notable special variables:

$- # contains an i when in interactive mode
$PS1 # defines prompt, only set for interactive shells
$PS2 # secondary prompt
$IFS # A list of characters that separate fields; used when the shell splits words as part of expansion.
$PPID The process ID of the shell’s parent process
$PWD The current working directory as set by the cd built-in command.
$UID The numeric, real user ID of the current user.
$EUID The numeric effective user ID of the current user.
$HOME The current user’s home directory;
$PATH A colon-separated list of directories in which the shell looks for commands.
$* Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable.
$@ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word.
$# Expands to the number of positional parameters in decimal.
$? Expands to the exit status of the most recently executed foreground pipeline.
$- A hyphen expands to the current option flags as specified upon invocation, by the set built-in command, or those set by the shell itself (such as the -i).
$$ Expands to the process ID of the shell.
$! Expands to the process ID of the most recently executed background (asynchronous) command.
$0 Expands to the name of the shell or shell script.
$_ The underscore variable is set at shell startup and contains the absolute file name of the shell or script being executed as passed in the argument list. Subsequently, it expands to the last argument to the previous command, after expansion. It is also set to the full pathname of each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file.

Positional Parameters

These refer to the arguments passed to a script:

$0 name of the script
$1 first parameter
$2 second paramter
$3 Third parameter
etc. and so on …

Call a script like this:



./test1.sh a b c

Example script:

test1.sh
#!/bin/bash echo $0 echo $1 echo $2 echo $3

Output:



test1.sh
a
b
c

Quotes



echo \$date        # use escape char
echo "\$date"      # use escape char
echo '$date'       # print literal value, not variable

Expansions

Brace expansion



echo start{a,b,c}end

Output:



startaend
startbend
startcend

More brace expansion:



echo f{oo,ee,a}d                 # brace expansion
echo {000..2}                    # new in Bash 4
for num in {000..2}; do echo "$num"; done
echo {00..8..2}
echo {D..T..4}

{ date; top -b -n1 | head ; } >logfile  # code block, requires spaces around { and semicolon after last command

Nested brace expansion



echo start{a,b{1,2,3},c}end   #

Tilde expansion

~/testdir $HOME/testdir
~+/testdir $PWD/testdir
~-/testdir $OLDPWD/testdir
~user2/testdir /home/user2/testdir

Parameter expansion:

${VAR1} avoid confusion when next char isn’t part of var
${!VAR1*} indirect expansion?????

Arithmetic Expansion



$(( 5 + 5 ))
$[ 5 + 5 ]

0x123 hex
0123 octal, leading zero

Process substitution



<(LIST)
>(LIST)

Command Substitution, Subshell



(ls -l)      # subshell
x=$(ls -l)      # newer, easier to nest, POSIX
x=`ls -l`       # older, can have some escape chars?

Word splitting



echo $( ps -ef )        # split on all delimiters defined by $IFS
echo "$( ps -ef )"      # don't split

IFS=$'\n'               # set IFS to just new lines
echo $( ps -ef )        # now it splits, output still messy

for i in $(ps -ef ); do echo $i; done    # now it splits by line

File name expansion ( globbing )

* multiple unknown chars
? single unknown char
[1-5] range of matchable chars
[a-ew-z] range of chars


ls -l *
ls -l test?.txt
ls -l test[1-5].txt

Character classes:



ls -ld [[:digit:]]*
ls -ld [[:upper:]]*

Character classes:



"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "word" or "xdigit"

Aliases



alias ll='ls -l'    # create alias
unalias ll          # remove alias
unalias -a          # remove all aliases

Shell Options



set -o                 # show all shell options
set -o noclobber       # turn on existing files won't be overwritten by redirects
set +o noclobber       # turn off
set -u                 # unset vars cause error and exit non-interactive shell
set -o noglob           # turn off globbing

Grep / Sed / Awk / Xargs

All three of these commands can to a lot more than what is show here:

grep

Match lines with grep:



grep abc test.txt
grep -i abc test.txt
grep -v abc test.txt
ps -ef | grep -i nginx
grep -E "abc|xyz" test.txt

sed

Substitute strings with sed:



sed 's/abc/xyz/g' test.txt       # global swap
sed 's/abc/xyz/gI' test.txt      # case insensitive
sed -i 's/abc/xyz/g' test.txt    # edit file in place
sed -E 's/a|b/x/g' test.txt      # extended regex
ps -ef | sed 's/root/abcd/g'     # piping

awk

Split strings with awk:



awk '{print $3, $5, $7}'  test1.txt                  # print columns
awk '{print "Fields: "$3" == "$5" "$7}'  test1.txt   # custom string

awk -F/ '{print $3, $5, $7}'  test1.txt       # field separator
awk -F: '{print $3, $5, $7}'  test2.txt       # field separator
awk -F, '{print $3, $5, $7}'  test3.txt       # field separator

ps -ef | awk '{print output $3, $5, $7}'      # piping
ps -ef | awk ' /tty/ {print $3, $5}'          # split and match

xargs

The xargs command is used to send batches of arguments to a command. The command is run for each batch. Commands can only support a limited number of arguments ( argument length limit for exec less some ). Running a command once per argument would be very slow. Default command is echo. Batch size is system defined.



find /data1 | xargs rm                       # remove all files listed
find /data1 | xargs grep "Error"             # grep for a string inside all files found
find /data1 -print0 | xargs -0 grep "Error"  # same but handle files with whitespace in name
ls *.txt | xargs gzip                        # gzip all files listed
find /data1 | xargs gzip                     # gzip all files found
find /data1 | xargs -P 0 gzip                # gzip all files found and do as many in parallel as possible ( 0 )

Conditionals - if/else

Test Operators



$(     # return value instead of command
$((    # needed to assign to var or echo, not needed for test
$[     # needed to assign, like arithmetic expansion but obsolete
$[[    # DOESN'T work

let    # basically same as ((, but no spaces

(      # subshell or array definition
((     # arithmetic ops, can add spaces around ops, ommit $ on int and array vars
       # bare parens return 0 (true) value is non zero, 1 (false) if zero

test   # shell built in   test condition
[      # shell built in   test condition allows -a, -o, spacing matters!!
[[     # shell keyword    test condition allows &&, ||, =~, spacing matters!!
{      # unambiguously identify vars, parameter expansion, code block

Comparison Operators



-eq, =, == # work in [ and [[
-a, -o     # only works in [
||, &&     # only works in [[
<          # works in [[
\<         # need to escape for [

if / elif / else




if [ $x -eq "abc" ]; then
  echo "match 1"
elif [ $x -eq "xyz ]; then
    echo "match 2"
else
  echo "no match"
fi

Alternate:



if [ $x -eq "abc" ]
  then                                 # no semi colon if then is on next line
    echo "match 1"
fi

if [ $x -eq "abc" ]; then echo "match 1"; fi  # one liner

Nesting



if [ $x -eq "abc" ]; then
        if [ z -ne 0 ]; then
          echo "non zero z"
        else
          echo "z was zero"
        fi
fi

Basic Usage

Command directly in if statement, no test needed:



if ls; then echo asdf; else echo xxxxx; fi
if ls asdfasdfasdfasdf; then echo asdf; else echo xxxxx; fi

if ((5 == 5)); ...            # arrithmetic
if [ 5 -eq 5 ]; ...           # arrithmetic
if [ "5" -eq "5" ]; ...       # arrithmetic, string treated as integer
if [ "abc" -eq "xyz" ]; ...   # FAIL - expects integer
if [ "abc" == "xyz" ]; ...    # string compare
if [ 5 == 5 ]; ...            # works but is it comaring as string or int????
if [ 5 = 5 ]; ...             # works, aparently not assignment outside of arithmetic expansion

More expression usage



((a++))                     # increment variable
((x = 42))                  # assign variable, arithmetic
((x=5+4))                   # assign variable, arithmetic
(( x = 5 + 4 ))             # assign variable, arithmetic, spaces are OK
(( x = 5 == 5 ))            # test and save result
x=$((5+4))                  # assign variable, arithmetic
for ((i=0; i<10; i++))      # multiple operations used for for loop
echo $((a + b + (14 * c)))

let x=5+5
let x=5

Basic Tests



if [ -z $x ];                          # check if string is: unset, empty, or all spaces
if [ -f /var/log/messages ];           # check if file exists
if [ $a == "test" ];                   # strings equal
if [ $a != "test" ];                   # strings not equal
if [ $x -eq 5 ];                       # equal, can also use  -eq, -ne, -lt, le, -gt, ge
if [ $? -eq 0 ];                       # check exit status OK
if ! grep $extra_user /etc/passwd;     # not found
if [ "$(whoami)" != 'root' ]; then     # not root
if [[ "$x" == t* ]];                   # use a regex
if [ ! $# == 2 ];            # check number of args

Alternate examples:



[ "$(whoami)" != 'root' ] && ( echo "not root"; exit 1)
[ "$(whoami)" == 'root' ] || ( echo "not root"; exit 1)
[ "$(whoami)" == 'root' ] || { echo "not root"; exit 1}  # don't invoke subshell

test "$(whoami)" != 'root' && (echo "not root"; exit 1)

if [ $[$year % 400] -eq "0" ]; then   #arithmetic expansion with $[
if (( ($a % 4) == "0" )) || (( ($a % 4) == "0" ))     # boolean logic, can use || or &&

Which Bracket and Operator to Use

How to use = vs == for ((, [, [[



if (( x = "5" )); ...         # test assignment
if (( "5" == "5" )); ...      # test arith equality
if [ "abc" == "abc" ]; ...    # test string compare
if [ "abc" = "abc" ]; ...     # test string compare
if [[ "abc" == "abc" ]]; ...  # test string compare
if [[ "abc" = "abc" ]]; ...   # test string compare

if [ 5 -eq 5 -o 1 -eq 3 ]; ...     # logical or
if [ 5 -eq 5 -a 1 -eq 1 ]; ...     # logical and

if [[ 5 -eq 5 || 1 -eq 3 ]]  ...   # logical or
if [[ 5 -eq 5 && 1 -eq 1 ]]; ...   # logical and


if [[ (5 -eq 5 ) || (1 -eq 1 && 2 -eq 2) ]];        # group for logic
if [ \( 5 -eq 5 \) -o \( 1 -eq 1 -a 2 -eq 2 \) ];   # same but need to escape ( and picky about spaces


if [ $x == abc ];    # works
if [ $x == "abc" ];  # works
if [ $x == ab* ];    # fail
if [ $x == "ab*" ];  # works but NOT as wildcard

if [[ $x == abc ]];    # works
if [[ $x == "abc" ]];  # works
if [[ $x == ab* ]];    # glob
if [[ $x =~ ab* ]];    # regex ( * still matches multiple chars ????)
if [[ $x == a.* ]];    # glob
if [[ $x =~ a.* ]];    # regex

if [ -e $filename ];       # fail on file name with spaces because of word splitting
if [ -e "$filename" ];     # justt put it in double quotes to fix
if [[ -e $filename ]];     # works on file name with spaces because NO word splitting

Exit Codes

These are important for conditionals / tests.



exit 0   # exit normal / OK
exit 1   # exit with error code
exit 2   # exit with error code
exit 3   # exit with error code

Primary expressions

Primary Meaning
[ -a FILE ] True if FILE exists.
[ -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 SGID bit is set.
[ -h FILE ] True if FILE exists and is a symbolic link.
[ -k FILE ] True if FILE exists and its sticky bit is set.
[ -p FILE ] True if FILE exists and is a named pipe (FIFO).
[ -r FILE ] True if FILE exists and is readable.
[ -s FILE ] True if FILE exists and has a size greater than zero.
[ -t FD ] True if file descriptor FD is open and refers to a terminal.
[ -u FILE ] True if FILE exists and its SUID (set user ID) bit is set.
[ -w FILE ] True if FILE exists and is writable.
[ -x FILE ] True if FILE exists and is executable.
[ -O FILE ] True if FILE exists and is owned by the effective user ID.
[ -G FILE ] True if FILE exists and is owned by the effective group ID.
[ -L FILE ] True if FILE exists and is a symbolic link.
[ -N FILE ] True if FILE exists and has been modified since it was last read.
[ -S FILE ] True if FILE exists and is a socket.
[ FILE1 -nt FILE2 ] True if FILE1 has been changed more recently than FILE2, or if FILE1 exists and FILE2 does not.
[ FILE1 -ot FILE2 ] True if FILE1 is older than FILE2, or is FILE2 exists and FILE1 does not.
[ FILE1 -ef FILE2 ] True if FILE1 and FILE2 refer to the same device and inode numbers.
[ -o OPTIONNAME ] True if shell option “OPTIONNAME” is enabled.
[ -z STRING ] True of the length if “STRING” is zero.
[ -n STRING ] or [ STRING ] True if the length of “STRING” is non-zero.
[ STRING1 == STRING2 ] True if the strings are equal. “=” may be used instead of “==” for strict POSIX compliance.
[ STRING1 != STRING2 ] True if the strings are not equal.
[ STRING1 < STRING2 ] True if “STRING1” sorts before “STRING2” lexicographically in the current locale.
[ STRING1 > STRING2 ] True if “STRING1” sorts after “STRING2” lexicographically in the current locale.
[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.

Combining expressions

Operation Effect
[ ! EXPR ] True if EXPR is false.
[ ( EXPR ) ] Returns the value of EXPR. Can use to override operator precedence.
[ EXPR1 -a EXPR2 ] True if both EXPR1 and EXPR2 are true.
[ EXPR1 -o EXPR2 ] True if either EXPR1 or EXPR2 is true.

Case Statements



case $x in
    [1-6]*)                 # using a range and wildcard
        echo "lower"
        ;;
    12|15|23)               # or
        echo "more"
        ;;
    100|200)                # or
        echo "higher"
        ;;
    *)
        echo "anything else"
        ;;
esac

Common case statement example:



case "$1" in
        start)
            start
            ;;

        stop)
            stop
            ;;

        status)
            status
            ;;

        restart)
            stop
            start
            ;;

        *)
            echo $"Usage: $0 {start|stop|restart|condrestart|status}"
            exit 1

esac

Input / Output



echo "test"      # echo out some text
echo -e "test"   # interpret backslash escape chars
echo -n "test"   # suppress trailing newline


printf "First: %s\nSecond: %s\n" "12" "34"


read         # read inpupt, save to var REPLY by default
read x       # promt for input, save in variable
read a b c   # read multiple words and save each word in corresponding var,
             # remaining vars all assigned to last variable
             # word split by $IFS

input "this is a test"

echo $a   # prints "this"
echo $b   # prints "is"
echo $c   # prints "a test"

Redirection

Standard file handles / streams:



| 0 | STDIN  | input |
| 1 | STDOUT | output |
| 2 | STDERR | error output |

Redirection operators:

> overwrite
>> append
2>&1 redirect STDERR to whereever STDOUT is going
&> overwrite both STDERR and STDOUT ( BASH 4+ )


ls > test1.txt            # redirect command output ( STDOUT ) to a file and **OVERWRITE** file
ls >> test1               # redirect command output ( STDOUT ) to a file and **APPEND** to file

ls asdf 2> test1.txt      # redirect command output ( STDERR ) to a file and **OVERWRITE** file
ls asdf 2>> test1.txt     # redirect command output ( STDERR ) to a file and **APPEND** to file

ls asdf &> test1.txt      # redirect command output ( STDOUT and STDERR ) to a file ( since Bash 4 )

ls asdf >> output.log 2>&1   # append STDOUT to file, also redirect STDERR to STDOUT ( both go to file )

ls asdf >> output.log 2>&1 &  # also run in background with extra &

Background

You can run a command in the background by appending an ampersand to it:



./server1 &

./process_data.sh &

Pipes

You can pipe output from one command to another like this:



cat data1.csv | sort

ps -ef | grep -i nginx

Here documents

Output a multi line string:



cat << MYLIST
tree
rock
grass
MYLIST

Output multi line string to a file:



cat << MYLIST > /var/log/output
car
water
sand
MYLIST

Pass input to something:



yum install $1 << CONFIRM
y
CONFIRM

Loops

For Loops



x="a b c"


for i in `cat list`; do
    echo $i ;
done


for i in `cat list`; do echo $i ; done
for i in `ls`; do echo $i ; done
for i in a b c; do echo $i; done
for i in {1..10}; do echo $i; done
for i in `seq 1 10`; do echo $i; done
for i in $x; do echo $i; done            # loop over string ( word splitting )
for i in /opt/*; do echo $i; done        # loop over globbed file list

for (( i=0; i<10; i++)); do echo $i; done


IFS=$'\n'                             # split on new line, not space or tab
for i in `ps -ef`; do echo $i; done

While Loops



i=0; while [ $i -lt 4 ]; do echo $i; i=$[$i+1];done


i=0
while [ $i -lt 4 ]; do
    echo $i
    i=$[$i+1]
done


while true; do      # infinite loop
    echo "."
    sleep 5
done

Until Loops



i=0
until [ $i -gt 4 ]; do
    echo $i
    i=$[$i+1]
done

Piping and Redirection into Loops



ls | while read i; do
    echo "file: " $i
done


while read i; do
    echo "file: " $i
done < test1.txt


c=0
while true; do
    ((c++))
    read x
    [[ $x == "done" ]] && break         # break out of loop
    [[ $x == "skip" ]] && continue      # cut this iteration short and start next iteration
    echo $c
done

Select Loops

Keeps reading lines from input. If line is blank will re-print menu.



select x in frog rock tree;
do
     echo "You selected: $x item number: $REPLY"
done

Using a glob:



select x in *;
do
     echo "You selected: $x item number: $REPLY"
done

Using a command:



select x in $(ls);
do
     echo "You selected: $x item number: $REPLY"
done

Shift

Useful for unknown number of args if you want to process them one at a time.



shift 3   # shift positional args left by 3
          # drop 1,2,3, rename what is left

Example script:



$cat test.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9
shift 3
echo  $1 $2 $3 $4 $5 $6 $7 $8 $9
$

Example output:



$bash test.sh a b c d e f g h i
a b c d e f g h i
d e f g h i
$

Variables - More



declare -p x      # show type
declare -i x=12   # declare as integer ( restrict to only integer )

readonly x=abc    # create constant ( read only )
readonly -p       # show all constants


declare -i z      # delcare as integer
z=45+4            # can now use arithmetic without expansion

-a Variable is an array.
-f Use function names only.
-i The variable is to be treated as an integer; arithmetic evaluation is performed when the variable is assigned a value (see Section 3.4.6).
-p Display the attributes and values of each variable. When -p is used, additional options are ignored.
-r Make variables read-only. These variables cannot then be assigned values by subsequent assignment statements, nor can they be unset.
-t Give each variable the trace attribute.

Arrays



declare -a ARRAYNAME

a[3]=5      # assign element, will declare even if not first element

a=(1 2 3)   # declare, initialize - no commas, just spaces
a=(a b c)   # declare, initialize - no commas, just spaces


echo ${a[3]}       # specific element
echo ${a[$x]}      # variable as an index
echo ${a[*]}       # entire array
echo ${a[@]}       # entire array
echo ${a[@]:2:4}   # slice array (index, len )

${#x[@]}           # array length ( differnt from string len )

unset a[3]         # remove element
unset a            # remove array

for i in ${a[@]}; do echo $i; done   # loop over array

a+=("test")        # append element to end of array
a+="test"          # append value to first element

Associative Arrays / Hashs ( BASH 4+ )



# Declare and initialize:

declare -A a=(
    [color]="red"
    [size]="5"
    [shape]="square"
)


# Declare then initialize

declare -A a

a[color]="red"
a[size]="5"
a[shape]="square"


echo ${a[color]}   # access element


unset a[color]     # remove an element

echo ${a[@]}       # all values
echo ${!a[@]}      # all keys
echo ${#a[@]}      # length


# Loop over hash:

for i in "${!a[@]}"; do
    echo $i ": " ${a[$i]}
done

Strings Indexing, Defaults, and Manipulation



${#x}                  # string length ( different from array length )

echo ${STRING:4}       # index 4 and up
echo ${STRING:6:5}     # 5 chars after char 6

echo ${TEST:-ALT}      # default value - if TEST is null or undefined, use alt instead
echo ${TEST:=abc}      # default value - if TEST is null or undefined, use alt instead, also assign value
echo ${TEST:?"asdf"}   # if not set, print string and exit script ( non-interactive shell )

Starting at beginning:



echo ${x#a}     # match and remove this char from var
echo ${x#a*}    # match and remove shortest possible match from this char
echo ${x##a*}   # match and remove longest possible match from this char

Starting at end:



echo ${x%a}     # match and remove this char from var
echo ${x%a*}    # match and remove shortest possible match from this char
echo ${x%%a*}   # match and remove longest possible match from this char

echo ${x/abc/xyz}   # replaced abc with xyz in var x

Functions



function test1 { echo "test"; }
test1 () { echo "test"; }



test1 () {                         # totally valid, just need that space before {
    echo "Values: " $1 $2 $3 $#
    return 0
}

test1 ()
{
    local x='abc'                      # local variable
    y='xyz'                            # not local, survives outside the funciton even if first used here
    echo "Values: " $1 $2 $3 $#
    return 123                         # between 0-255
}


test1 a b c
echo $?

Signals

Signal name Signal value Effect
SIGHUP 1 Hangup
SIGINT 2 Interrupt from keyboard ctrl-c
SIGKILL 9 Kill signal
SIGTERM 15 Termination signal
SIGSTOP 17,19,23 Stop the process, 19 is ctrl-z

Send signals to processes:



kill    5607    #  SIGTERM 15 - kill process
kill -9 5607    #  SIGKILL 9 - force kill process
kill -HUP 5607  #  SIGHUP 1 - usually reload configs if supported

Trap signals within a script:



trap "echo will not stop" SIGINT SIGTERM           # when these signals are trapped
trap "load_configs" SIGHUP                         # load config files on SIGHUP
trap "{ rm -f $LOCKFILE ; exit 255; }" EXIT        # executed when shell exits EXIT or 0

Debug with Trap

Detect when a variable is used:



declare -t VARIABLE=value
trap "echo VARIABLE is being used here." DEBUG

Dir Stack - Pushd / Popd

Navigate quickly with these:



dirs          # show dir stack
dirs -p       # show dir stack one entry per line
dirs -v       # same but with numbers


pushd /etc    # add this dir to the stack and switch to it
pushd         # swap top two dirs,
pushd +2      # dir 2 and below shifted to top

popd          # remove top dir from stack and change to that dir
popd +2       # remove dir 2 from stack

References