Sponsored Content
Top Forums UNIX for Beginners Questions & Answers Answers to Frequently Asked Questions Tips and Tutorials The Whole Story on #! /usr/bin/ksh Post 302112884 by Perderabo on Sunday 1st of April 2007 12:00:31 AM
Old 04-01-2007
Part 4: Odds and Ends

Invented by Dennis Ritchie

The concept originated with Dennis Ritchie:
Code:
>From dmr Thu Jan 10 04:25:49 1980 remote from research
The system has been changed so that if a file being executed
begins with the magic characters #! , the rest of the line is understood
to be the name of an interpreter for the executed file.
Previously (and in fact still) the shell did much of this job;
it automatically executed itself on a text file with executable mode
when the text file's name was typed as a command.
Putting the facility into the system gives the following
benefits.

1) It makes shell scripts more like real executable files,
because they can be the subject of 'exec.'

2) If you do a 'ps' while such a command is running, its real
name appears instead of 'sh'.
Likewise, accounting is done on the basis of the real name.

3) Shell scripts can be set-user-ID.

4) It is simpler to have alternate shells available;
e.g. if you like the Berkeley csh there is no question about
which shell is to interpret a file.

5) It will allow other interpreters to fit in more smoothly.

To take advantage of this wonderful opportunity,
put

	#! /bin/sh

at the left margin of the first line of your shell scripts.
Blanks after ! are OK.  Use a complete pathname (no search is done).
At the moment the whole line is restricted to 16 characters but
this limit will be raised.


From uucp Thu Jan 10 01:37:49 1980

BSD picked it up from Version 8 of Research Unix and made it popular.

What to Call the Concept

Eventually, the #! line came to be called the "sharpbang" line and sharpbang can still be found in some kernel source code. This was shortened to "shebang" somehow. I would have expected "shabang" but it seems that "shebang" is what most people use. A few people seem to use "hashpling". Apparently, SCO has a switch called "hashplingenable" which must be set at kernel build time to enable this feature. And I have been told that some folks use the term "hashbang". (Anyone for sharppling?)


Special Rules for Perl

Recall that multiple arguments on the #! line are often passed as a single argument. If perl is passed an argument like "-a -b". it will break it apart and act like "-a" and "-b" had been passed. Also perl does not ignore the #! line. Perl will inspect it and will turn on any switches it finds. This helps compensate for systems with a very short #! line limit. perl will scan a #! line until it finds the string "perl". Then it starts scanning for switches. During this scan, "-*" and "- " are ignored. If the #! line does not contain the string "perl", perl will process the #! line the way a Unix kernel would and thus invoke the proper interpreter.

Handling Different Paths

Let's say some systems have, for example, /opt/perl/bin/perl and /usr/local/bin/perl. How to write a perl script? My feeling is that it falls on the System Administrator to provide the needed commonality. I would put perl in /usr/local/bin. If the perl installation procedure puts perl in /opt/perl/bin/perl, that is fine... but then I would a symbolic link in /usr/local/bin pointing to the perl executable. Same thing with perl. So on all systems under my control "#! /usr/local/bin/python" is guaranteed to work or python is not available on that system. Same thing with perl, etc. It is rare for me to add a link to a directory like /usr/bin. But I will for do this for ksh and bash should an OS be missing either shell. And I always ensure that bash and ksh will work if stuff like /opt or /usr/local is unmounted. These shells are the only cases where I will override the installation procedure if I must. So on my systems stuff like this will work:

#! /usr/bin/ksh
#! /usr/bin/bash
#! /usr/local/bin/perl

And until this stuff works, I do not consider the OS installation to be complete. Scripts imported from the outside world may need a tweak to run if they expect the interpreters elsewhere. But programs like "configure" will find perl if it is in /usr/local/bin. So this is my approach. But there are other ideas...

Another approach is to use a #! line that result in an intermediate program invoking the desired interpreter after a PATH search. The most frequently used example would be something like "#! /usr/bin/env perl". This assumes that env is in /usr/bin (not the case with, for example, Unicos, but my above comments apply to env and I would add the required links). It also assumes that perl is on the PATH somewhere. A more elaborate example is
Code:
#! /usr/bin/sh -- # -*- perl -*- -p
eval 'exec perl -S $0 ${1+"$@"}'

And even more elaborate examples are in the book Programming Perl by Larry Wall, et al.

And the Posix Standard on this page checks in with
Quote:
Furthermore, on systems that support executable scripts (the "#!" construct), it is recommended that applications using executable scripts install them using getconf -v to determine the shell pathname and update the "#!" script appropriately as it is being installed (for example, with sed).
See the linked page for their suggested installation script.

The ksh expanded environment

Let's say that you use ksh exclusively and you have a script and you leave off the "#!". Your interactive ksh will try to exec the script and fail. So your interactive ksh with fall back to running your script as a ksh script. It does this by forking a copy of itself to create a subshell. This forked subshell can then, in effect, expand on the standard Unix concept of "environment". When a process exec's another process, the new program inherits a bunch of stuff, open files, current directory, and the ENVIRONMENT. The ENVIRONMENT is a set of strings which, by convention, take the form of variable settings, like: PATH=/usr/bin:/usr/local/bin. But the forked ksh subshell knows everything about the parent subshell. Early ksh version exploited this by having ways to export arrays, aliases, and functions. This requires avoiding the #! line and thus living with the problems this creates. Most sites strongly encourage the use of the #! line and this undermines the ksh expanded environment concept. And it confused beginners who saw stuff like exported aliases mentioned in the docs. Recent versions of ksh have retreated from the expanded environment concept. So my suggestion is to forget about ksh exported arrays, aliases, and functions and use that #! line.
These 4 Users Gave Thanks to Perderabo For This Post:
 

8 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

#!/usr/bin/ksh Command Interpreter in a sh script

Hi, I have a developer that is trying to start a script with sh "scriptname". In the script, he is specifying #!/usr/bin/ksh as the command interpreter. For some reason sh is ignoring the #!/usr/bin/ksh. We are running Solaris 8. Does anyone have any ideas what could be causing this? Here... (3 Replies)
Discussion started by: ckeith79
3 Replies

2. UNIX for Dummies Questions & Answers

ksh: /usr/bin/ls: arg list too long

I am using IBM AIX unix version 4.3.3.0. In a directory there are many files with different patterns. When I am trying to execute the command, ls -l with the file pattern, which have fewer files it gives the desired result. However when I am trying to execute the same command for file pattern,... (2 Replies)
Discussion started by: jitindrabappa
2 Replies

3. Solaris

How do I link ld in /usr/ucb/ to /usr/ccs/bin?

Hi all, below is the problem details: ora10g@CNORACLE1>which ld /usr/ucb/ld ora10g@CNORACLE1>cd /usr/ccs/bin ora10g@CNORACLE1>ln -s /usr/ucb/ld ld ln: cannot create ld: File exists ora10g@CNORACLE1> how to link it to /usr/ccs/bin? (6 Replies)
Discussion started by: SmartAntz
6 Replies

4. Shell Programming and Scripting

!/usr/bin/ksh error

Usually we use !/usr/bin/ksh at the start of the script.But if I am having this stuff in the scripts and calling one script from other its not working.What may be the reason behind it ? xyz.ksh #!/usr/bin/ksh echo "Hi" abc.ksh #!/usr/bin/ksh echo "I am fine" ksh xyz.ksh Its... (4 Replies)
Discussion started by: dr46014
4 Replies

5. AIX

aix:ksh: /usr/bin/rm: 0403-027 The parameter list is too long.

Hi, I am getting the below error message When i am trying to delete the files from the directory.Could you please guide me? rm *.aud ksh: /usr/bin/rm: 0403-027 The parameter list is too long. and find /oracle/admin/testP/adump/*.aud -mtime +5 -exec rm {} \; ksh: /usr/bin/find:... (3 Replies)
Discussion started by: nokiae63
3 Replies

6. OS X (Apple)

When to use /Users/m/bin instead of /usr/local/bin (& whats the diff?)?

Q1. I understand that /usr/local/bin means I can install/uninstall stuff in here and have any chance of messing up my original system files or effecting any other users. I created this directory myself. But what about the directory I didn't create, namely /Users/m/bin? How is that directory... (1 Reply)
Discussion started by: michellepace
1 Replies

7. Shell Programming and Scripting

/usr/bin/ksh -E

I saw one script using the first line as below /usr/bin/ksh -E I have used -x for debug but couldn't find what is this -E option for ? Pls let me know what is this -E used for Thanks RL (1 Reply)
Discussion started by: reldb
1 Replies

8. BSD

FreeBSD: /usr/bin/ld not looking in /usr/local/lib

I'm not sure if this is the default behavior for the ld command, but it does not seem to be looking in /usr/local/lib for shared libraries. I was trying to compile the latest version of Kanatest from svn. The autorgen.sh script seems to exit without too much trouble: $ ./autogen.sh checking... (2 Replies)
Discussion started by: AntumDeluge
2 Replies
All times are GMT -4. The time now is 11:02 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy