Linux – Shebang or Not Shebang

environment-variableslinuxscriptingshebangshell

I want to use a program in the shebang, so I create a script named <myscript> with:

#!<mypgm>

I also want to be able to run <mypgm> directly from the command prompt.

<mypgm> args...

So far, no issue.

I want to be able to run <myscript> from the command prompt with arguments.

<myscript> blabla

In turn, the shebang makes <mypgm> being called with the following arguments:

<mypgm> <myscript> blabla

Now, I need to know when <mypgm> <myscript> blabla is called using the shebang, or not:

myscript blabla # uses the shebang
-or-
<mypgm> myscript blabla   # directly in the command prompt.

I looked at the environment variables (edit: <=== wrong assertion (¬,¬”) ), at the process table (parent process too) but didn't find any way to make a difference.

The only thing I found so far is:

grep nonvoluntary_ctxt_switches /proc/$$/status

When this line is just after the shebang, the value is often 2 (sometimes 3) when called through the shebang, and 1 (sometimes 2) with the direct call. Being unstable and dependent on process scheduling (the number of times the process was taken off from its CPUs), I am wondering if anybody here might have a better solution.

Best Answer

Instead of having myprg magically detect whether it is being used in a shebang, why not make that explicit by using a command-line flag (such as -f) to pass it a file as a script?

From your example in the comments:

In the calc theoretical example above. calc PI + 1 should return 4.14159... Now adding the support for the shebang (i.e. a filename as the first parameter) would return the calculation contained into the file.

Make calc take a script file through -f and then create scripts with:

#!/usr/local/bin/calc -f
$1 + 1

Let's say you call this file addone.calc and make it executable. Then you can call it with:

$ ./addone.calc PI
4.141592...

That call will translate into an invocation of /usr/local/bin/calc -f ./addone.calc PI, so it's pretty clear which argument is a script file and which is a parameter to the script.

This is similar to how awk and sed behaves.

A similar (but opposite) approach is to have calc take a script file argument by default (which simplifies its use with a shebang), but add a command-line flag to use it with an expression from an argument. This is similar to how sh -c '...' works.