This is a read-only archive. Find the latest Linux articles, documentation, and answers at the new Linux.com!

Linux.com

Feature: Shell & CLI

Korn -- an extended shell

By Mark Alexander Bain on May 05, 2008 (4:00:00 PM)

Share    Print    Comments   

Everyone knows what a Linux shell is -- you open up a Linux terminal window (such as Konsole or xterm), type in some commands, and there you are, using your Linux shell. Write your commands to a file, make it executable, run it, and you're a shell programmer. But did you know that there are different shells that you can use, and that each shell operates in a slightly different way? My personal favorite is the Korn shell; by the end of this article, it may be your favorite as well.

By default, Linux generally uses bash, the Bourne again shell. Before moving from that to the Korn shell, consider why you might want to change shells. The Korn binary is smaller than the bash binary, and many functions (such as echo and getopts) are built into the shell rather than separate executables, which means that Korn uses less memory to run and can be quicker as well. In addition, Korn is completely backward compatible with bash. That means that even if you never use any of the Korn functionality, you can still use all of the commands that you're already used to. In addition, Korn offers useful features like built-in arithmetic expressions, compound variables, discipline functions, and coprocesses, all of which we'll cover in a moment.

With Korn's advantages, you may wonder why Linux uses bash by default. Quite simply, the reason is historical. The default shell for Unix was the Bourne shell (or sh), so it was logical that the default shell for Linux should be the Bourne again shell. Of course, when talking about the default, we're actually just talking about your entry in /etc/passwd. If your entry reads something like:

bainm:x:1000:100:Mark Alexander Bain:/home/bainm:/bin/bash

then your default shell is the Bourne again shell, but if it reads something like:

bainm:x:1000:100:Mark Alexander Bain:/home/bainm:/bin/ksh

then your default shell is the Korn shell. You can also check which you're using by querying your system's environment:

> env | grep SHELL SHELL=/bin/bash

Before you try changing your shell to Korn you may want to make sure that it is actually installed on your system. The easiest way to do that is to look for the executable:

> ls -l /bin/bash /bin/ksh ls: /bin/ksh: No such file or directory -rwxr-xr-x 1 root root 677184 2006-12-11 21:20 /bin/bash

If the Korn executable is not there, you can use your distro's installation mechanism to get it; for example, use Yast on SUSE or apt-get install ksh on Debian. Then, to change to the Korn shell, just type /bin/ksh. To stop, type exit at the command line and you're back to bash. You can make Korn your default by changing your information in /etc/passwd, but it's probably safer to do this through your distro's user management software. However, you don't need to change to the shell in order to use it; instead, you can create a script and tell it to use Korn by adding one line at the start of the file:

#!/bin/ksh

Let's now see what additional functionality you get when you start using Korn, starting with Korn's built-in arithmetic expressions.

Built-in arithmetic expressions

If you've tried to carry out any maths using bash you'll have had to have done it indirectly, with an expression like answer=$( echo 1.5 + 1.7 | bc ) or answer=$( echo 1.5 1.7 | awk '{print $1 + $2 }' ). If you use Korn, you'll be able to do that directly by typing answer=$(( 1.5 + 1.7 )) or (( answer = 1.5 + 1.7 )).

You can use this ability in conjunction with some other mathematical functions, such as abs, acos, asin, atan, cos, cosh, exp, int, log, sin, sinh, sqrt, tan, and tanh. So, for example, you could create variable containing a very accurate value for pi with the expression (( pi = 4.0 * ( 4.0 * atan(1.0/5.0) - atan(1.0/239.0) ) )). This would calulate pi to be 3.14159265358979324.

Compound variables

We've just seen how to use a variable to store the value of pi. Let's examine the variables that we might want to use to define a circle using the Korn shell and our pi variable:

> radius=30 > (( circumference = 2 * pi * radius )) > (( area = pi * radius * radius ))

As you see, you do not need to use the $ sign when using variables; you can if you want to, but you don't need to. In this expression, the variable circumference would now contain 188.495559215387594 and area would contain 2827.43338823081392.

Suppose you want to group these variables together, maybe prefixing each variable with the letters "circle_". With Korn you can use a single variable to do the job -- a compound variable:

> circle= > circle.radius=30 > (( circle.circumference = 2 * pi * circle.radius )) > (( circle.area = pi * circle.radius * circle.radius ))

You can use this technique to do more than just neaten up variables; you can use it to create the structures and records that you see in many programming languages:

> driverx=( name="" float wage=145.50 integer travel_radius=50 )

Here we've defined a compound variable as a structure and defined a data type for each field, and given each of them a default value. Next we can use our structure to build a record set:

> eval "driver01=$driverx" > driver01.name="Bill" > eval "driver02=$driverx" > driver02.name="Fred" > (( driver02.wage = ${driverx.wage} * 1.10 )) # Let's give Fred a pay rise > print "${driver01.name} \$${driver01.wage} ${driver01.travel_radius} miles" Bill $145.50 50 miles > print "${driver02.name} \$${driver02.wage} ${driver02.travel_radius} miles" Fred $160.05 50 miles

Discipline functions

Not only can you assign multiple values to a single variable, but with Korn you can even associate functions with one -- Korn's discipline functions.

A Korn variable can have three discipline functions -- get, set, and unset -- which are executed when the variable is read, written to, or removed. There's also one big difference between these and other shell functions -- these functions don't output anything directly; you'll need make use of the Korn special variable .sh.value. Changing the value of .sh.value from within your function changes the value of your variable. So, using discipline functions, the method for calculating the circumference of a circle becomes:

> function circle.circumference.get { (( .sh.value = 2 * pi * circle.radius )) }

This function can be defined on the command line for use in the current shell, or written into a script file, but once done you only have to change the value for the radius variable to change the circumference variable:

> circle.radius=1 > echo ${circle.circumference} 6.28318530717958648 > circle.radius=20 > echo ${circle.circumference} 125.66370614359173

In a very short time you'd be able to create a set of functions that calculates the area and circumference when you input the radius; the area and radius when you input the circumference; and the circumference and radius when you input the area -- all using just the three variables circle.area, circle.circumference, and circle.radius.

Next, we'll just look at something else that you may not have come across before, but which you may find useful -- the coprocess.

Coprocesses

If you're familiar with bash, you already know that a pipe, represented by |, allows the output of one process to be fed as the input to another. A Korn coprocess is simply a two-way pipe. With it you can make background and foreground processes communicate with each other. All you have to do is to send one process to the background (using |&), then use print -p to send information to the process and read -p to obtain outputs from it.

The first thing to do is to create the script to run in the background. The following script accepts a numerical input and keeps a running total:

#!/bin/ksh total=0 while [ "" == "" ] do read input (( total = total + input )) echo $total done

If you save this as keep_count.ksh, you can start using it in the following way, either from the command line or from within a script:

./keep_count.ksh |& print -p 2 read -p x # x will contain 2 print -p 10 read -p x # will now contain 12

You can have as many processes running in the background as you want. The only problem is working out how to communicate to each of them -- except that it isn't a problem. The secret is to redefine each pipe's file descriptors:

./ keep_count.ksh |& exec 4>&p # Redefine the input exec 5<&p # Redefine the output print -u4 1 read -u5 x # x will contain the value 1 ./ keep_count.ksh |& exec 6>&p exec 7<&p print -u4 1 read -u5 x # x will now contain the value 2 print -u6 1 read -u7 y # y will contain the value 1

A couple of points to finish with

Though we said that Korn had backwards compatibility with bash, there are some differences. For example: history. If you type history 100 in bash then the shell will display the last 100 history entries. If you do the same in Korn, it will display all entries from line 100 of the history file. If you see one of the lines that you want to run again, type r and the line number:

>history 1069 ls -l /lib/ast/ksh 1070 ls -l /bin/ksh93 1071 html2text -style pretty /home/bainm/Articles/Bain_ksh.html | wc -w 1072 grep bainm /etc/passwd 1073 ps -ef | grep firefox 1074 kill -9 3639 >r 1071

One other issue you may find if you start using Korn is that if you press the up-arrow key, then instead of seeing the last command that you typed in, you'll see a set of control characters. The same occurs if you press the left, right, or down arrows. The remedy is simple: edit your /etc/.kshsrc file and add the line set -o emacs. Next time you start the shell the keys will work in the way that you're used to.

Share    Print    Comments   

Comments

on Korn -- an extended shell

Note: Comments are owned by the poster. We are not responsible for their content.

Korn -- an extended shell

Posted by: Anonymous [ip: 89.221.80.85] on May 05, 2008 05:45 PM
Thanks for your short introduction to Korn shell features.
I had heard its name a lot before, but never really considered it as a candidate for my default (and beloved!) shell. Now I'm going to take it seriously into account; I'll start by trying it for a while.
I have loved BASH during my GNU/Linux life; probably I'll also love KSH for the rest of it!

--
Ebrahim

#

Korn -- an extended shell

Posted by: Anonymous [ip: 91.199.241.6] on May 05, 2008 05:55 PM
Sorry, but you say that arithmetics in bash are only possible indirectly, by piping through bc or awk or such. But the following works just fine in bash:

echo $((1+1))

Its documented also, for instance: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-10.html#ss10.2

Cheers

#

Re: Korn -- an extended shell

Posted by: Anonymous [ip: 199.172.169.21] on May 06, 2008 10:24 AM
And in shells that don't have built-in arithmetic, the simplest solution is to call expr, not piping through bc or awk!

#

Korn -- an extended shell

Posted by: Anonymous [ip: 207.203.254.110] on May 05, 2008 06:04 PM
Here is an idea. Rather than start off by attacking one project, why not simply focus on the strengths of what you find delightful on the one you are raving about? Furthermore, if all you use is ksh, then it stands to reason that you will not know all the strengths of bash. Finally, I would summarize by saying rather than get too involved in equations etc in bash, ksh, etc, you would be better off learning something like ruby, perl, or python that gives you much more power than shell script does. Shell scripting can have its place, but the value of having programmatic cross platform solutions makes your work much more reusable.

Haz

#

Re: Korn -- an extended shell

Posted by: Anonymous [ip: 69.12.128.128] on May 05, 2008 06:37 PM
excellent points.

#

Korn -- an extended shell

Posted by: Anonymous [ip: 69.12.128.128] on May 05, 2008 06:34 PM
Can Linux.com please get qualified authors in the future? Not only is this Author wrong about bash's arithmetic (which is basic bash knowledge), but he leaves out lots of expected information. How many people use their shell to do calculating? I would say that floating point arithmetic is the least of my worries when considering a shell. Ksh uses less memory? Most systems these days come with at least 512 mb of RAM, this makes bash's 6mb versus ksh's 4mb a silly point to argue.

#

Re: Korn -- an extended shell

Posted by: Anonymous [ip: 4.249.201.79] on May 05, 2008 07:41 PM
Actually the memory arguement may have merit. If you use linux on an embedded system, and what basic functionality, a possible GUI, and solidstate. You will probably have only a few GB told system. I am not sure what basic performance difference you get and agree with a previous post of using Ruby, Perl, etc.. if you really wish to get powerful scripting.

#

Re(1): Korn -- an extended shell

Posted by: Anonymous [ip: 141.123.223.100] on May 05, 2008 09:43 PM
No, the "embedded" argument doesn't have merit in this case. Yes, embedded systems have less memory and need smaller binaries, but this isn't linuxdevices.com. In general, it's a small subset of the population who are building embedded systems, and the rest of us are tired of hearing about how the embedders have special needs. We get it, your device doesn't have a lot of memory. Cars also have wheels, we don't need to be reminded of it every time someone talks about a car. Frankly, if you've got enough skill to build an embedded system, this article isn't going to bring you anything new. You're already probably familiar with the functionalities, limitations and footprints (feetprint?) of every binary you intend to put into the system. So, pointing out that it uses...GASP...TWO WHOLE MEGS less memory is not something that's going to interest....well, anyone.

#

Korn -- an extended shell

Posted by: Anonymous [ip: 10.0.1.19] on May 05, 2008 09:51 PM
many functions (such as echo and getopts) are built into the shell rather than separate executables

Fact checking, anyone? Both the examples cited are shell-builtins on bash as well..

#

Re: Korn -- an extended shell

Posted by: Anonymous [ip: 91.84.13.8] on May 05, 2008 10:05 PM
$ which echo
/bin/echo

$ bash --version
GNU bash, version 3.2.25(1)-release (i486-pc-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

Doesn't look builtin to me...

#

Re(1): Korn -- an extended shell

Posted by: Anonymous [ip: 69.12.128.128] on May 05, 2008 10:47 PM
$ man bash

Then look under "SHELL BUILTIN COMMANDS" and you'll find echo. But its not the one executed by default.
You can chmod 000 your /bin/echo and still have the ability to echo.

#

Re(1): Korn -- an extended shell

Posted by: Anonymous [ip: 195.135.144.148] on May 06, 2008 01:01 PM
Hm. Looks pretty built-in to me ...


# bash --version
GNU bash, version 3.1.17(1)-release (i486-pc-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.


# which echo
/bin/echo

# mv /bin/echo /bin/echo.bak

# echo test
test

;)

#

Re(1): Korn -- an extended shell

Posted by: Anonymous [ip: 12.34.246.36] on May 06, 2008 03:21 PM
Seems weird that the bash man page would list "echo" in the "SHELL BUILTIN" section, and that the binary would contain the echo usage statement, and that the "builtin" command would return true when executing "echo". ;)

user@host [/home/q0px]
$ strings `which bash` | grep -w echo
echo [-neE] [arg ...]
user@host [/home/q0px]
$ bash -c 'builtin echo'; echo $?

0
user@host [/home/q0px]
$ bash -c 'builtin /bin/echo'; echo $?
bash: line 0: builtin: /bin/echo: not a shell builtin
1


As an aside, A big reason Linux used Bash instead of Korn was that ksh was not considered open source until recently. The AT&T license didn't allow it to be redistributed, or something like that. That's also why pdksh was developed. Recently, though, ksh93 was relicensed under the AT&T "cpl". If anything, it would have made more sense for Linux to use ksh if it was possible, since the POSIX sh specification was *very* strongly influenced by ksh88.


With regards to the difference between ksh93 and Bash - basically ksh has namespaces/compound variables and the ability to load compiled modules (I'm working on a module for shell-native LDAP support, for example), while Bash has the <<< "here variables" and better programmable completion. Ksh93 runs scripts faster than Bash, in general. Essentially, ksh (ksh93, not ksh88) is slightly more capable for script development, while bash is a little more handy as an interactive shell.

#

Korn -- an extended shell

Posted by: Anonymous [ip: 65.19.217.154] on May 05, 2008 10:51 PM
You may want to learn about the 'type' command because your 'which' does not know about shell builtins.
--------
$ type which
which is aliased to `type -path'
$ echo $BASH_VERSION
3.1.17(1)-release
$ type echo
echo is a shell builtin
$
------

And if you want to change your shell, use a shell command! Try 'chsh' :)

sdb

#

Korn -- an extended shell

Posted by: Anonymous [ip: 84.69.189.20] on May 05, 2008 10:53 PM
man bash
> /echo

Go back a few pages, and you'll find echo *IS* a builtin command - along with test, kill, and several others..
Which DOES NOT show builtin commands
For example:
$ ksh
$ which echo
/bin/echo

I don't know the comparable 'whence' command in bash, but in ksh it shows builtins.

#

Korn -- an extended shell

Posted by: Anonymous [ip: 130.76.64.14] on May 05, 2008 11:51 PM
vw004a@nadine ~
$ ksh
\[\033]0;\w\007
\033[32m\]\u@nadine \[\033[33m\w\033[0m\]
$

OK - ksh doesn't treat my PS1 correctly. That's a bad start for my adoption of ksh(1).

#

Korn -- an extended shell

Posted by: Anonymous [ip: 213.41.244.95] on May 06, 2008 06:27 AM
AFAIK, zsh has (almost?) all the Ksh features. And its completion is very neat. Also the ** facility (so you almost never need the find command).

--
Basile Starynkevitch

#

Attack geeks on the prowl?

Posted by: Anonymous [ip: 122.167.9.254] on May 06, 2008 09:36 AM
Computers are for us to have fun, remember?

Millions of us use PCs with yesterday's RAM, whether 256MB, 128MB, or even (gasp) 64MB, and want programs to be reasonably efficient for what they do. Efficiency is always needed ... some of us with second machines with 2GB or 4GB find the experience unpleasant when inefficient programs chew up all available memory for no apparent reason than it is there, for example the popular internet browser (not naming any names, it has just been fixed) which works just fine on 128MB, but for some bizarre reason rolls all the way up to 3.6GB on a 4GB machine???

As for the 64MB systems and smaller, because of efficient software, we can do all kinds of nifty stuff on them, like run HAM stations, robotics, home automation and other experiments in annoying people and animal pets, telephone answering machines, and a thousand other things. A bit of efficiency always helps. 4MB versus 6MB is a big difference.

"... learning something like ruby, perl, or python that gives you much more power" ... is true and sometimes the best way, yet often they just pile on layers of complexity, memory usage, etc. Just for a few simple calculations, per example of original writer? Good for ksh to have been first (if memory serves) to make such calculations available in a shell with a measure of sophistication. And good for bash to have stepped up for some friendly competition. There is room for all.

I could go on, but you get the idea. I cheer the original writer who took the chance to bring up some good positive ideas even if the bash example was a bit dated. Why not reread his bit about compound functions, coprocesses -- just those two provide many ways to create useful new functionality in a short time for varied needs. And I cheer those who spoke up for reasonable efficiency, for the needs of embedded systems, and all the rest of us who try to squeeze more fun functionality into ever-tinier spaces.

#

well, another "lame!" comment

Posted by: Michael Shigorin on May 06, 2008 10:57 PM
I think too that author managed to miss the point almost completely. Yes, bash is pretty dumb (at least out of most boxes). Yes, ksh has better math (still there are way more appropriate tools, and current pdksh would fail e.g. pi example).

But.

For interactive usage, get yourself zsh and practice tabbing through e.g. ls options. I won't write an article on that, just try yourself.

For advanced usage, I'll second Ruby recommendation.

For embedded usage, there's busybox. No ksh at bay.

PS: just in case, I happen to co-maintain pdksh package in ALT Linux since 2002.

#

Korn -- an extended shell

Posted by: Anonymous [ip: 84.246.31.190] on May 07, 2008 01:16 AM
And i use the ksh so i can set the commandline editing to vi
with set -o vi
btw echo is buildin and an external command
if you wanne use the the external command you will need to give the full path to the command.
The external one has some nice options ...

/Arthur

#

Korn -- an extended shell

Posted by: Anonymous [ip: 122.167.39.224] on May 07, 2008 07:32 AM
How nice to hear from another maintainer. People just don't seem to understand us. Like you, I ask them not to use this program I maintain, because it has bugs, and other programs are better. They always look at me strangely and go away. Maybe you know why?

#

Korn -- an extended shell

Posted by: Anonymous [ip: 10.0.1.177] on May 08, 2008 05:19 PM
Thanks for sharing this information about korn shell. I never really asked anyone about it because almost everyone who has helped me learn Linux used bash. I might not be able to use the full capabilities of korn shell right now but it does sound like something I should try eventually. :) -Clair from newlinuxuser.com

#

This story has been archived. Comments can no longer be posted.



 
Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya