Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
It seems to me you still don't quite understand how the shebang line works. It is interpreted by execve(2), not by shell. At first, shell doesn't look inside an executable file, be it an ELF binary or a shell script or any other script: it just tries to execve it.
Only if that fails does the shell fall back to interpreting the executable as a shell script¹—this is the ancient compatibility feature the SO answer is talking about. For historical context, you may want to read the Unix FAQ linked from that answer. It describes the situation as it was in 1992.
________
¹ Which one depends on the calling shell. E.g. dash, mksh, oksh, yash, zsh and busybox hush will treat it as a /bin/sh script. Bash, ksh93, bosh and busybox ash will interpret it by themselves. Csh and tcsh are a special case as explained in the FAQ above.
Code:
$ cat noshebang.sh
: a legacy Bourne-compatible shell script
echo "Hello, I'm a `ps ocomm= $$` script
I was called by `ps ocomm= $PPID` as
`ps ocmd= $$`"
Code:
dash$ ./noshebang.sh
Hello, I'm a sh script
I was called by dash as
/bin/sh ./noshebang.sh
Code:
bash$ ./noshebang.sh
Hello, I'm a bash script
I was called by bash as
/bin/bash
Contrast that with csh/tcsh
Code:
tcsh% ./noshebang.sh
Hello, I'm a sh script
I was called by tcsh as
/bin/sh ./noshebang.sh
But
Code:
tcsh% cat csh-only.csh
# csh and tcsh will interpret this as a [t]csh script, bash as a bash script
repeat 1 echo "Hello I'm `ps ocomm= $$` script"
echo "I was called as"
echo "`ps ocmd= $$`"
Code:
tcsh% ./csh-only.csh
Hello I'm tcsh script
I was called as
/usr/bin/tcsh ./csh-only.csh
Code:
bash$ ./csh-only.csh
./csh-only.csh: line 2: repeat: command not found
I was called as
/bin/bash
$ command
$ env command
$ sudo command
the calling process (bash, env or sudo) invokes
execve(2)
which is a system call, that is, a call to the system, aka the kernel
while the execvp(3) family of functions are glibc frontends to execve(2)
and execve(3) (on die.net) is just the POSIX manual for the execvp(3) family of functions
if command is a binary then it is run by execve(2)
if not a binary then the shebang is honored by execve(2)
if the shebang calling process can run binaries
#!/usr/bin/env
#!/usr/bin/sudo
then we get infinite recursion
if there is no shebang then the system (the calling process, I believe), aka the kernel
tries some default shell after execve(2) fails
this shell is usually the system default shell
like, for example, sh
however, if the local default shell is csh
then csh is run if the first character in the script is #
otherwise sh is run
when command must be a script
$ bash command
$ sh command
then execve(2) is not called, the shebang is ignored
and the script is interpreted directly by the respective calling process (bash, sh)
I was confused by the fact that bash invokes execve(2) when command is run directly
An interpreter script is a text file that has execute permission enabled and whose first line is of the form:
#! interpreter [optional-arg]
The interpreter must be a valid pathname for an executable which is not itself a script. If the filename argument of execve() specifies an interpreter script, then interpreter will be invoked with the following arguments:
interpreter [optional-arg] filename arg...
where arg... is the series of words pointed to by the argv argument of execve().
For portable use, optional-arg should either be absent, or be specified as a single word (i.e., it should not contain white space); see NOTES below.
Quote:
Example
The following program is designed to be execed by the second program below. It just echoes its command-line one per line.
Code:
/* myecho.c */
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int j;
for (j = 0; j < argc; j++)
printf("argv[%d]: %s\n", j, argv[j]);
exit(EXIT_SUCCESS);
}
This program can be used to exec the program named in its command-line argument:
We can use the second program to exec the first as follows:
Code:
$ cc myecho.c -o myecho
$ cc execve.c -o execve
$ ./execve ./myecho
argv[0]: ./myecho
argv[1]: hello
argv[2]: world
We can also use these programs to demonstrate the use of a script interpreter. To do this we create a script whose "interpreter" is our myecho program:
It seems to me you still don't quite understand how the shebang line works.
This reminds me of a joke:
Quote:
A physicist, a chemist and a programmer talk during a lunch break.
The physicist: my profession is most important, God said "let it be light" and there was light, he must be a great physicist.
The chemist: but before that God separated the heavens from the earth, he must be a great chemist.
The programmer: And the chaos, who created the chaos?!
Yes, your summary is correct but one minor point: execve is a system call (part of the kernel) and as such described in the man section 2: execve(2). The exec* family of library functions are glibc frontends to the execve syscall and described in the man section 3: exec(3).
Yes, your summary is correct but one minor point: execve is a system call (part of the kernel) and as such described in the man section 2: execve(2). The exec* family of library functions are glibc frontends to the execve syscall and described in the man section 3: exec(3).
Now I don't know to what Stack Overflow answer are you referring to.
So the kernel takes care of shebang and it calls execve(2) directly. Thank you for the clarification, I corrected the post.
The one you were citing in #15 before you edited your post. I amended #16 to include the direct link to the answer.
Thank you, I completely forgot that I posted that link.
Also, bash calls execve(2), which is a system call (part of the kernel). It finally arrived to me. Unless, of course, bash is explicitly invoked, and then it does not call execve(2) and the file must be a bash script. It can't be a sh or a csh script since bash is invoked directly.
I thought that a "system call" means a call initiated by the system, if you can imagine, when in fact it means a call to the system, aka kernel, a call to the inner functions of the operating system.
interpreter will be invoked with the following arguments:
interpreter [optional-arg] filename arg...
where arg... is the series of words pointed to by the argv argument of execve().
Filename is contained in argv[0] in execve(2), and it does not appear two times in the argument list of the interpreter.
The FAQ is unclear on a detail: was the Berkeley hack that created the shebang done inside execve(2)? Because otherwise, since execve(2) is called from the shell, the kernel has no chance to intervene when the file is not binary to test the shebang. Also, is the default shell, when the shebang is missing, decided in the calling shell? For example, bash would have to choose sh. This would be the solution that would fit the current data.
Filename is contained in argv[0] in execve(2), and it does not appear two times in the argument list of the interpreter.
I can only recommend you to read that man page again, carefully, and including the example c code too. And also you can modify those example files to examine execve better.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.