-
Which shell should I use under Unix?
First, this is a religious issue if there ever was one, for Unix users.
The most popular shells (in no particular order) are the Bourne shell
(sh), the Korn shell (ksh), the C shell
(csh), the T shell tcsh.
There are certainly are intelligent folks that use, and are proponents of,
each shell out there.
Personally, I use the Korn shell - ksh(1).
Here's my reasoning -
-
The Korn shell is available with nearly every Unix. It was written by
David Korn of AT&T Bell Labs and has been provided with all System V-derived
Unix systems since at least the late '80s. For Unix systems that
don't provide ksh(1) refer to the work-alike alternatives below.
-
The Korn shell was the basis for the POSIX shell standard, the only Unix
shell standard. (POSIX shells, only recently available, are often called
simply sh, replacing the traditional Bourne shell
sh(1). bash(1) is a freely available shell which
implements the POSIX shell standard.) This means that commercial Unix
must provide those features selected. Right now, POSIX shells are in
their infancy, so using a subset of Korn shell features is a good way to
assure that your commands and shell scripts will continue to work for
some time into the future.
-
The Korn shell does not share the problems of its popular alternative -
the C shell (and csh(1) derivatives such as tcsh(1)).
See Tom Christiansen's "csh Programming Considered Harmful" frequent net
news posting for details.
-
The Korn shell provides both emacs and vi
command-line editing. (set -o emacs and set -o vi,
respectively.) A POSIX shell need only provide vi-style
command-line editing.
This command-line editing makes it a good interactive shell (as opposed
to just a good choice for shell-script programming).
-
The Korn shell has been maintained and new features introduced. (Features
that used only to be available in alternative shells (such as elaborate
prompt formatting) are now available in ksh(1).) Common
Unix vendor-provided
implementations include ksh88 (1989) and ksh93 (1993).
(The version can be determined by typing CTRL-v while in
ksh's vi command mode.)
If ksh(1) is not available or you're still looking for
alternatives:
the POSIX shell sh(1), Public Domain ksh
(ksh(1)), and bash(1) (The Bourne Again Shell) are
good choices. The latter two, provide ksh(1)-like behavior
but are freely available. (The real Korn shell is a commercially
licensed product from AT&T.)
plonka, Dec 10 1997
-
In ksh, how can I map the cursor arrow keys to move about in the command history?
I have found that many people, especially in academic environments, choose
tcsh for no other reason
than that, by default, it allows one to use the cursor arrow
keys to move around in the shell's command history. If this feature is all
that you're looking for it can be done in ksh by adding these
commands to, for instance your shell rc file:
set -o emacs
alias __A=`echo "\020"` # up arrow = ^p = back a command
alias __B=`echo "\016"` # down arrow = ^n = down a command
alias __C=`echo "\006"` # right arrow = ^f = forward a character
alias __D=`echo "\002"` # left arrow = ^b = back a character
alias __H=`echo "\001"` # home = ^a = start of line
The ksh rc file is, usually ~/.kshrc, is specified in
~/.profile like this:
export ENV=~/.kshrc
plonka, Apr 2 1998
-
How do I print a file under Unix?
This is not a simple question to answer completely. It depends at least
upon the flavor of Unix in use, the type of file(s) to be printed,
and the user's personal preferences.
Also, many options exist because of the differences between AT&T
System V-derived Unixes and Berkeley-dervied ones. AT&T System V-derived
Unixes like Solaris (System V Release 4) have the lp(1) command to print, and
also the Korn shell (ksh), for instance. The name lp
is historical and derived from the phrase "line printer".
The guys around here
(and at many educational institutions) have an affinity for all things
Berkeley (mostly because 5-10 years ago that was the most progressive Unix).
Berkeley Unix added the lpr(1) command for printing, and the C
shell (csh). (As for Solaris machines, since Sun previously sold
a Berkeley-derived Unix (SunOS 4.x and earlier revision) they include the
Berkeley commands as well. So, both lp(1) and lpr(1)
exist there. (As well as both ksh(1) and csh(1).)
This is also true of IBM's AIX, since it is a hybrid of System V and
Berekeley Unixes.
Here we have seen lpr(1), print, and lp(1)
all being used. In this case print was a user-defined alias.
To further obfuscate things... ksh(1) does have a print built-in
that is similar to echo. So print may be a poor choice
as an user-defined alias or shell funciton name in ksh(1), but not
in csh(1).
Print filters exist to do special formatting of printed files - such as
enscript. (Note that this utility is sometimes called
nenscript - I don't know why it has two names but I think
that they're the same thing.) For example, this csh(1) alias:
alias print 'enscript -G -P hpb263 -T US \!* '
Here's some examples (assuming a preference for System V)...
You could print PostScript files like this:
$ lp file.ps
and plain text files either like this:
$ lp file.txt
or:
$ enscript -G -T US file.txt
if you like fancy PostScript 2-up formatting.
All of these commands respect the LPDEST environment variable,
which is used to specify the printer destination. For example:
ksh$ export LPDEST=hpb263
ksh$ lp file.txt # print to the HP printer for b263
Alternatively, lp(1)'s -d option or lpr(1)'s
and enscript(1)'s -P option can be used to specify
the print destination. If no destination is specified using any of these
methods, the system default printer will be used. The system default printer
can be determined on many systems by issuing this command:
$ lpstat -t
plonka, Dec 10 1997
-
How do we install freely-available packages under Unix?
- For Source Distributions
Currently, packages that are distributed as source distributions are kept in
/opt/packages, eg. as a
package.tar.Z or package.tar.gz.
For the most part, we expect to keep only package versions that are currently
installed and in use in that directory.
These are then extracted in /opt/local/source.
Most distributions will create a package-version sub-dir
when extracted, which is convenient so that multiple version can co-exist.
You may wish to create a symbolic link to indicate which version is currently
installed and in use. eg.
# cd /opt/local/source
# ln -s package_version package
We will leave the extracted distribution there as long as disk-space allows.
- Making Modifications
When you find that you have to either modify the package or perform an
unusual build and/or install procedure please document it. If you modify
a file, please save the original. eg.
# cd /opt/local/source/package_version
# cp -p Makefile.in Makefile.in_orig
# vi Makefile.in # edit Makefile for site-specific changes
If your changes are extensive, it may be preferable to use RCS:
# cd /opt/local/source/package_version
# ci -l file.c
# vi file.c # edit source for bug-fixes, enhancements, etc.
# ...
# make install
# ci -u file.c # check-in and explain your installed changes
This will be especially helpful to produce patch(1)es using
rcsdiff(1).
If /opt/local/Makefile exits, update it to include a rule to
build the package. This will give you an opportunity to show which commands
you used to build the package and should make it much easier for the package
to be rebuilt in the future. For example, many configure-able
packages could be built and installed like this:
package: $(srcdir)/$@
@banner "$@"
cd $(srcdir)/$@ && \
rm -f config.cache && \
CC="$(CC) $(CPPFLAGS)" ./configure --prefix=$(prefix) && \
make install realclean
Lastly, If the build and/or install procedure is not particular clear, please
explain it in a /opt/local/source/README.package
file. eg.
# cd /opt/local/source/package_version
# ...
# make install
# vi /opt/local/source/README.package
...
README for package
------------------
package was configured using with:
# ./configure --sbin=/opt/local/bin --with-some-other-option
Dave Plonka <plonka AT dot DOT wisc DOT edu>
Wed Jan 7 11:31:41 CST 1998
...
#
- For Binary Distributions
Packages that are not distributed as source distributions are kept in
/opt/packages, eg. as a
package.Z or package.gz.
This is appropriate for binary distributions of gcc, for instance,
and some commercial distributions. Packages that using a vendor-suppled
mechanism (eg. Solaris' pkgadd) will usually install into
/opt/PACKAGE.
plonka, Jan 6 1998
-
How do we administer root access under Unix?
The use of individual root accounts (eg. rootjs for John Smith's
root account), rather than the anonymous real root, is
preferable because:
-
each person can have their own personal root environment
-
it makes it more convenient to determine who did what
-
each account can have a seperate root shell history (if you use
su - rootyou to become root)
-
-
it will enable us to keep track of who did what edits as root
with RCS. (Even though you are really be root (uid=0) when you
log in, RCS will use your login name to track changes.)
-
it is more secure than sharing the real root password
-
Adding root accounts
Using vipw, if available, edit the passwd file(s)
to add an entry something like this:
root:x:0:1:Super-User:/:/bin/sh
rootjs:x:0:1:Root - John Smith:/:/bin/ksh
If your system provides a utility such as Solaris' pwck(1M)
you can use it to check the passwd file integrity before logging
out of your root shell.
When adding multiple "uid=0" accounts, make sure to
always add the additional root accounts after the "normal" one, so that
files owned by uid=0 will show root as the owner. (Still,
some systems, such a Digital Unix, create a hashed database of
passwd file entries to efficiently perform
getpwuid(3), so ls(1) might show a user name
other than simply root. This is only a small annoyance though
as long as you put the word root in the names of all
"uid=0" accounts.)
Also, it's safer to leave the real
root as the first line in case the passwd file is somehow left
corrupted while editing.
Make sure that the GECOS field has a
unique "real" name (ie. more specific than "Super-User" or some such thing)
so that if ever anyone sends e-mail using the name from the GECOS
field it will go to the right place. (Many sendmails will
allow you to send to the user name by the name in this field with
underscores in place of spaces - eg. John_Smith. You would
want this e-mail to go to John Smith's normal account... However if you
had accidentally put John Smith in the GECOS field as
rootjs' "real" name, e-mail to John_Smith would be
relivered to rootjs instead because that entry
would be encountered earlier in the passwd file.)
-
becoming root using su(1)
The - argument to su(1) causes it to invoke a login
shell. This is important so that the shell startup (eg.
/etc/profile, .profile) and rc
(eg. /.kshrc) files will be sourced - enabling you to
customize your root shell environment:
$ su - rootyou
Password:
#
-
Changing a root account password
When chaning a root account password, it's *important* that you use your
own root account name as the argument to passwd(1) here otherwise you'll
end up changing the real "root" passwd and confusion will ensue:
# passwd rootyou
New password:
Re-enter new password:
#
-
Maintaining shell startup files
Common shell startup files, such as /etc/profile and
root's .profile should be compatible with
Bourne shell syntax, so that it will be compatible with all commonly
used shells. (A similar rule would hold true for csh-
derived shells and their respective startup and files.)
Here's an example fragment for root's .profile:
case "$LOGNAME" in
rootdp) # rootdp uses ksh
export HISTFILE=/.sh_history_${LOGNAME?}
export FCEDIT=vi EDITOR=vi VISUAL=vi
export PATH=/usr/local/bin:/usr/xpg4/bin:/usr/bin:/usr/ccs/bin:/etc:/usr/sbin:/usr/ucb
export MANPATH=/usr/local/man:/usr/man
;;
*) # generic root, keep syntax Bourne shell compatible
HISTFILE="/.sh_history_$LOGNAME"
export HISTFILE
FCEDIT=vi
EDITOR=vi
VISUAL=vi
export FCEDIT EDITOR VISUAL
PATH=/usr/local/bin:/usr/xpg4/bin:/usr/bin:/usr/ccs/bin:/etc:/usr/sbin:/usr/ucb
export PATH
MANPATH=/usr/local/man:/usr/man
export MANPATH
;;
esac
If multiple system administrators might maintain these files, it would
be a good idea to maintain such files using RCS.
plonka, Jan 14 1998
-
What's the deal with the system log under Ultrix?
After re-learning how to view and manipulate the Ultrix system logs
multiple times, I thought it was worth an explanation, if only to save
myself time. Here's the deal:
Under Ultrix syslog-type messages which are handled by the
error logging daemon - elcsd appear, usually, to go to a binary
file called /usr/adm/syserr/syserr.hostname.
(Check /etc/elcsd.conf to be sure.)
The records in this file can be viewed using the uerf command -
the so-called "Ultrix Error Report Formatter", of course ;^P.
A typical invocation might look like this:
# uerf -t s:23-apr-1998 |more
I've found this to be an incredibly slow and tedious process... you
often have to guess what ranges of time during which interesting
messages may have occurred otherwise it takes the utility forever
to show the records. (Forget trying to tail the uerf
output if the file is sizable.)
Apparently this binary file grows without bound. Things like a file
system being full for a while causes it to become quite large, so
when you want to trim down the log, you can do this:
# cd /usr/adm/syserr
# mv syserr.hostname syserr.hostname.old
# eli -r
That last command, causes elcsd to reconfigure, re-opening it's
log file(s).
plonka, Apr 23 1998
-
How do we use RCS?
RCS, the Revision Control System, manages file revisions. In our group,
we use it to help maintain all plain text files on Unix-based projects. These
files include C language source files, shell scripts, configuration files, etc.
The RCS commands should be
in /opt/local/bin, which should be specified accordingly in your
PATH environment variable.
A typical session to edit an RCS-maintained file might look like this:
$ co -l file # check-out the file with a lock
...
$ vi file # perform an edit
...
$ rcsdiff file # diff(1) the file to examine the change
...
$ ci -u file # check-out the file with a lock
...
explain the reason for the change here...
^D
Here's some useful RCS commands:
- co -M file
- Check out file for reading. The -M specifies
that the file should be retrieved with the original modification time,
rather than the current time. This is useful so that checked-out
files do not appear to be newer than the last time they were edited.
(This is also nice when using
make(1) because the file won't look as if it's been
touched unless a real change has been made.)
- co -l file
- Check out file locked, for writing.
- rcsdiff file
- Show the differences for file between the revision
currently locked and the previously checked-in revision.
- ci -u file
- Check in file, to deposit changes made in the
RCS/file,v. Before checking in a file, you
should create an RCS directory, which will contain the revision
(,v) files: mkdir RCS.
- rcs -u file && rm file && co -M file
- Break a lock for file, remove the file with the edits
to be thrown away, and check out the latest revision for reading.
This procedure would be used to "back-out" of a change you were
working on, but decided not to check it in.
- ident executable
- Generate a list of the RCS $Id$ strings from
executable. These indicate the revisions of the
RCS-maintained source files that were used to produce
executable.
Please see the rcsintro man page for more information.
plonka, May 22 1998
-
How source I search the revisions of an RCS file?
Similarly to using grep(1), you can use the freely-available
rcsgrep utility available in the O'Reilly "Unix Power Tools"
archive. (See this for where it can
be found.)
For example:
$ rcsgrep -a pattern file(s)
Since some of the output goes to standard output and some to standard
error, it may be necessary to pipe the combined outputs into a pager,
as in:
$ rcsgrep -a pattern file(s) 2>&1 |less
The -a option specifies to search in all revisions.
plonka, Feb 22 1999
-
How do we restore files using ADSM?
There are two ways to administer ADSM, with a GUI (X) client or from
the command line. The GUI can be launched, as root like this:
# export DISPLAY=whatever:0
# dsm
Alternatively, there is a command-line interface. From my cursory look at
the dsmc command, you can do this (as root):
# dsmc restore -latest /path/to/file/to/be/restored/filename /tmp/filename
If you're restoring a directory rather than a file and you want the content of
the subdirectories too, add the -subdir=yes option, as in:
# dsmc restore -latest -subdir=yes /path/to/dir/to/be/restored/dirname/ /tmp/dirname/
To explore all the subtleties and features try:
# dsmc help
plonka, Aug 17 1998
-
How can I create a gzip(1)ped tar(1) archive "on the fly"?
You can have essentially the same effect as the "compress-on-the-fly"
-z option that gnu tar(1) has, like this:
$ tar cf - dir_or_file [...] |gzip -c > archive.tar.gz
^ ^^^^^^^^
Specifying "-" as the file name following tar(1)'s "-f" option
causes tar(1) to write to standard output which, here, will go
into the pipe to "gzip -c". gzip(1), in turn, will compress
its input and again send it to standard output which we then
redirected to a ".tar.gz" or ".tgz" file.
That should work with tar and gzip on any Unix, not
just ones which have GNU tar.
plonka, Nov 25 1998
-
How can I determine what process is using a give TCP or UDP port?
Initially, netstat may be useful to determine which ports are in use:
$ netstat -a |grep .service|port
Then, you can use the freely available utility lsof to determine
which process is using a give port, for instance when you get the error
Address already in use.
$ lsof -i protocol:service|port
E.g.:
$ lsof -i UDP:1812
See the lsof man page for full details.
plonka, Jan 5 1999