tcsh shell 变量

使用和操作 tcsh shell 变量

tcsh 是最流行的 UNIX® shell 之一。学习如何用 tcsh shell 变量简化自己的工作以及如何利用 tcsh 的高级安全特性。

Arpan Sen, 首席工程师, Systems Documentation, Inc. (SDI)

Arpan Sen 是致力于电子设计自动化行业的软件开发首席工程师。他使用各种 UNIX 版本(包括 Solaris、SunOS、HP-UX、IRIX,以及 Linux 和 Microsoft Windows)已经多年。他热衷于各种软件性能优化技术、图形理论和并行计算。Arpan 获得了软件系统硕士学位。



2008 年 11 月 03 日

tcsh 是原来的 Berkeley UNIX C shell 的改进版本,它是最流行的 UNIX shell 之一。本文讨论 tcsh 提供的一些功能:它提供的 shell 变量可以减少几个常规任务花费的时间,还提供了一些高级的安全特性,比如监视用户及其命令历史。本文描述的所有命令和脚本都用 tcsh 6.15 测试过(参见 参考资料)。

如何设置 shell 变量

tcsh 提供几个内置的 shell 变量。其中一部分(比如 rmstarnoclobber)是布尔值,所以建议用 set <variablename> 打开它们。对于 prompt 等其他内置变量,需要使用 set <variablename>=<value> 提供一个值。使用 unset <variablename> 取消变量。清单 1 给出一些基本示例。

清单 1. 如何设置/取消 shell 内置变量
tcsh# set prompt="arpan@tintin# "
arpan@tintin# set autologout=1
arpan@tintin# unset prompt
 echo $autologout
1
 <prompt has disappeared due to unset operation>

下面几节讨论 tcsh 通过 shell 内置变量提供的一些最有用的特性。

用 rmstar 预防灾难

在 UNIX 中,造成混乱的最常见原因可能是意外地执行了 rm *。大多数用户在使用 rm 命令时不使用 -i 选项,因此会立即删除文件。tcsh 定义了一个 shell 变量 rmstar;如果打开这个变量,在用户执行操作时会显示提示,要求用户确认操作。但是,如果用户在命令提示下运行 rm –f *,就不会出现确认提示。清单 2 演示 rmstar 的用法。

清单 2. 使用 rmstar shell 变量
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#

防止意外覆盖现有的文件

造成混乱的另一个典型场景是意外地覆盖现有的文件。为了防止发生这种情况,应该一直打开 shell 变量 noclobber。(这个变量在 csh shell 中也可用)。注意,这只能防止把输出重定向到现有文件;如果使用 cpmv 覆盖文件,这个变量没有任何帮助。见清单 3。

清单 3. 使用 noclobber 防止意外覆盖文件
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

还要注意,shell 操作符 >>>! 不考虑 noclobber 的设置。前一个操作符在现有文件中追加内容(所以仍然可以恢复数据),后者覆盖现有内容。

自动 Tab 补齐

当在 shell 提示上输入命令时,可以只输入命令字符串的一部分,然后按 Tab,shell 会自动补齐命令字符串或者给出可用的选择,这会显著加快输入速度。这个功能对于长文件名尤其有意义;可以只输入前几个字母并让 shell 补齐文件名。为了启用这个特性,需要设置 shell 变量 autolist。清单 4 给出一个示例。

清单 4. 使用 autolist 启用自动命令补齐
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

在这个示例中,[TAB] 表示按 Tab 键。在 shell 提示上输入 vi thi[TAB],shell 会把 thi[TAB] 扩展为 this_is_a_big_file

使用 addsuffix 在 Tab 补齐期间区分目录

如果同时设置 addsuffix shell 变量和自动 Tab 补齐,那么在找到匹配时 tcsh 会在文件夹后面加上一个 / 字符,这样就更容易区分出文件夹。它在一般文件后面加一个空格。在清单 5 所示的情况中,有一个名为 documents 的文件夹,这个文件夹中有一个名为 deliverables 的文件;用户输入 do[TAB],shell 就会显示 documents/。如果取消 addsuffix 变量,tcsh 就只显示 documents,这对于判断 documents 是一般文件还是文件夹很不方便。

清单 5. 在使用 autolist 的同时使用 addsuffix 区分文件夹
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

使用 fignore shell 变量避免意外删除

在某些情况下,限制自动 Tab 补齐特性是有意义的。例如,如果 vi 是一个会话中最常用的命令,那么把 Tab 补齐提供的命令字符串限制在文本文件范围内可以节省时间。同样,如果 .c 和 .cpp 文件还未备份,希望避免意外删除它们,那么在 Tab 补齐期间最好不要出现具有 .c/.cpp 扩展名的文件,这样在 rm 命令后面使用 Tab 补齐特性时就不会删除它们。为了避免在 Tab 补齐期间显示 C/C++ 文件,使用 set fignore=(.c .cpp .h)。见清单 6。

清单 6. 使用 fignore 避免在 Tab 补齐期间显示源代码文件
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

注意,如果在 rm 后面按 Tab 键(而不是在 m 后面按 Tab 键),那么所有 C/C++ 源代码文件都会出现。

在没有用户活动时自动注销

数据安全是所有组织都很关心的问题。如果意外地让一个 shell 终端一直打开着,就可能提供访问重要文件的机会,这种情况随时都会发生。可以用 tcsh autologout 变量解决这个问题。如果在指定的时间(以分钟为单位)内没有用户活动,用户就从系统中注销,返回到 tcsh(如果 tcsh 是登录 shell)。如果 tcsh 不是登录 shell,用户就退出到以前的 shell(这对安全帮助不大)。因此,在安全环境中选择 tcsh 作为登录 shell 是有意义的。清单 7 给出一个由于没有用户活动导致自动注销的示例。

清单 7. 由于没有用户活动导致自动注销
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

改进 tcsh 的安全性:监视正在使用系统的每个用户

必须一直监视用户对受保护系统的访问。tcsh 提供了内置 shell 变量 watch,可以通过它查看正在使用系统的用户。语法是 set watch=(username1 ttyname1 username2 ttyname2 …)。这会监视用户 username1 是否在终端 ttyname1 上登录了。可以用特殊语法 set watch=(any any) 监视所有系统终端上的所有用户。

在默认情况下,watch 每 10 分钟检查一次系统中的登录/注销活动。可以通过 watch 语法中的第一个参数指定活动检查之间的时间间隔,例如:set watch=(5 any any)。见清单 8。

清单 8. 使用 watch 检查登录/注销活动
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 还提供内置命令 log,这个命令列出受 watch 变量影响的终端以及正在使用它们的用户(见清单 9)。注意,如果在没有设置 watch 的情况下使用 log,就会导致一个错误。

清单 9. 使用 log 检查 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

使用 prompt 变量跟踪当前的工作目录

tcsh 定义了 prompt 内置 shell 变量,可以通过这个变量定制 shell 提示。最常见的 UNIX 任务之一是跟踪当前所在的文件夹和机器。不需要一直使用 pwdhostname,只需通过设置 prompt 变量让 shell 提示反映当前的工作目录和主机名,即可实现相同的效果。见清单 10。

清单 10. 通过修改 prompt 变量让 shell 提示反映当前的工作目录和主机
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]

但是,这种方式有一个问题:如果切换到另一个文件夹,提示并不会反映这一变化。为了随着切换文件夹连续改变提示,应该使用特殊别名 cmdcwd。如果已设置这个别名,那么在切换到新文件夹之后 tcsh 会执行 cmdcwd 映射到的命令。为了在提示中反映修改后的文件夹,cmdcwd 必须映射到 set prompt 命令(见清单 11)。

清单 11. 使用 cmdcwd 别名在提示中反映修改后的文件夹
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]

注意,这个方案不但能够反映 cd 命令所做的文件夹切换,对于 pushdpopd 命令也是有效的。如果使用 X-Windows,另一个跟踪当前文件夹的好方法是,在跨多个文件夹工作时,在 xterm 标题栏上显示文件夹名。

例如,可以使用 echo 命令在 xterm 标题栏上显示一些基本信息。在 shell 提示上输入 echo "[Ctrl-v][Esc]]2; Hello [Ctrl-v][Ctrl-g]"。注意,[Ctrl-v] 表示按组合键 Ctrl-V。输入这个命令序列,就会在 shell 提示上显示以下内容:echo "^[]2; Hello ^G"。执行这个命令之后,xterm 标题栏显示 Hello。清单 12 演示如何在 xterm 标题栏和提示中同时显示当前文件夹名。

清单 12. 使用 cmdcwd 修改提示并设置 xterm 标题栏
arpan@tintin[/home/arpan1/ibm1]# alias cwdcmd 'set prompt="$user@`hostname`[$cwd]# "; 
    echo "^[]2;$cwd^G" '

自动纠正无效的命令用法

tcsh 提供内置变量 correct,这有助于纠正无效的命令用法。例如,如果希望调用 perl,但是输入的是 prl,tcsh 会提示您纠正它。清单 13 给出一个示例。

清单 13. 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
..

定期执行特定的命令

系统管理员最常见的任务之一是监视磁盘使用量,并在磁盘使用量接近 100% 时采取措施。tcsh 的一个出色特性使我们能够轻松地定期执行特定的命令。把 periodic 映射到要定期执行的任务,并把 shell 内置变量 tperiod 设置为执行任务的时间间隔(以分钟为单位)。清单 14 演示如何使用 tperiodperiodic。注意,periodic 映射到脚本 checkdiskusage,这个脚本检查磁盘使用量,tcsh 每 10 分钟运行它一次。

清单 14. 使用 tcsh 内置变量定期执行命令
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

针对每个终端分别设置历史文件

同一位 UNIX 系统用户常常从多个终端登录。为了针对每个终端分别维护命令执行历史,可以使用 histfilesavehist 环境变量。histfile 变量用来指定存储命令执行历史的文件;默认设置是 $HOME/.history。savehist 变量让 tcsh 存储用户在 shell 提示上输入的最后 N 个命令。清单 15 中定义的 histfile 变量指定多个历史文件,这样就可以监视多个终端。

清单 15. 使用 histfile 和 savehist 变量存储用户的命令历史
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

监视运行一个命令花费的时间

为了监视执行一个 UNIX 进程花费的时间,可以设置 time 变量。输出显示用户时间、内核时间和实际流逝时间。清单 16 给出一个示例。

注意,可以用 tcsh 的内置命令 time 产生相同的输出,但是要对脚本做大量修改 —— 每个命令必须加上前缀 time(例如,time du –sm /opt)。如果使用 time 变量,那么只需在脚本的开头加上一行 set time,就可以显示各个命令的执行时间。

清单 16. 使用 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

调试 shell 脚本:在发生错误时自动输出退出值

shell 变量 printexitvalue 是一个很有用的 tcsh 特性,它对脚本调试非常有帮助。在通常情况下,shell 脚本和 UNIX 程序在成功完成时返回零。如果设置这个变量,那么当脚本或程序返回非零值时 tcsh 会显示退出状态,这会指出潜在的错误。见清单 17。

清单 17. 使用 printexitvalue 帮助调试
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

注意,在这个变量与一个 shell 脚本结合使用时,显示的是脚本的非零返回值,而不是脚本内部使用的命令或用户程序的返回值。

结束语

除了支持 csh 提供的 shell 变量之外,tcsh 还提供了大量 shell 变量和别名。本文主要介绍 tcsh 特有的变量。这里只讨论了一部分变量;更详细的信息参见 参考资料

参考资料

学习

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文
  • 获得最新的 tcsh 更新、下载和 FAQ
  • 访问 Tcsh 手册页
  • 阅读 brief introduction to many tcsh shell variables
  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • 技术书店 浏览关于这些主题和其他技术主题的图书。
  • Podcasts:收听 IBM 技术专家的访谈录。

获得产品和技术

  • IBM 试用软件:使用可从 developerWorks 直接下载的软件构建您的下一个开发项目。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX, Linux
ArticleID=349503
ArticleTitle=tcsh shell 变量
publish-date=11032008