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).
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.
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.
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.
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.
Learn
- Get the latest tcsh updates, downloads and FAQ.
- Visit the Tcsh man pages.
- Read a brief introduction to many tcsh shell variables .
- Browse the technology bookstore for books on these and other technical topics.
-
Podcasts: Tune in and
catch up with IBM technical experts.
Get products and technologies
-
IBM
trial software: Build your next development project with software for download
directly from developerWorks.
Discuss
-
Participate in the AIX and UNIX forums:
- AIX Forum
- AIX Forum for developers
- Cluster Systems Management
- IBM Support Assistant Forum
- Performance Tools Forum
- Virtualization Forum
- More AIX and UNIX Forums
Arpan Sen is a lead engineer working on the development of software in the electronic design automation industry. He has worked on several flavors of UNIX, including Solaris, SunOS, HP-UX, and IRIX as well as Linux and Microsoft Windows for several years. He takes a keen interest in software performance-optimization techniques, graph theory, and parallel computing. Arpan holds a post-graduate degree in software systems. You can reach him at arpansen@gmail.com.



