Bash command option clarification bash -ex - linux

could you please explain to me what exactly this shell command do?
It is quite difficoult to retrive the description of this -ex option.
sh #!/bin/bash -ex
Thanks in advance

It means you're invoking new bash shell with -e and -x shell options
See shell options here: https://tldp.org/LDP/abs/html/options.html
-e errexit Abort script at first error, when a command exits with non-zero status (except in until or while loops, if-tests, list constructs)
-x xtrace Similar to -v, but expands commands
since -x is similar to -v:
-v verbose Print each command to stdout before executing it
So it's actually dropping to next level shell:
$ echo $SHLVL
1
$ sh #!/bin/bash -ex
$ echo $SHLVL
2
in which in this level 2 shell, option -e and -x is activated

Related

use of flags in bash script

Scripts in linux start with some declaration like :
#!/bin/bash
Correct me if I am wrong : this probably says which shell to use.
I have also seen some scripts which say :
#!/bin/bash -ex
what is the use of the flags -ex
#!/bin/bash -ex
<=>
#!/bin/bash
set -e -x
Man Page (http://ss64.com/bash/set.html):
-e Exit immediately if a simple command exits with a non-zero status, unless
the command that fails is part of an until or while loop, part of an
if statement, part of a && or || list, or if the command's return status
is being inverted using !. -o errexit
-x Print a trace of simple commands and their arguments
after they are expanded and before they are executed. -o xtrace
UPDATE:
BTW, It is possible to set switches without script modification.
For example we have the script t.sh:
#!/bin/bash
echo "before false"
false
echo "after false"
And would like to trace this script: bash -x t.sh
output:
+ echo 'before false'
before false
+ false
+ echo 'after false'
after false
For example we would like to trace script and stop if some command fail (in our case it will be done by command false): bash -ex t.sh
output:
+ echo 'before false'
before false
+ false
These are documented under set in the SHELL BUILTIN COMMANDS section of the man page:
-e will cause Bash to exit as soon as a pipeline (or simple line) returns an error
-x will case Bash to print the commands before executing them
-e
is to quit the script on any error
-x
is the debug mode
Check bash -x command
and What does set -e mean in a bash script?

Shell scripting shell inside shell

I would like to connect to different shells (csh, ksh etc.,) and execute command inside each switched shell.
Following is the sample program which reflects my intention:
#!/bin/bash
echo $SHELL
csh
echo $SHELL
exit
ksh
echo $SHELL
exit
Since, i am not well versed with Shell scripting need a pointer on how to achieve this. Any help would be much appreciated.
If you want to execute only one single command, you can use the -c option
csh -c 'echo $SHELL'
ksh -c 'echo $SHELL'
If you want to execute several commands, or even a whole script in a child-shell, you can use the here-document feature of bash and use the -s (read commands from stdin) on the child shells:
#!/bin/bash
echo "this is bash"
csh -s <<- EOF
echo "here go the commands for csh"
echo "and another one..."
EOF
echo "this is bash again"
ksh -s <<- EOF
echo "and now, we're in ksh"
EOF
Note that you can't easily check the shell you are in by echo $SHELL, because the parent shell expands this variable to the text /././bash. If you want to be sure that the child shell works, you should check if a shell-specific syntax is working or not.
It is possible to use the command line options provided by each shell to run a snippet of code.
For example, for bash use the -c option:
bash -c $code
bash -c 'echo hello'
zsh and fish also use the -c option.
Other shells will state the options they use in their man pages.
You need to use the -c command line option if you want to pass commands on bash startup:
#!/bin/bash
# We are in bash already ...
echo $SHELL
csh -c 'echo $SHELL'
ksh -c 'echo $SHELL'
You can pass arbitrary complex scripts to a shell, using the -c option, as in
sh -c 'echo This is the Bourne shell.'
You will save you a lot of headaches related to quotes and variable expansion if you wrap the call in a function reading the script on stdin as:
execute_with_ksh()
{
local script
script=$(cat)
ksh -c "${script}"
}
prepare_complicated_script()
{
# Write shell script on stdout,
# for instance by cat-ting a here-document.
cat <<'EOF'
echo ${SHELL}
EOF
}
prepare_complicated_script | execute_with_ksh
The advantage of this method is that it easy to insert a tee in the pipe or to break the pipe to control the script being passed to the shell.
If you want to execute the script on a remote host through ssh you should consider encode your script in base 64 to transmit it safely to the remote shell.

Using linux script command

The script command executes and records logs.
( http://www.computerhope.com/unix/uscript.htm )
( http://linuxers.org/article/script-command-line-tool-recordsave-your-terminal-activity )
I use script command for saving commands and those output.
Whenever using 'script', I type commands like followings.
$ script result.log
Script started, file is result.log
$ date
$ ls -la.
$ exit
Sometimes I want to use those command with shell script.
So I run like following.
$ script -c test.sh result.log
But the result.log has only output, it doesn't contain command itself.
I want the result.log to include commands and output.
How can I do it?
Thanks
if you use sh -x to run your script it will print the commands or add
set -x to your script.
script -c "sh -x ./test.sh" reult.log
sample output:
+ date
Tue Dec 23 09:52:22 CET 2014
+ ls -la
set -o verbose
Execute this on terminal before executing your script or add this at the beginning of the script.
This will change the terminal configuration to echo all the commands before executing them.
This will add the command then followed by the output of that command.
you can also use :
set -x or set -v set -xv
-x option enables variable expansion and echo's all the option used with the command.
-v is similar to -o verbose this simply echo's the command name
-xv echo's both.

execute shell script directly differ from using sh command in ubuntu 12.04

Try to test command exist or not using simple script
$ cat test.sh
command -v nwef
echo $?
$ sh test.sh
127
$ ./test.sh
1
$ bash test.sh
1
In centos 6.5, the result is always 1.
Anyone know why "sh test.sh" is different?
sh in Ubuntu is dash, not bash.
The differences in exit statuses are with your usage of the command builtin and how Bash and Dash treat them differently.
In man bash:
command [-pVv] command [arg ...]
...
If the -V or -v option is supplied, the exit status is 0 if command was found, and 1 if not. If
neither option is supplied and an error occurred or command cannot be found, the exit status is 127. Otherwise, the exit status of the command builtin is the exit status of command.
This is why you get an exit 1 with Bash.
Since Dash does not treat -v option in command as Bash does, it treats nwef as "command not found", which is exit 127.
I think it's also important to note here how Debian treats ./test.sh differently than sh test.sh. Since the script does not contain a shebang path to an interpreter like #!/bin/sh, running ./test.sh defaults to #!/bin/bash instead of #!/bin/sh and treats your usage of command with exit 1. Unfortunately, I cannot find an explanation for this in documentation.

Debug bash/ksh script and subscripts

I know that to debug script I can issue command
set -x
on the first line. The problem is that when script launches some other scripts they do not inherit this setting. So my question is whether there is some possibility to set this flag globally for shell and all subshells or for some script and all scripts launched by it?
In Bash you can use export SHELLOPTS. It will make all Bash subshells inherit the -x option (as well as all the other options in SHELLOPTS!).
Example:
export SHELLOPTS
bash -x script1.sh
See bash recursive xtrace
It depends, you call call your subshells with -x too,
Put the set -x inside the Shell script
$ cat shell1.sh
echo "Shell1"
$ cat shell2.sh
#!/bin/bash
set -x
./shell1.sh
echo "shell2.sh"
$ ./shell2.sh
+ ./shell1.sh
Shell1
+ echo shell2.sh
shell2.sh

Resources