Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between shebang flags vs. set builtin flags

Tags:

bash

posix

sh

Is there a difference in behaviours with respect to the flags passed to the script on the shebang line vs. using the set builtin?

For example:

#!/bin/bash -e

# do stuff

vs.

#!/bin/bash
set -e
# do stuff

(The question is not specific to -e flag but in general for any such flags).

Obviously the set [flags] is effective only from the point it's set. But are there any other differences in functionality/behaviour?

Is behaviour same in a POSIX shell, too?

like image 946
P.P Avatar asked May 23 '20 20:05

P.P


People also ask

What does set Xe do?

1) tells bash to exit under certain conditions (which may apply to your script). If that is the case, " set -xe " might print more of the trace before exiting than " set -e " followed by " set -x ".

What is the purpose of a shebang in a script file?

What is the shebang? The shebang is a special character sequence in a script file that specifies which program should be called to run the script. The shebang is always on the first line of the file, and is composed of the characters #! followed by the path to the interpreter program.

Is bash shebang necessary?

The shebang is only mandatory for those scripts, which shall be executed by the operating system in the same way as binary executables. If you source in another script, then the shebang is ignored. On the other hand. IF a script is supposed to be sourced, then it is convention to NOT put any shebang at the start.

What is set in bin bash?

by Taimoor Mohsin. In Bash, the set command allows you to manage certain flags and characteristics to influence how your bash scripts behave. These controls ensure that your scripts follow the correct path and that Bash's peculiar behavior does not cause difficulties.


Video Answer


3 Answers

are there any other differences in functionality/behaviour?

When your file has executable permissions and is executed, then the shebang line is parsed by the kernel.

When your file is executed under the shell like bash ./script.sh then the shebang is just a comment. So it will be ignored, and your script will be run with whatever the callers flags are. Putting your flags after the shebang will make sure proper flags are set in your scripts in either case.

The shebang is parsed by kernel. That basically means that the behavior differs from kernel to kernel, from operating system to operating system. Some operating systems didn't handle arguments in shebang at all and ignored all the arguments. Some kernels parse for example #!/bin/sh -a -b as execl("/bin/sh", "-a -b") some as execl("/bin/sh", "-a", "-b"). The parsing of the shebang line to executable and arguments is done by some other code different that your shell. Sometimes if there is a space after #! like #! /bin/sh utilities don't recognize it as a valid shebang. There's even a recent linux kernel regression with too long shebang line.

The behavior of how shebang is interpreted differs between systems, so you can't be certain, so it's best to set options after the shebang.

Is behaviour same in a POSIX shell, too?

A POSIX shell doesn't (have to) interpret your shebang. If you are asking if executing sh -e and set -e has the same behavior in posix shell, then yes, the option -e on command line has the same behavior as set -e.

I couldn't find a specification of shebang line nor how should it be interpreted in posix specification. I can see in execve documentation:

Another way that some historical implementations handle shell scripts is by recognizing the first two bytes of the file as the character string "#!" and using the remainder of the first line of the file as the name of the command interpreter to execute.

Those "historical implementations" seem to be very widely used still today.

The shebang line is parsed by the kernel after exec* calls. But when you are doing sh <script> or popen or system the shell can (but doesn't have to) interpret the shebang line by itself as a extension and not rely on kernel implementation, from posix:

Shell Introduction

  1. The shell reads its input from a file (see sh), from the −c option or from the system() and popen() functions defined in the System Interfaces volume of POSIX.1-200x. If the first line of a file of shell commands starts with the characters"#!",the results are unspecified.

As for bash, it looks like bash first tries execve, then if it can't find the reason why kernel failed to run the executable, if the file has a shebang, then it parses shebang on its own to find out the interpreter.

like image 160
KamilCuk Avatar answered Oct 26 '22 22:10

KamilCuk


Some operating systems may disallow or limit the use of arguments in the shebang. No such limit would apply to a set command in the script itself.

like image 21
chepner Avatar answered Oct 26 '22 21:10

chepner


The manpage states that "-e" has different behaviour depending on POSIX mode or not. Other than that, I have never noticed a difference between setting parameters and extending shebang. Why are you asking this question?

like image 1
Snorik Avatar answered Oct 26 '22 23:10

Snorik