LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This 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


Reply
  Search this Thread
Old 12-16-2021, 03:40 AM   #16
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,678

Rep: Reputation: Disabled

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

Last edited by shruggy; 12-23-2021 at 12:31 PM.
 
2 members found this post helpful.
Old 12-17-2021, 01:22 PM   #17
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
when command can be a binary or a script
$ 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
Code:
    $ command
but it does not invoke it when used explicitly
Code:
    $ bash command
    $ bash echo a
    /usr/bin/echo: /usr/bin/echo: cannot execute binary file
https://linux.die.net/man/2/execve

Quote:
Interpreter scripts

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:
Code:
/* execve.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    char *newargv[] = { NULL, "hello", "world", NULL };
    char *newenviron[] = { NULL };

   if (argc != 2) {
fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
exit(EXIT_FAILURE);

}
newargv[0] = argv[1];

execve(argv[1], newargv, newenviron);
perror("execve"); /* execve() only returns on error */
exit(EXIT_FAILURE);
}
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:
Code:
$ cat > script.sh
#! ./myecho script-arg
^D
$ chmod +x script.sh
We can then use our program to exec the script:
Code:
$ ./execve ./script.sh
argv[0]: ./myecho
argv[1]: script-arg
argv[2]: ./script.sh
argv[3]: hello
argv[4]: world
execve can only find the interpreter and the script-arg
in the shebang of the file received as its first argument

Last edited by doru; 12-27-2021 at 02:53 AM.
 
Old 12-17-2021, 01:40 PM   #18
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
when you write/execute:
Code:
bash command
the real command is bash and "command" is just an argument.
 
Old 12-18-2021, 10:46 AM   #19
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
Quote:
Originally Posted by shruggy View Post
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?!
What does "SO answer" mean?

Is the summary in my last post correct?
 
Old 12-18-2021, 10:49 AM   #20
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,678

Rep: Reputation: Disabled
Ah sorry, SO means Stack Overflow.

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).

Last edited by shruggy; 12-23-2021 at 12:28 PM.
 
1 members found this post helpful.
Old 12-19-2021, 01:46 AM   #21
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
[DELETED]

Last edited by doru; 12-23-2021 at 12:00 PM.
 
Old 12-23-2021, 12:02 PM   #22
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
Quote:
Originally Posted by shruggy View Post
Ah sorry, SO means Stack Overflow.

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.
 
Old 12-23-2021, 12:33 PM   #23
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,678

Rep: Reputation: Disabled
Quote:
Originally Posted by doru View Post
Now I don't know to what Stack Overflow answer are you referring to.
The one you were citing in #15 before you edited your post. I amended #16 to include the direct link to the answer.

Last edited by shruggy; 12-23-2021 at 01:44 PM.
 
1 members found this post helpful.
Old 12-26-2021, 03:39 AM   #24
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
Quote:
Originally Posted by shruggy View 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.

I have improved my summary in post #17.

Last edited by doru; 12-26-2021 at 05:55 AM.
 
Old 12-26-2021, 07:09 AM   #25
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 138

Original Poster
Rep: Reputation: 19
The manual of execve(2) is wrong.
Quote:
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.

Last edited by doru; 12-27-2021 at 02:38 AM.
 
Old 12-26-2021, 08:22 AM   #26
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
Quote:
Originally Posted by doru View Post
The manual of execve(2) is wrong.

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.
 
  


Reply

Tags
env, infinite, loop, script, shebang, variable



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] infinite loop that isnt infinite? frieza Programming 2 10-27-2010 02:16 PM
RPM dependency failure: /usr/bin/env instead of /bin/env anoosh3000 Linux - Software 1 04-10-2009 05:34 AM
fetchmail stuck in infinite loop Prommy Linux - Software 0 02-17-2004 08:15 AM
Sendmail build - infinite loop?? kstarks Linux - Software 0 10-02-2003 07:13 AM
How do i ping an address in Konsole w/ out an infinite loop?? vbp6us Linux - Networking 1 03-02-2003 04:26 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

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

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration