Bash script: started with $! instead of #! and got mysterious behavior. What happened?

I accidentally ran a bash script with $! instead of #! and got a very strange behavior. I'm trying to find out what happened.

If you try this script:

 $!/bin/bash echo Hello world! 

you will get the following behavior:

 $ chmod +x hello $ ./hello [nothing happens, get prompt back] $ exit exit Hello world! $ 

So it looks like this happened:

  • A new bash shell has been created.
  • After exiting, the rest of the script is executed.

What? How's it going? Without #! how does the shell know to use bash to interpret the script?

Obviously, this is a question of "satisfying my curiosity" and not "solving my problem." Googling doesn't give much, perhaps because #! and $! queries do not make Googlebot happy.

+7
source share
3 answers

$ something is an extension of the parameter ("variable"), but $! in particular, returns a value that is not set in your script, so it expands as a string with zero length.

Therefore, your script is correct, equivalent:

 /bin/bash echo Hello world! 

The shebang magic number is an old Unix function, but the shell is even older. A text file with the execution bit set so that the kernel cannot execute exec (because it is not actually compiled) is executed by a subshell. That is, the shell intentionally launches another shell and passes the path as a parameter. Since the commands written as shell scripts were executed before shebang was invented, and it is still present in the code.

+9
source

dollar-bang gets the PID of the last background process.

http://tldp.org/LDP/abs/html/internalvariables.html (search for "$!")

+8
source

By deploying the bit to @DigitalRoss, reply :.

Executable script without #! the first line runs /bin/sh - even if you execute it from bash (or tcsh ). This is not shell functionality; it is at the core.

So, when you executed your script, it was executed /bin/sh (which means that on most systems it will not be able to use bash-specific functions), $! expanded to zero (since this shell did not start any background processes), and the first line calls the interactive shell /bin/bash . Then you exit this interactive shell and your script runs the line echo Hello world! and exits, returning you to the original shell.

For example, if you change echo Hello world! on echo $BASH_VERSION , you will find that you are not printing anything - and if you type history from the called interactive bash shell, it will not show anything.

+3
source

All Articles