eval ‘exec /usr/bin/perl -wS $0 ${1+“$@“}‘

There are too many tricks involved in these few lines of programs.
It really takes a lot of skill to understand.

Let me explain first, the line starting with # indicates that the line is a comment line in the shell, but if the script has executable permission and is
executed directly (such as the exec* series system calls of C, or directly typing the script name under the shell) , which acts
as an instruction to the interpreter. In this example, the specified interpreter is /usr/bin/perl (assuming that
Perl has been installed on the user's system and the installation location is /usr/bin/perl, otherwise the script cannot be executed anyway)

when a user When you get the script, depending on your personal habits and knowledge level, there may be the following three ways to execute the script:

Execution method 1, after ./foo
uses chmod +x foo to give the script executable permission, you can use this method to execute.
As mentioned earlier, when this method is executed, the OS will follow the instruction of #! on the first line of the script to find the
position of the interpreter, which is /usr/bin/perl here, so once /usr/bin/perl is found, The next two lines
eval 'exec /usr/bin/perl ......' if $rrunning_under_some_shell; will be
executed as Perl code. Because the variable $running_under_some_shell has not been defined, its value is
undef, that is to say, the if modifier will fail, and the eval sentence will not be executed. So in this case,
if Perl has been installed in the system and the location of Perl is in /usr/bin/perl, these two lines are equivalent to nothing
Note that newlines can be added arbitrarily as blanks in Perl, so the combination of these two lines is actually a complete
statement. But there is a trick here, it is intentionally written in two lines for reasons explained below.

Execution mode 2, perl foo
can be executed in this way when the user already knows that the script is a Perl script. This method
is basically the same as the first method, the only difference is that #!/usr/bin/perl will be treated as a normal Perl comment.

Execution mode 3, sh foo
In this mode, the user mistakenly thinks that foo is a shell script, so the shell is invoked to execute the script.
At this time, the first line #! will be ignored by the shell as a normal comment. In this case, eval will be interpreted as a
shell command, and its parameter 'exec /usr/bin/perl ....' is a legal shell command,
whose function is to re-invoke /usr/bin /perl to interpret the script, the shell parameter $0 is in this case
the name of the script itself. And "$@" is equal to "$1" "$2" "$3" ... That is, the parameters of the script (Note).
That is to say: if the script is mistakenly executed as a shell script, that's fine, because it's also a
legal Perl script
. A correct shell statement. Because once the eval line is successfully executed, exec will overwrite the current process,
so the if line has no chance to execute at all, and there will be no error.

Summarize:
The purpose of writing this way is to make the script interpretable by both perl and shell. If it
is interpreted by perl, it is correct, but even if it is interpreted by shell, not only will there be no errors, but the same
result will be obtained.

Note: This place is usually written as "$@" but in your example it is written as ${1+"$@"} for some reason, maybe there is another meaning, I checked, in my system (Debian 4.0),
two There are all kinds of writing methods. If you are interested, you can go to the shell
version and ask about the difference between "$@" and ${1+"$@"}.

Guess you like

Origin blog.csdn.net/world_hello_100/article/details/109506251