Tcsh is one of the most popular UNIX® shells. Learn how
you can use tcsh shell variables to make your work
easier and how to take advantage of tcsh's advanced
security features.
Tcsh, an enhancement of the original Berkeley UNIX C
shell, is one of the most popular UNIX shells. This article
looks at some of the power that tcsh brings to the table: it
provides shell variables that make several regular tasks
less time consuming, and it also brings in advanced security
features like monitoring of users and their command
histories. All commands and scripts described in this
article have been tested with tcsh 6.15 (see the
Resources
section).
How to set shell
variables
Tcsh comes with several built-in shell variables. Some of
these, like rmstar and noclobber ,
are boolean in nature, so I recommend that you use set
<variablename> to turn them on. For other built-ins
like prompt, you need to provide a value using
set <variablename>=<value> . To unset a variable, use
unset <variablename> . Listing 1 shows some
basic examples.
Listing 1. How to set/unset shell
built-in variables
tcsh# set prompt="arpan@tintin# "
arpan@tintin# set autologout=1
arpan@tintin# unset prompt
echo $autologout
1
<prompt has disappeared due to unset operation>
|
The next few sections describe some of the most useful features tcsh
provides through shell built-ins.
Prevent disaster
with rm
Perhaps the most common way of messing things up in UNIX
is to inadvertently issue rm * . Most users
don't use the -i option with rm ,
thereby deleting the files instantly. Tcsh defines a shell
variable rmstar ; when turned on, it provides
the user with a prompt that requests confirmation of the
user's action. However, it doesn't work if the user runs
rm –f * at the command prompt. Listing 2 shows
the use of rmstar .
Listing 2. Using the rmstar shell
variable
arpan@tintin# pwd
/home/arpan/scratchpad
arpan@tintin# ls
file1 file2
arpan@tintin# set rmstar
arpan@tintin# rm *
Do you really want to delete all files? [n/y] n
arpan@tintin# ls
file1 file2
arpan@tintin# unset rmstar
arpan@tintin# rm *
arpan@tintin# ls
arpan@tintin#
|
Prevent accidental overwriting of
existing files
Another typical doomsday scenario is the accidental
overwriting of an existing file. To prevent this from
happening, always keep the noclobber shell
variable turned on. (This variable is also available in the
csh shell.) Note that this can only save you while you're
trying to redirect output to an existing file -- it isn't
any help if you're using cp or mv
to overwrite the file. See Listing 3.
Listing 3. Using noclobber to prevent
accidental file overwrite
arpan@tintin# ls
file1 file2
arpan@tintin# set noclobber
arpan@tintin# echo testing > file1
file1: File exists.
arpan@tintin# unset noclobber
arpan@tintin# echo testing > file1
arpan@tintin# cat file1
testing
|
Also note that the shell operators >> and >!
override noclobber . The former operator appends
to the existing file (so data may still be recovered), and
the latter overwrites existing content.
Automatic Tab
completion
When you're typing commands at the shell prompt, it
speeds things up considerably if you can type in part of the
command string, click Tab, and have the shell either
complete the command string or provide options for
completion. This functionality is particularly useful with
long filenames -- you can key in the first few letters and
let the shell complete the filename. To enable this feature,
you need to set the autolist shell variable.
Listing 4 gives an example.
Listing 4. Using autolist for
automatic command completion
arpan@tintin# ls
this_is_a_big_file test.c threads.h
arpan@tintin# set autolist
arpan@tintin# vi t[TAB]
this_is_a_big_file test.c term.h
arpan@tintin# vi th[TAB]
this_is_a_big_file threads.h
|
In this example, [TAB] indicates clicking the Tab key.
Type in vi thi[TAB]
at the shell prompt, and the shell expands thi[TAB]
to this_is_a_big_file .
Use addsuffix to
distinguish directories during Tab completion
If the addsuffix shell variable is set along
with automatic Tab completion, it's easier to distinguish
folders because tcsh suffixes them with a / character when a
match is found. It suffixes normal files with a space.
Listing 5 shows a situation with a folder named documents
and a file named deliverables in the same folder; the
user types in do[TAB] ,
and in response the shell displays documents/ .
If the addsuffix variable is unset, then tcsh displays only
documents , which is inconvenient because you
need to determine whether documents is a normal file
or a folder.
Listing 5. Using addsuffix for
additional clarity while using autolist
arpan@tintin# ls
documents deliverables
arpan@tintin# set autolist
arpan@tintin# ls do[TAB]
arpan@tintin# ls documents
arpan@tintin# set addsuffix
arpan@tintin# ls do[TAB]
arpan@tintin# ls documents/
arpan@tintin# unset autosuffix
arpan@tintin# ls do[TAB]
arpan@tintin# ls documents
|
Use the fignore shell variable to
avoid accidental deletion
It makes sense to restrict the automatic Tab-completion
feature under certain circumstances. For example, if vi is
the most-used command in a session, then you can save time
if only text files come up during Tab completion. Likewise,
if .c and .cpp files aren't yet backed up and you want to
avoid accidental deletion at all cost, then it's best to
avoid files with .c/.cpp extensions during Tab completion so
they aren't deleted when you use rm followed by
Tab completion. To prevent C/C++ file types from showing up
during Tab completion, use set fignore=(.c .cpp .h) .
See Listing 6.
Listing 6. Using fignore to prevent
source files from showing up during Tab completion
arpan@tintin# set autolist
arpan@tintin# ls
memory.h memory.cpp kernel.c memory.o kernel.o
arpan@tintin# rm m[TAB]
memory.h memory.cpp memory.o
arpan@tintin# set fignore=(.c .cpp .h)
arpan@tintin# rm m[TAB]
memory.o
|
Note that if you use rm followed by Tab, as opposed to
m followed by Tab, then all C/C++ source files
appear.
Automatically log
out in case of no user activity
Data security is a prime concern in all organizations.
Leaving a shell terminal open inadvertently can potentially
provide access to secure files, but this happens all the
time. You can solve this problem using the tcsh
autologout variable. When there is no user activity
for a specific time (measured in minutes), the user is
logged off the system to tcsh (if it's the login shell). If
tcsh isn't the login shell, the user exits to the previous
shell, which isn't much help. Thus, it makes sense to have
tcsh as the login shell of choice in a secure environment.
Listing 7 shows a case of automatic logout due to
inactivity.
Listing 7. Automatic logout in case of
inactivity
arpan@tintin# rsh herge
arpan@herge# set autologout=1
arpan@herge# date
Sat Jun 28 18:13:07 IST 2008
<After 1 min of inactivity>
arpan@herge# auto-logout
Connection to herge closed.
arpan@tintin# date
Sat Jun 28 18:14:10 IST 2008
|
Enhanced security in tcsh:
Monitor everyone who's using the system
Access to a restricted system must be continuously
monitored. Tcsh provides the built-in shell variable
watch , which makes it easy to view who is logging in
and out of the system. The syntax is set
watch=(username1 ttyname1 username2 ttyname2 …) . This
monitors whether the user with username1 is logged on to
terminal ttyname1. The special syntax set watch=(any
any) lets you monitor all users across all system
terminals.
By default, watch checks the system for login/logout
activity every 10 minutes. You can override this behavior by
specifying the time between activity checks as the first
variable of the watch syntax: for example, set
watch=(5 any any) . See Listing 8.
Listing 8. Using watch to check for
login/logout activity
arpan@tintin# set watch=(5 any any)
<checks for login/logout activity across system every 5 minutes)
arpan@tintin# set watch=(b* any)
<check the login/logout activities of all users whose name starts with b across
any terminal in the network>
|
Tcsh provides the built-in command log , which lists the
terminals affected by watch variables and who's using them
(see Listing 9). Note that using log without
watch being set causes an error.
Listing 9. Using log to check for
terminal usage under watch
arpan@tintin# log
arpan has logged on pts/0 from 132.132.6.73
root has logged on console
zanies has logged pts/5 from 132.132.2.1
|
Use the prompt variable to keep
track of the current working directory
Tcsh defines the prompt built-in shell
variable, which you can use to customize shell prompts. One
of the most common UNIX tasks is keeping track of which
folder and machine you're currently in. Instead of
continuously using pwd and hostname ,
you can achieve the same effect by manipulating the
prompt variable to reflect the current working
directory and hostname. See Listing 10.
Listing 10. Change the prompt
variable to reflect the current working directory and host
tcsh-6.15$ pwd
/home/arpan/ibm1
tcsh-6.15$ hostname
tintin
tcsh-6.15$ echo $user
arpan
tcsh-6.15$ set prompt="$user@`hostname`[$cwd] "
arpan@tintin[/home/arpan/ibm1]
|
But an issue remains with this approach: if you change to a different
folder, the prompt doesn't reflect the change. To make this
change continual as you switch folders, you use the special
alias cmdcwd . If this alias is set, then tcsh
executes the command that cmdcwd was aliased to
after switching to a new folder. To reflect the changed
folder in the prompt, cmdcwd must be aliased to
the set prompt command (see Listing 11).
Listing 11. Use the cmdcwd alias to
reflect changed folders in the prompt
tcsh-6.15$ alias cmdcwd 'set prompt="$user@`hostname`[$cwd] " '
tcsh-6.15$ cd
arpan@tintin[/home/arpan/ibm1] cd net
arpan@tintin[/home/arpan/ibm1/net]
|
Note that this scheme works seamlessly with the pushd and
popd commands as well, not just with cd
while changing folders. If you're using X-Windows, yet
another smart way to keep track of the current folder is to
display the folder name on the title bar of the xterm as you
work your way across multiple folders.
For example, you can print some basic information on the
xterm title bar using the echo command. Type
echo "[Ctrl-v][Esc]]2; Hello
[Ctrl-v][Ctrl-g]" at the shell prompt. Note
that [Ctrl-v] means to click the key
combination Ctrl-V. Keying in this sequence displays
the following at the shell prompt: echo "^[]2; Hello
^G" . On execution of this command, the xterm title
bar displays Hello . Listing 12 shows how to
display the current folder name in the xterm title bar along
with the prompt.
Listing 12. Use cmdcwd to change the
prompt and set xterm title bar
arpan@tintin[/home/arpan1/ibm1]# alias cwdcmd 'set prompt="$user@`hostname`[$cwd]# ";
echo "^[]2;$cwd^G" '
|
Automatically correct invalid
command usage
Tcsh provides the built-in variable correct ,
which helps you correct invalid command usage. For example,
if you want to invoke perl and have typed in
prl , tcsh lets you correct it. Listing 13 gives
an example.
Listing 13. Automatically correct
typos with tcsh
arpan@tintin# set correct=cmd
arpan@tintin# prl
CORRECT>perl (y|n|e|a)? y
..
arpan@tintin# figner
CORRECT>finger (y|n|e|a)? y
..
|
Periodic execution of specific
commands
One of the most common tasks system administrators need
to do is monitor disk usage and take action if it nears
100%. Tcsh has a great feature that lets you perform such
periodic execution of events with ease. Alias periodic
to the task you want to be executed on a periodic basis, and
set the shell built-in tperiod equal to the
number of minutes between executions of the task. Listing 14
shows how to use tperiod and periodic .
Note that periodic is aliased to the script
checkdiskusage , which checks for disk usage and
is run by tcsh every 10 minutes.
Listing 14. Use tcsh built-ins for
periodic execution of commands
arpan@tintin# set tperiod=10
arpan@tintin# alias periodic checkdiskusage
arpan@tintin# cat checkdiskusage
df -k | awk -F" " '{print $5}' | grep "9[0-9]*"
if ($status <> 0) then
mail –s "disk quota exceeded 90%" root@officemail.com
endif
exit $status
|
Set a history file on a
per-terminal basis
It's fairly common to have the same user of a UNIX system
logged on from multiple terminals. To maintain the command
execution history on a per-terminal basis, you can use the
histfile and savehist environment
variables. The histfile variable lets the user
specify the name of the file where the command execution
history should be stored; the default is $HOME/.history. The
savehist variable asks tcsh to store the user's
last N commands on the shell prompt. The
histfile variable definition in Listing 15 allows for
multiple history files so you can monitor multiple
terminals.
Listing 15. Use the histfile and
savehist variables to store the user's command history
arpan@tintin# tty
/dev/pts/0
arpan@tintin# set savehist=25
arpan@tintin# set histfile=~/.history_`tty | sed –e 's/\//_/g' `
arpan@tintin# echo $histfile
~/.history_dev_pts_0
|
Monitor the time it takes to run
a command
To monitor the time it takes for a UNIX process to
execute, you can set the time variable. The
output displays the user time, kernel time, and real elapsed
time. Listing 16
shows an example.
Note that you can achieve the same output using tcsh's
built-in time command, but the script change
isn't minor -- every command must be prefixed with
time (for example, time du –sm /opt ). If
you use the time variable, the single line set
time at the start of the script is good enough to display
the time it takes to run individual commands.
Listing 16. Use time to display
individual commands' execution time
arpan@tintin# cat script
set time
du –sm /opt
df –k /lib
arpan@tintin# tcsh –f ./script
198 /opt
0.628u 0.008s 0:02.00 0.0% 0+0k 0+0io 0pf+0w
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 15773312 1125772 13846300 8% /
0.000u 0.004s 0:00.02 0.0% 0+0k 0+0io 0pf+0w
|
Debug shell scripts:
Automatically print the exit value on error
The shell variable printexitvalue is a
useful feature of tcsh that immensely aids script debugging.
Typically, shell scripts and UNIX programs return 0 on
successful completion. If you set this variable, tcsh
displays the exit status whenever a script or program
returns a non-zero value, thereby indicating a potential
error. See Listing 17.
Listing 17. Use printexitvalue for
debugging
arpan@tintin# set printexitvalue
arpan@tintin# ls /tmp/opt
ls: /tmp/opt: No such file or directory
Exit 2
arpan@tintin# cat error_script
ls –l; return 2
arpan@tintin# ./error_script
./error_script: line 1: return: can only `return' from a function or sourced script
Exit 1
arpan@tintin# unset printexitvalue; ls /tmp/opt
ls: /tmp/opt: No such file or directory
|
Note that when you use this variable in conjunction with a shell
script, the non-zero return value of the script is
displayed, not the individual return values of commands or
user programs that the script may use internally.
Conclusion
Tcsh provides a gamut of shell variables and aliases, in
addition to supporting those that csh supplies. This article
has focused mainly on the variables that are unique to tcsh.
The discussion covers only a cross section of the variables;
for a detailed discussion, see the
Resources
section. |
No comments:
Post a Comment