The UNIX and Linux Forums  


Go Back   The UNIX and Linux Forums > Top Forums > UNIX for Dummies Questions & Answers > Answers to Frequently Asked Questions > Tips and Tutorials
.
google unix.com



Tips and Tutorials Helpful articles from our Users.

More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
Learning Oracle ADF: A Beginner's Story iBot Oracle Updates (RSS) 0 04-06-2008 06:10 AM
CEP and the Story of the Fish iBot Complex Event Processing RSS News 0 12-17-2007 05:50 AM
Bangkok Post Article: The story behind the Linux operating system Neo News, Links, Events and Announcements 0 04-05-2003 10:05 AM

 
English Japanese Spanish French German Portuguese Italian Dutch Swedish Russian Norwegian Hungarian Hebrew Danish Bulgarian Greek Powered by Powered by Google
 
LinkBack Thread Tools Search this Thread Rate Thread Display Modes
Prev Previous Post   Next Post Next
  #1 (permalink)  
Old 03-31-2007
Perderabo's Avatar
Perderabo Perderabo is offline Forum Staff  
Unix Daemon
  
 

Join Date: Aug 2001
Location: Ashburn, Virginia
Posts: 9,126
The Whole Story on #! /usr/bin/ksh

Introduction

Originally, we only had one shell on unix. When ran a command, the shell would attempt to invoke one of the exec() system calls on it. It the command was an executable, the exec would succeed and the command would run. If the exec() failed, the shell would not give up, instead it would try to interpret the command file as if it were a shell script. This works fine as long as there is only one shell on the system. But what if you are using one shell as your interactive and want to run a script written in another shell's language?

This is where the #! trick comes in. The idea of using # to represent a comment originated with csh and was quickly added to the bourne shell. Now all shells know to ignore stuff after a #. So we can add a leading line something like "#! /usr/bin/ksh". To the shell this line is just a comment. But if the kernel tries to execute a file with this line, it will exec the specified interpreter and pass the script to it. So shell scripts become executable pretty much like real executables are. Now when a shell tries to exec a shell script, it succeeds.

What if you leave off the #! line? Well, the kernel exec will fail. Your average shell will then try to run the script itself. A few shells will try to inspect the script to try to guess the language. This is not good. You may be running ksh as your interactive shell and writing ksh scripts. If you later switch to bash as an interactive shell, some of your scripts may continue to run while others may fail. Also the line is a comment that provides an important clue to a programmer who looks at the script to understand it. Knowing which language the author is attempting to use is a big help.

While I have used the term "shell", actually this technique can be used with many programs that are not shells. Here is a "script" to display a multiline message:
Code:
#! /usr/bin/cat
Line 1
Line 2 
Line 3
This will display that "#! /usr/bin/cat" line, but other than that, it works fairly well.

Passing an Argument

You can pass a single argument like this:
#! /usr/local/bin/perl -w
But, in general, you are limited to one argument. On most systems, a line like: "#! /some/interpreter -a -b" will result in "-a -b" being passed as a single argument. However, the single argument is not limited to starting with a hyphen. We can improve on our message script:
Code:
#! /usr/bin/sed 1d
Line 1
Line 2 
Line 3
Example

Let's put all of this together with an example. Here is a perl script that I will call perlargs:
Code:
#! /usr/local/bin/perl -w

#! /usr/local/bin/perl -w
print "script name is ", $0, "\n";
while (@ARGV) {
        $ARGV = shift @ARGV;
        print "argument ", $i++,  " is ", $ARGV, "\n";
}

system "ps -f -ww";

The -w asks perl issue warning messages. The script simply displays its arguments, then runs the ps command. When I run it, I get:
Code:
$ ./perlargs one two three
Name "main::i" used only once: possible typo at ./perlargs line 10.
script name is ./perlargs
argument 0 is one
argument 1 is two
argument 2 is three
                 UID        PID   PPID    STIME TTY     TIME CMD
                 perderabo   69      1 17:47:28 n01  0:00.24 /bin/ksh -l
                 perderabo  201     69 18:28:22 n01  0:00.03 /usr/local/bin/perl -w ./perlargs one two three
                 perderabo 2055    201 18:28:22 n01  0:00.01 ps -f -ww
$
Notice that the perl process was called with 5 arguments. The 2nd argument is the name of the script. It is up to the perl process to to present the final 3 arguments as the argument list seen by the script. Also realize the kernel started the perl process. After that, it is up to perl to open the script and read it and execute each line. This is why scripts need to be readable. You cannot execute a non-readable script.

Conclusion

This should be enough information to understand what is happening with those #! lines. In the following posts, I will add details on various aspects of the process.
 

Bookmarks

Tags
perl, perl shift, shebang, shift, shift perl

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes Rate This Thread
Rate This Thread:

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On




All times are GMT -4. The time now is 04:05 PM.


Powered by: vBulletin, Copyright ©2000 - 2006, Jelsoft Enterprises Limited. Language Translations Powered by .
vBCredits v1.4 Copyright ©2007 - 2008, PixelFX Studios
The UNIX and Linux Forums Content Copyright ©1993-2009. All Rights Reserved.Ad Management by RedTyger

Content Relevant URLs by vBSEO 3.2.0