1

I just barely landed a job where 80% of my work is in the Unix Environment. I'm learning how to shell script. I'm really having a hard time trying to set the header on my practice scripts. If you take a look at my first script, it accepts the header. I created the same header again on a new script and it give me a bad interpreter. Both were created executables using the command chmod u+x nameOfScript. Both scripts are in the same location. So I really don't understand what's going on. Take a look:

parallels@ubuntu:~$ cat firstApp.ksh

#!usr/bin/ksh

# this prints the first line.

echo "Hi this is my first app, which me luck!"
echo "i hope this works again"    
#this is a comment as well

Now look at my other script which doesn't work, same header

parallels@ubuntu:~$ cat thirdApp.ksh
#!usr/bin/ksh

#print this

echo "I'm gonna try this again"

When I run this script, it runs...

parallels@ubuntu:~$ ./firstApp.ksh
Hi this is my first app, which me luck!
i hope this works again

But when I run this it fails

parallels@ubuntu:~$ ./thirdApp.ksh
bash: ./thirdApp.ksh: usr/bin/ksh: bad interpreter: No such file or directory

I'm copying the header exactly on both scripts, when I look for the Korn shell header I get this

parallels@ubuntu:~$ which ksh
/usr/bin/ksh
parallels@ubuntu:~$ 

Please let me understand what I'm doing wrong. Unix is still very new to me.

OPJ
  • 123
  • 2
  • 13

2 Answers2

3

The commands will only work when run in the root directory. You need:

#!/usr/bin/ksh

with the full absolute path name (starting with a /), not a relative pathname as you have with:

#!usr/bin/ksh

Note that to be relevant, the shebang (#!) must be the first two characters in the file. Leading blank lines, or blanks on the line before the #, render it irrelevant; the kernel looks to see if the first two characters are #! and if they are not, ignores the shebang line.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • but how is it that I both scripts in the same location but one passes and one fails...thats what i really don't understand, and i only been messing with Unix/Linux for 2.5 months so please bare with me – OPJ Sep 11 '14 at 17:17
  • I'm rereading the question. Are there any blank lines at the start that we can't see? The `#!` shebang must be the first two characters in the file to be relevant, and the path must have a `/` at the start for sanity's sake. – Jonathan Leffler Sep 11 '14 at 17:19
  • there is a blank line on the first one before the header – OPJ Sep 11 '14 at 17:21
  • 2
    A blank line before the shebang (`#!`) makes all the difference in the world. The shebang must be the first two characters in the file. – Jonathan Leffler Sep 11 '14 at 17:24
  • 1
    That sounds like the working one has the blank line, which would explain it. It isn't using the shebang at all in that case and is being run by the current (`bash`) shell. – Etan Reisner Sep 11 '14 at 17:29
  • hmm i see, but why would it still run even being the second lin in the script? – OPJ Sep 11 '14 at 17:29
  • 1
    When the kernel refused to handle the file because it didn't start with the shebang, the Korn shell decided to treat it as a script and read the script normally. The blank line didn't matter; the comment line starting `#!` didn't matter; the rest worked. – Jonathan Leffler Sep 11 '14 at 17:31
  • What does the shebang do anyways? i was assuming it imports the ksh "libraries" – OPJ Sep 11 '14 at 17:44
  • 'What does shebang do' is an excellent question. Please search SO to see if there's already an answer, and add a comment here with a link to it if you find one. If not, I'll add to my answer later; I can't afford to do it justice now. Succinctly, though, the kernel gets asked to execute the script, recognizes it isn't a binary (wrong magic number), recognizes the shebang as a magic number, and arranges to run the program (Korn shell in this case) with the script file as its source of data. – Jonathan Leffler Sep 11 '14 at 18:14
  • This works for other programs than shells too: I've played with executable `makefile`s which start `#!/usr/bin/make -f`, for example. Then, running `./makefile` runs `make`. It makes more sense if the makefile is called `something.mk` (so the alternative was typing `make -f something.mk`). – Jonathan Leffler Sep 11 '14 at 18:14
  • Try [How does the `#!` shebang work?](http://stackoverflow.com/questions/3009192/how-does-the-work) – Jonathan Leffler Sep 11 '14 at 18:38
1

In Unix, the #! located in the first column of the first line of a script is called the shebang. This is the mechanism that allows the Unix executor to figure out the program you want to use to process your script. If you don't have a shebang, your script will execute with your default shell.

If you don't have the shebang in your shell script, but the user's default shell is Kornshell, everything will be okay. If the user's default shell is C-shell, your script won't work. Therefore, you should always use the shebang.

The problem with the shebang is that it doesn't use your $PATH to find the program. Instead, you must have the hard coded path. If you had:

#! usr/bin/ksh

And, you're in the /home/opj directory, it will look for /home/opj/usr/bin/ksh. This is the problem of the non-working script. You need that beginning /:

#! /usr/bin/ksh

That is, of course, assuming that your Kornshell application is under /usr/bin/ksh and not under /bin/ksh. Most shells are under the /bin directory. Check to make sure it's either /bin/ksh or /usr/bin/ksh.

One way around this limit is to depend upon env which is almost always under the /usr/bin. When you use env, env will search for the program along your path, and then use that as the interpreter to your script:

#! /usr/bin/env perl

My script will find the Perl interpreter whether it's under /bin/perl, /usr/bin/perl, or /usr/local/bin/perl. In fact, Perlbrew depends heavily upon this behavior.

The disadvantage is that you can't force someone to use a particular version of your interpreter. If I have #! /bin/ksh, that's what my script will use.

One more thing. Why are you using Kornshell instead of BASH. BASH and Kornshell are 95% identical in syntax, but BASH is just more ubiquitous now. I use Kornshell because that's what I learned way back in the last two decades of the 20th century. I even installed Kornshell on my Mac just because I like its features that aren't in Bash.

However, I recommend new users to learn BASH simply because if they have an issue, there's a lot more resources out there.

David W.
  • 105,218
  • 39
  • 216
  • 337