Thursday, August 11, 2016

The Bash "Set Builtin"

  • The Builtin "set" allows you
    • to change the values of shell options and
    • set the positional parameters, or
    • to display the names and values of shell variables.

  • If no options or arguments are supplied, set displays the names and values of all shell variables and functions, sorted according to the current locale, in a format that may be reused as input for setting or resetting the currently-set variables.
    Read-only variables cannot be reset.

    Remember the result is sorted accoding to current locale.
    Also it also in such a format that we can reuse them right away.The result also shows the functions in your current environment.

  • Syntax:set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument ...]set [+abefhkmnptuvxBCEHPT] [+o option-name] [argument ...]
    These options can be remembered as
    "Hump Backbone theft vx" (See below for details)

  • When options are supplied, they set or unset shell attributes.Options, if specified, have the following meanings. Note that a - is used to set the option and + is to unset:

  • We can see the values of the shell options by displaying contents of SHELLOPTS variableThe current set of options may be also be found in $-. Only difference is the way options are represented.The $- gives list of single character options and $SHELLOPTS gives textual list separated by colon.

    [sm017r@lldd010 ~]$ echo $-
    himBHP[sm017r@lldd010 ~]$ echo $SHELLOPTSbraceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:physical[sm017r@lldd010 ~]$


-b : Cause the status of terminated background jobs to be reported immediately, rather than before printing the next primary prompt.

Normally when status of a background job changes, the shell waits for next prompt the report.
When "set -b" is used the status change is reported immediately.

[sm017r@lldd009 ~]$ echo $0
-bash
[sm017r@lldd009 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd009 ~]$ sleep 3 &
[1] 63129
[sm017r@lldd009 ~]$ [ENTER]
[1]+  Done                    sleep 3

In the above example, the shell waited till we hit ENTER to display the prompt.

[sm017r@lldd009 ~]$ set -b
[sm017r@lldd009 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:notify
[sm017r@lldd009 ~]$ sleep 3 &
[1] 65475
[sm017r@lldd009 ~]$ [1]+  Done                    sleep 3

Note that contents of SHELLOPTS show that -b (notify) option was set.
We can also see that once 3 seconds were over the status was reported immedietely without waiting for the next prompt.

The option can be unset using set +b
set -o notify
Note that behaviour similar to -b can be achieved using set -o notify.
Again remember that -o is used to set the value and +o is used to unset.

Example:

[sm017r@lldd009 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd009 ~]$ set -o notify
[sm017r@lldd009 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:notify
[sm017r@lldd009 ~]$ set +o notify
[sm017r@lldd009 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor

-a : Marks all variables and function which are modified or created for export to the environment of subsequent commands.
This means all variables and functions are exported automatically.

[sm017r@lldd009 ~]$ set -a
[sm017r@lldd009 ~]$ echo $SHELLOPTS
allexport:braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd009 ~]$ var1=sukul
[sm017r@lldd009 ~]$ bash  ---> Start New subshell
[sm017r@lldd009 ~]$ echo $var1  --> var1 is still available in subshell because it was auto exported.
sukul
[sm017r@lldd009 ~]$ set +a  --> unset allexport
[sm017r@lldd009 ~]$ var2=sukul
[sm017r@lldd009 ~]$ bash
[sm017r@lldd009 ~]$ echo $var2  --> var2 is not available in subshell because it was not autoexported.

[sm017r@lldd009 ~]$

set -o allexport
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-C (capital)
Prevent output redirection using ‘>’, ‘>&’, and ‘<>’ from overwriting existing files.

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd010 ~]$ touch file1
[sm017r@lldd010 ~]$ echo "sukul" > file1
[sm017r@lldd010 ~]$ set -C
[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:noclobber
[sm017r@lldd010 ~]$ echo "sukul" > file1
-bash: file1: cannot overwrite existing file
[sm017r@lldd010 ~]$

Note that without noclobber(-C), overwriting file1 was possible.
With noclobber(-C) , overwriting file1 is not possible.

set -o noclobber
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-k : All arguments in the form of assignment statements are placed in the environment for a command, not just those that precede the command name.

[sm017r@lldd010 ~]$ cat script1.bash
echo $VAR1 $VAR2 $VAR3
[sm017r@lldd010 ~]$ VAR1=sukul bash script1.bash VAR2=china VAR3=moon
Sukul


[sm017r@lldd010 ~]$ set -k
[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:keyword:monitor:noclobber
[sm017r@lldd010 ~]$ VAR1=sukul bash script1.bash VAR2=china VAR3=moon
sukul china moon

Note that in the 1st example values of VAR2 and VAR3 are not printed, because they are set after the command line.
In the 2nd example  we set "keyword" option and then result shows variables that are set even after the command line.
set -o keyword
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-B:
The shell will perform brace expansion.
This option is on by default.

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:keyword:monitor:noclobber

[sm017r@lldd010 ~]$ touch a{x,y,z}b  
[sm017r@lldd010 ~]$ ls -lrt
-rw-r----- 1 sm017r ecdiwln    0 Aug 10 00:27 axb
-rw-r----- 1 sm017r ecdiwln    0 Aug 10 00:27 azb
-rw-r----- 1 sm017r ecdiwln    0 Aug 10 00:27 ayb

In this example brace expansion works and creates 3 files axb azb and ayb

[sm017r@lldd010 ~]$ set +B
[sm017r@lldd010 ~]$ echo $SHELLOPTS
emacs:hashall:histexpand:history:interactive-comments:keyword:monitor:noclobber
[sm017r@lldd010 ~]$ touch a{x,y,z}c
[sm017r@lldd010 ~]$ ls -lrt
-rw-r----- 1 sm017r ecdiwln    0 Aug 10 00:27 a{x,y,z}c

The braceexpand option is enabled by default. The set +B unsets this and brace expansion does not work anymore.
Thats why a file with name a{x,y,z}c is created.
set -o braceexpand
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.


-o :
Set the option corresponding to option-name

Ex:
set -o braceexpand
(check the examples in the 2nd column)

-n :
Read commands but do not execute them; this may be used to check a script for syntax errors.

This option is ignored by interactive shells.

(wasnt being able to test this :( . Doesnt seem to work)

set -o noexec
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-e:
Exit immediately if a pipeline , which may consist of a single simple command , a list(command separated by && or ||) , or a compound command returns a non-zero status.

By default  The shell does not exit if the command that fails is
  • part of the command list immediately following a while or until keyword, part of the test in an if statement,
  • part of any command executed in a && or || list except the command following the final && or ||,
  • any command in a pipeline but the last, or if the command’s return status is being inverted with !.

Example 1:
[sm017r@lldd010 ~]$ cat script1.bash
echo $SHELLOPTS
who | while read LINE
do
cho $LINE
date
done
echo $?

Note that in above script, the keyword echo is misspelled.
But this is inside a while loop. In the below result we can see that the while loop does not exit even if the command fails.
It keeps looping until its all done. So we can see that the command failure inside a complex command (like while, until, if) is ignored.

[sm017r@lldd010 ~]$ bash script1.bash
braceexpand:hashall:interactive-comments
script1.bash: line 4: cho: command not found
Wed Aug 10 00:49:31 EDT 2016
script1.bash: line 4: cho: command not found
Wed Aug 10 00:49:31 EDT 2016
script1.bash: line 4: cho: command not found
Wed Aug 10 00:49:31 EDT 2016
0    --> return code of while loop is 0 even if there is a failure inside while.

Example 2:
[sm017r@lldd010 ~]$ cat script1.bash
set -e
echo $SHELLOPTS
who | while read LINE
do
cho $LINE
date
done
echo $?

[sm017r@lldd010 ~]$ bash script1.bash
braceexpand:errexit:hashall:interactive-comments
script1.bash: line 5: cho: command not found

In the above example, we set the errexit option using set -e
Note that here when the command failed, the compound command also exited. It didnt keep looping.
This is useful when we want pipeline or compound command to exit as soon as some command fails in it.

set -e errexit
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

Above Set of options can be abbreviated as "baCkBone"

-h :

Locate and remember (hash) commands as they are looked up for execution. This option is enabled by default.

set -o hashall
-u:

Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’ as an error when performing parameter expansion.
An error message will be written to the standard error, and a noninteractive shell will exit.

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd010 ~]$ cat script1.bash
echo "Sukul's Age is $AGE"
[sm017r@lldd010 ~]$ bash script1.bash
Sukul's Age is

In 1st example value for variable AGE is not set. The script works fine without any issues.

[sm017r@lldd010 ~]$ cat script1.bash
set -u
echo "Sukul's Age is $AGE"
[sm017r@lldd010 ~]$ bash script1.bash
script1.bash: line 2: AGE: unbound variable

In the 2nd option we set nounset option using set -u. In this case the script fails because variable AGE is not provided a value.
This is very useful when we want variables to have values and make sure bash is stricter when it comes to empty variables.
set -o nounset
The nounset means that unset variables are not allowed.
-m :

Job control is enabled

This option is enabled by default for interactive shells.

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor


set -o monitor

-P :
If set, do not resolve symbolic links when performing commands such as cd which change the current directory.
The physical directory is used instead.

[sm017r@lldd010 ~]$ ln -s /cfs/app/etl_d2x/ecdw_apps_d23c/fccdtv/code/bin/ fccdtvbin

fccdtvbin is the soft link created for /cfs/app/etl_d2x/ecdw_apps_d23c/fccdtv/code/bin/

[sm017r@lldd010 ~]$ cd fccdtvbin
[sm017r@lldd010 fccdtvbin]$ pwd
/home/sm017r/fccdtvbin
[sm017r@lldd010 fccdtvbin]$

When -P option is set, cd will take us to the actual physical directory.

[sm017r@lldd010 ~]$ set -P
[sm017r@lldd010 ~]$ cd fccdtvbin
[sm017r@lldd010 bin]$ pwd
/cfs/app/etl_d2x/ecdw_apps_d23c/fccdtv/code/bin
[sm017r@lldd010 bin]$

Notice that cd to the link name, actually takes us to the physical directory.
To unset use set +P

set -o physical
Above Set of options can be abbreviated as "humP"

-v

Print shell input lines as they are read.

This can be useful to see what all lines are executed by the script.

[sm017r@lldd010 ~]$ cat script1.bash
set -v     --> Set verbose mode.
echo "$(date) : Sukul"
echo "$(date) : Mahadik"

[sm017r@lldd010 ~]$ bash script1.bash
echo "$(date) : Sukul"
Wed Aug 10 02:15:14 EDT 2016 : Sukul
echo "$(date) : Mahadik"
Wed Aug 10 02:15:14 EDT 2016 : Mahadik

Above example shows both line being executed and output from the command.
To only see the lines being executed, we can redirect the output to the file.
On the screen we will only get the list of lines being executed. This is very useful if we are debugging a big script and we want to know what piece of code is getting executed.

[sm017r@lldd010 ~]$ bash script1.bash > file1
echo "$(date) : Sukul"
echo "$(date) : Mahadik"

set -o verbose
-x

Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before
they are executed.

The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments.

[sm017r@lldd010 ~]$ echo $PS4
+

[sm017r@lldd010 ~]$ cat script1.bash
set -x
echo "$(date) : Sukul"
echo "$(date) : Mahadik"

[sm017r@lldd010 ~]$ bash script1.bash
++ date
+ echo 'Wed Aug 10 02:24:17 EDT 2016 : Sukul'
Wed Aug 10 02:24:17 EDT 2016 : Sukul
++ date
+ echo 'Wed Aug 10 02:24:17 EDT 2016 : Mahadik'
Wed Aug 10 02:24:17 EDT 2016 : Mahadik
[sm017r@lldd010 ~]$ echo $PS4
+

set -x xtrace
Above Set of options can be abbreviated as "vx"

-t
Exit after reading and executing one command.

[sm017r@lldd010 ~]$ cat script1.bash
echo sukul
set -t
echo mahadik

[sm017r@lldd010 ~]$ bash script1.bash
sukul

Not sure about the practical application of this option. For now we can see that as soon as -t option is encounered, the script ends.
set -o onecmd
-H
Enable ‘!’ style history substitution
This option is on by default for interactive shells.

Following is how history substitution works

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd010 ~]$ echo "Sukul Mahadik"
Sukul Mahadik
[sm017r@lldd010 ~]$ history | grep 'Sukul Mahadik'
  189  08/10/16 01:12 echo "Sukul Mahadik"
  190  08/10/16 01:12 history | grep 'Sukul Mahadik'

[sm017r@lldd010 ~]$ !189
echo "Sukul Mahadik"
Sukul Mahadik

!189 causes the command number 189 to be printed and reexecuted again.
This is active by default for interactive shells.


set -o histexpand
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-E

If set, any trap on ERR is inherited by shell functions, command substitutions, and commands executed in a subshell environment.
The ERR trap is normally not inherited in such cases.
set -o errtrace
-f

Disable filename expansion (globbing)

Globbing is enabled by default.  We can use -f to disable globbing.

[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[sm017r@lldd010 ~]$ ls scr*
script1.bash
[sm017r@lldd010 ~]$ set -f
[sm017r@lldd010 ~]$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:noglob
[sm017r@lldd010 ~]$ ls scr*
ls: cannot access scr*: No such file or directory
[sm017r@lldd010 ~]$

The -f option disables globbing and "ls scr*" does not work anymore.
Use set +f to enable file globbing again.
set -o noglob
This also can be used to active same result as on left side
Remember -o is for setting and +o is for unsetting.

-T

If set, any trap on DEBUG and RETURN are inherited by shell functions, command substitutions, and commands executed in a subshell environment. The DEBUG and RETURN traps are normally not inherited in such cases.

set -o functrace
Above Set of options can be abbreviated as "tHEfT"

--
If no arguments follow this option, then the positional parameters are unset.
Otherwise, the positional parameters are set to the arguments, even if some of them begin with a ‘-’.

[sm017r@lldd011 ~]$ set -- sukul mahadik
[sm017r@lldd011 ~]$ echo $2 $1
mahadik sukul
[sm017r@lldd011 ~]$ set --
[sm017r@lldd011 ~]$ echo $2 $1

[sm017r@lldd011 ~]$



-
Signal the end of options, cause all remaining arguments to be assigned to the positional parameters.
If there are no arguments, the positional parameters remain unchanged.

[sm017r@lldd011 ~]$ set - sukul mahadik
[sm017r@lldd011 ~]$ echo $2 $1
mahadik sukul
[sm017r@lldd011 ~]$ set - suntul
[sm017r@lldd011 ~]$ echo $2 $1
suntul
[sm017r@lldd011 ~]$ set -
[sm017r@lldd011 ~]$ echo $2 $1
suntul
[sm017r@lldd011 ~]$



set -o emacs
Use an emacs-style line editing interface
We can change this by using set -o vi OR set +o emacs

set -o history
Enable command history.
This option is on by default in interactive shells.

set -o vi
Use a vi-style line editing interface.
We can change this by using set -o emacs OR set +o vi

set -o pipefail
If set, the return value of a pipeline is the value of
the last (rightmost) command to exit with a non-zero
status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.

The exit status of a pipeline is the exit status of the last command in the pipeline, unless the pipefail option is enabled.
If pipefail is enabled, the pipeline’s return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.

[sm017r@cldi016 ~]$ ls -lrt | wg | wc -l
-bash: wg: command not found
0
[sm017r@cldi016 ~]$ echo $?
0
Note that even though the 2nd command in the pipe failed (because no command named wg exists), the return code was 0. That is because rc is the return code of the last command (wc -l)


[sm017r@cldi016 ~]$ set -o pipefail
[sm017r@cldi016 ~]$ ls -lrt | wg | wc -l
-bash: wg: command not found
0
[sm017r@cldi016 ~]$ echo $?
127
[sm017r@cldi016 ~]$
Here we set pipefail which causes return code to be the return code of the right most failed command.


Note that pipefail is disabled by default.




  • Note that the options can also be used upon invocation of the shell.Example: bash -x script1.bash

  • The command set o without an option lists each of the features controlled by set, followed by its state (on or off). The command set +o without an option lists the same features in a form you can use as input to the shell.

[sm017r@lldd010 ~]$ set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off
[sm017r@lldd010 ~]$ set +o
set +o allexport
set -o braceexpand
set -o emacs
set +o errexit
set +o errtrace
set +o functrace
set -o hashall
set -o histexpand
set -o history
set +o ignoreeof
set -o interactive-comments
set +o keyword
set -o monitor
set +o noclobber
set +o noexec
set +o noglob
set +o nolog
set +o notify
set +o nounset
set +o onecmd
set +o physical
set +o pipefail
set +o posix
set +o privileged
set +o verbose
set +o vi
set +o xtrace

No comments:

Post a Comment