LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Script command explanation (https://www.linuxquestions.org/questions/programming-9/script-command-explanation-4175709005/)

Debian6to11 03-06-2022 04:26 AM

Script command explanation
 
Suppose I have a script with four lines as follows:
command1
command2
command3
command4

If command2 gives an error does the script proceed to command3, or does it stop?

If so, is it essentially the same as:
command1 && command2 && command3 && command4

michaelk 03-06-2022 06:56 AM

No, the && means command2 will only run if command1 completed successfully and so on.

command1
command2
...

command2 will run regardless if command1 ran successfully.

teckk 03-06-2022 08:05 AM

Why don't you try/experiment/test it for yourself.

Code:

#!/usr/bin/bash

a=({1..20})
b=(cow horse dog cat bird fish frog elephant lion tiger)
c=(one two three four five six seven eight nine ten)

echo "${a[@]}"
ech "${b[@]}"
echo "${c[@]}"

echo -e ''$_{1..50}'\b─'

echo "${a[@]}" &&
ech "${b[@]}" &&
echo "${c[@]}"


boughtonp 03-06-2022 08:57 AM


 
If you want a script to stop when it encounters an error, you can use "set -e"


Debian6to11 03-06-2022 10:24 AM

It seems I have to use (set -e).

Is there anything I can do to find out which line gave the error?

boughtonp 03-06-2022 10:44 AM


 
"set -x" will output certain commands, after expansions, but before executing.

It's quite common to apply these to the shell/bash command - e.g. "#!/usr/bin/bash -ex" - try that with teckk's script to see how it works.

The benefit of "set" is you can turn the options on/off for relevant parts of a script (Though confusingly, set uses "+" to turn things off.)

Also, if you haven't already, ShellCheck can be used to highlight common errors.


Debian6to11 03-06-2022 11:12 AM

I tried teckk's script and also a second time I used (-ex) at the end of the hashbang line, I have seen no difference.
Trying that with the set -e as a second line closed the terminal window after pressing enter, no error output. Never mind about that though.

With the set -e option, I can place that line anywhere, let's say at the beginning of a script, and to unset it at line 50 for instance, I have to insert a line as (set +). Did I get that right?

And there is nothing that can show me which line or command gave me an error? I am planning to automate LFS as much as I can and I do expect a few errors at least (on a good day). I am planning to make it in 3-4 sections and then combine it (the file will be long at the end).

Debian6to11 03-06-2022 11:19 AM

Or can I direct the output to a file to find out where the error was?

teckk 03-06-2022 11:19 AM

Quote:

And there is nothing that can show me which line or command gave me an error?
test1.sh
Code:

#!/usr/bin/bash

set -x

a=({1..20})
b=(cow horse dog cat bird fish frog elephant lion tiger)
c=(one two three four five six seven eight nine ten)

echo "${a[@]}"
ech "${b[@]}"
echo "${c[@]}"

echo -e ''$_{1..50}'\b─'

echo "${a[@]}" &&
ech "${b[@]}" &&
echo "${c[@]}"

Code:

bash ./test1.sh
+ a=({1..20})
+ b=(cow horse dog cat bird fish frog elephant lion tiger)
+ c=(one two three four five six seven eight nine ten)
+ echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ ech cow horse dog cat bird fish frog elephant lion tiger
./test1.sh: line 10: ech: command not found
+ echo one two three four five six seven eight nine ten
one two three four five six seven eight nine ten
+ echo -e '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─' '\b─'
──────────────────────────────────────────────────
+ echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ ech cow horse dog cat bird fish frog elephant lion tiger
./test1.sh: line 16: ech: command not found

Tells exactly what line failed.

Debian6to11 03-06-2022 11:49 AM

Good one, what I need. And that was a nice example teckk.

Thanks to all. Have a nice day/night.

boughtonp 03-06-2022 01:02 PM

Quote:

Originally Posted by Debian6to11 (Post 6335646)
I tried teckk's script and also a second time I used (-ex) at the end of the hashbang line, I have seen no difference.

You should do! Although you haven't stated which distro/shell you're using, but I'm fairly sure this is POSIX level and should work everywhere

Anyway, here's a quick example - it has the same effect whether you are running Bash yourself, or whether execve is calling it as "#!/path/to/bash" (although one important distinction is the latter passes only a single argument to the interpreter).
Code:

$ bash -c 'echo one;ech two;echo three'
one
bash: ech: command not found
three

$ bash -e -c 'echo one;ech two;echo three'
one
bash: ech: command not found

$ bash -x -c 'echo one;ech two;echo three'
+ echo one
one
+ ech two
bash: ech: command not found
+ echo three
three

$ bash -ex -c 'echo one;ech two;echo three'
+ echo one
one
+ ech two
bash: ech: command not found


Quote:

With the set -e option, I can place that line anywhere, let's say at the beginning of a script, and to unset it at line 50 for instance, I have to insert a line as (set +). Did I get that right?
Enable with "set -e", (optionally) disable with "set +e", or "set -x" and "set +x", or "set -ex" and "set +ex", etc.


pan64 03-07-2022 01:10 AM

what was missing:
I would suggest to use:
Code:

set -o errexit # set -e
set -o nounset

errexit will force to stop the script in case of an error, so back to the original post, if command2 fails command3 and anything after will not be executed.
nounset is used to stop if someone tries to use an undefined variable.
set -o xtrace (or set -x) is used to print a lot of debug messages, this was described before.

boughtonp 03-07-2022 06:41 AM


 
And for consistency/completeness, "set -o nounset" is the same as "set -u"

The benefit of the single-letter options over option names is the ability to combine them in a single argument/command.

"help set" provides a convenient reminder of what's what.


NevemTeve 03-07-2022 12:02 PM

Also there is set -o pipefail
Example:
Code:

set -e
make install 2>&1 | tee log.make.all
echo 'tee' succeed

vs
Code:

set -e
set -o pipefail
make install 2>&1 | tee log.make.all
echo both 'make install' and 'tee' succeed



All times are GMT -5. The time now is 03:07 PM.