中国青基会

查看完整版本: tcsh shell 变量

lili 2008-11-11 03:15

tcsh shell 变量

[url=http://www.ibm.com/developerworks/cn/aix/library/au-tcsh/index.html#author][color=#996699]Arpan Sen[/color][/url], 首席工程师, Systems Documentation, Inc. (SDI)

[indent]tcsh 是最流行的 UNIX® shell 之一。学习如何用 tcsh shell 变量简化自己的工作以及如何利用 tcsh 的高级安全特性。[/indent]tcsh 是原来的 Berkeley UNIX C shell 的改进版本,它是最流行的 UNIX shell 之一。本文讨论 tcsh 提供的一些功能:它提供的 shell 变量可以减少几个常规任务花费的时间,还提供了一些高级的安全特性,比如监视用户及其命令历史。本文描述的所有命令和脚本都用 tcsh 6.15 测试过(参见 [url=http://www.ibm.com/developerworks/cn/aix/library/au-tcsh/index.html#resources][color=#996699]参考资料[/color][/url])。
[color=#000000]如何设置 shell 变量[/color]
tcsh 提供几个内置的 shell 变量。其中一部分(比如 [font=新宋体]rmstar[/font] 和 [font=新宋体]noclobber[/font])是布尔值,所以建议用 [font=新宋体]set <variablename> [/font]打开它们。对于 [i]prompt[/i] 等其他内置变量,需要使用 [font=新宋体]set <variablename>=<value>[/font] 提供一个值。使用 [font=新宋体]unset <variablename>[/font] 取消变量。清单 1 给出一些基本示例。

[b][color=#000000]清单 1. 如何设置/取消 shell 内置变量[/color][/b]
[table=70%][tr][td]tcsh# set prompt="arpan@tintin# "arpan@tintin# set autologout=1arpan@tintin# unset prompt echo $autologout1 <prompt has disappeared due to unset operation>[/td][/tr][/table]
下面几节讨论 tcsh 通过 shell 内置变量提供的一些最有用的特性。
[color=#000000]用 rmstar 预防灾难[/color]
在 UNIX 中,造成混乱的最常见原因可能是意外地执行了 [font=新宋体]rm *[/font]。大多数用户在使用 [font=新宋体]rm[/font] 命令时不使用 [font=新宋体]-i[/font] 选项,因此会立即删除文件。tcsh 定义了一个 shell 变量 [font=新宋体]rmstar[/font];如果打开这个变量,在用户执行操作时会显示提示,要求用户确认操作。但是,如果用户在命令提示下运行 [font=新宋体]rm –f *[/font],就不会出现确认提示。清单 2 演示 [font=新宋体]rmstar[/font] 的用法。

[b][color=#000000]清单 2. 使用 rmstar shell 变量[/color][/b]
[table=98%][tr][td]arpan@tintin# pwd/home/arpan/scratchpadarpan@tintin# lsfile1 file2arpan@tintin# set rmstararpan@tintin# rm *Do you really want to delete all files? [n/y] narpan@tintin# lsfile1 file2arpan@tintin# unset rmstararpan@tintin# rm * arpan@tintin# lsarpan@tintin# [/td][/tr][/table]
[color=#000000]防止意外覆盖现有的文件[/color]
造成混乱的另一个典型场景是意外地覆盖现有的文件。为了防止发生这种情况,应该一直打开 shell 变量 [font=新宋体]noclobber[/font]。(这个变量在 csh shell 中也可用)。注意,这只能防止把输出重定向到现有文件;如果使用 [font=新宋体]cp[/font] 或 [font=新宋体]mv[/font] 覆盖文件,这个变量没有任何帮助。见清单 3。

[b][color=#000000]清单 3. 使用 noclobber 防止意外覆盖文件[/color][/b]
[table=98%][tr][td]arpan@tintin# ls file1 file2arpan@tintin# set noclobberarpan@tintin# echo testing > file1file1: File exists.arpan@tintin# unset noclobberarpan@tintin# echo testing > file1arpan@tintin# cat file1testing[/td][/tr][/table]
还要注意,shell 操作符 [font=新宋体]>>[/font] 和 [font=新宋体]>![/font] 不考虑 [font=新宋体]noclobber[/font] 的设置。前一个操作符在现有文件中追加内容(所以仍然可以恢复数据),后者覆盖现有内容。
[color=#000000]自动 Tab 补齐[/color]
当在 shell 提示上输入命令时,可以只输入命令字符串的一部分,然后按 [b]Tab[/b],shell 会自动补齐命令字符串或者给出可用的选择,这会显著加快输入速度。这个功能对于长文件名尤其有意义;可以只输入前几个字母并让 shell 补齐文件名。为了启用这个特性,需要设置 shell 变量 [font=新宋体]autolist[/font]。清单 4 给出一个示例。

[b][color=#000000]清单 4. 使用 autolist 启用自动命令补齐[/color][/b]
[table=98%][tr][td]arpan@tintin# lsthis_is_a_big_file test.c threads.harpan@tintin# set autolistarpan@tintin# vi t[TAB]this_is_a_big_file test.c term.harpan@tintin# vi th[TAB]this_is_a_big_file threads.h[/td][/tr][/table]
在这个示例中,[font=新宋体][TAB][/font] 表示按 Tab 键。在 shell 提示上输入 [b][font=Lucida Console][size=2]vi thi[TAB][/size][/font][/b],shell 会把 [font=新宋体]thi[TAB][/font] 扩展为 [font=新宋体]this_is_a_big_file[/font]。
[color=#000000]使用 addsuffix 在 Tab 补齐期间区分目录[/color]
如果同时设置 [font=新宋体]addsuffix[/font] shell 变量和自动 Tab 补齐,那么在找到匹配时 tcsh 会在文件夹后面加上一个 / 字符,这样就更容易区分出文件夹。它在一般文件后面加一个空格。在清单 5 所示的情况中,有一个名为 [i]documents[/i] 的文件夹,这个文件夹中有一个名为 [i]deliverables[/i] 的文件;用户输入 [b][font=Lucida Console][size=2]do[TAB][/size][/font][/b],shell 就会显示 [font=新宋体]documents/[/font]。如果取消 addsuffix 变量,tcsh 就只显示 [font=新宋体]documents[/font],这对于判断 [i]documents[/i] 是一般文件还是文件夹很不方便。

[b][color=#000000]清单 5. 在使用 autolist 的同时使用 addsuffix 区分文件夹[/color][/b]
[table=98%][tr][td]arpan@tintin# lsdocuments deliverablesarpan@tintin# set autolistarpan@tintin# ls do[TAB]arpan@tintin# ls documentsarpan@tintin# set addsuffixarpan@tintin# ls do[TAB]arpan@tintin# ls documents/arpan@tintin# unset autosuffixarpan@tintin# ls do[TAB]arpan@tintin# ls documents[/td][/tr][/table]
[color=#000000]使用 fignore shell 变量避免意外删除[/color]
在某些情况下,限制自动 Tab 补齐特性是有意义的。例如,如果 vi 是一个会话中最常用的命令,那么把 Tab 补齐提供的命令字符串限制在文本文件范围内可以节省时间。同样,如果 .c 和 .cpp 文件还未备份,希望避免意外删除它们,那么在 Tab 补齐期间最好不要出现具有 .c/.cpp 扩展名的文件,这样在 [font=新宋体]rm[/font] 命令后面使用 Tab 补齐特性时就不会删除它们。为了避免在 Tab 补齐期间显示 C/C++ 文件,使用 [font=新宋体]set fignore=(.c .cpp .h)[/font]。见清单 6。

[b][color=#000000]清单 6. 使用 fignore 避免在 Tab 补齐期间显示源代码文件[/color][/b]
[table=98%][tr][td]arpan@tintin# set autolistarpan@tintin# lsmemory.h memory.cpp kernel.c memory.o kernel.oarpan@tintin# rm m[TAB]memory.h memory.cpp memory.oarpan@tintin# set fignore=(.c .cpp .h)arpan@tintin# rm m[TAB]memory.o[/td][/tr][/table]
注意,如果在 [font=新宋体]rm[/font] 后面按 Tab 键(而不是在 [font=新宋体]m[/font] 后面按 Tab 键),那么所有 C/C++ 源代码文件都会出现。
[color=#000000]在没有用户活动时自动注销[/color]
数据安全是所有组织都很关心的问题。如果意外地让一个 shell 终端一直打开着,就可能提供访问重要文件的机会,这种情况随时都会发生。可以用 tcsh [font=新宋体]autologout[/font] 变量解决这个问题。如果在指定的时间(以分钟为单位)内没有用户活动,用户就从系统中注销,返回到 tcsh(如果 tcsh 是登录 shell)。如果 tcsh 不是登录 shell,用户就退出到以前的 shell(这对安全帮助不大)。因此,在安全环境中选择 tcsh 作为登录 shell 是有意义的。清单 7 给出一个由于没有用户活动导致自动注销的示例。

[b][color=#000000]清单 7. 由于没有用户活动导致自动注销[/color][/b]
[table=98%][tr][td]arpan@tintin# rsh hergearpan@herge# set autologout=1arpan@herge# dateSat Jun 28 18:13:07 IST 2008<After 1 min of inactivity>arpan@herge# auto-logoutConnection to herge closed. arpan@tintin# dateSat Jun 28 18:14:10 IST 2008[/td][/tr][/table]
[color=#000000]改进 tcsh 的安全性:监视正在使用系统的每个用户[/color]
必须一直监视用户对受保护系统的访问。tcsh 提供了内置 shell 变量 [font=新宋体]watch[/font],可以通过它查看正在使用系统的用户。语法是 [font=新宋体]set watch=(username1 ttyname1 username2 ttyname2 …)[/font]。这会监视用户 username1 是否在终端 ttyname1 上登录了。可以用特殊语法 [font=新宋体]set watch=(any any)[/font] 监视所有系统终端上的所有用户。
在默认情况下,[font=新宋体]watch[/font] 每 10 分钟检查一次系统中的登录/注销活动。可以通过 [font=新宋体]watch[/font] 语法中的第一个参数指定活动检查之间的时间间隔,例如:[font=新宋体]set watch=(5 any any)[/font]。见清单 8。

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

[b][color=#000000]清单 9. 使用 log 检查 watch 所影响的终端的使用情况[/color][/b]
[table=98%][tr][td]arpan@tintin# logarpan has logged on pts/0 from 132.132.6.73root has logged on consolezanies has logged pts/5 from 132.132.2.1[/td][/tr][/table]
[color=#000000]使用 prompt 变量跟踪当前的工作目录[/color]
tcsh 定义了 [font=新宋体]prompt[/font] 内置 shell 变量,可以通过这个变量定制 shell 提示。最常见的 UNIX 任务之一是跟踪当前所在的文件夹和机器。不需要一直使用 [font=新宋体]pwd[/font] 和 [font=新宋体]hostname[/font],只需通过设置 [font=新宋体]prompt[/font] 变量让 shell 提示反映当前的工作目录和主机名,即可实现相同的效果。见清单 10。

[b][color=#000000]清单 10. 通过修改 prompt 变量让 shell 提示反映当前的工作目录和主机[/color][/b]
[table=98%][tr][td]tcsh-6.15$ pwd/home/arpan/ibm1tcsh-6.15$ hostnametintintcsh-6.15$ echo $userarpantcsh-6.15$ set prompt="$user@`hostname`[$cwd] "arpan@tintin[/home/arpan/ibm1] [/td][/tr][/table]
但是,这种方式有一个问题:如果切换到另一个文件夹,提示并不会反映这一变化。为了随着切换文件夹连续改变提示,应该使用特殊别名 [font=新宋体]cmdcwd[/font]。如果已设置这个别名,那么在切换到新文件夹之后 tcsh 会执行 [font=新宋体]cmdcwd[/font] 映射到的命令。为了在提示中反映修改后的文件夹,[font=新宋体]cmdcwd[/font] 必须映射到 [font=新宋体]set prompt[/font] 命令(见清单 11)。

[b][color=#000000]清单 11. 使用 cmdcwd 别名在提示中反映修改后的文件夹[/color][/b]
[table=98%][tr][td]tcsh-6.15$ alias cmdcwd 'set prompt="$user@`hostname`[$cwd] " 'tcsh-6.15$ cd arpan@tintin[/home/arpan/ibm1] cd netarpan@tintin[/home/arpan/ibm1/net] [/td][/tr][/table]
注意,这个方案不但能够反映 [font=新宋体]cd[/font] 命令所做的文件夹切换,对于 [font=新宋体]pushd[/font] 和 [font=新宋体]popd[/font] 命令也是有效的。如果使用 X-Windows,另一个跟踪当前文件夹的好方法是,在跨多个文件夹工作时,在 xterm 标题栏上显示文件夹名。
例如,可以使用 [font=新宋体]echo[/font] 命令在 xterm 标题栏上显示一些基本信息。在 shell 提示上输入 [b][font=Lucida Console][size=2]echo "[Ctrl-v][Esc]]2; Hello [Ctrl-v][Ctrl-g]"[/size][/font][/b]。注意,[font=新宋体][Ctrl-v][/font] 表示按组合键 [b]Ctrl-V[/b]。输入这个命令序列,就会在 shell 提示上显示以下内容:[font=新宋体]echo "^[]2; Hello ^G"[/font]。执行这个命令之后,xterm 标题栏显示 [font=新宋体]Hello[/font]。清单 12 演示如何在 xterm 标题栏和提示中同时显示当前文件夹名。

[b][color=#000000]清单 12. 使用 cmdcwd 修改提示并设置 xterm 标题栏[/color][/b]
[table=98%][tr][td]arpan@tintin[/home/arpan1/ibm1]# alias cwdcmd 'set prompt="$user@`hostname`[$cwd]# ";     echo "^[]2;$cwd^G" '[/td][/tr][/table]
[color=#000000]自动纠正无效的命令用法[/color]
tcsh 提供内置变量 [font=新宋体]correct[/font],这有助于纠正无效的命令用法。例如,如果希望调用 [font=新宋体]perl[/font],但是输入的是 [font=新宋体]prl[/font],tcsh 会提示您纠正它。清单 13 给出一个示例。

[b][color=#000000]清单 13. tcsh 自动纠正输入[/color][/b]
[table=98%][tr][td]arpan@tintin# set correct=cmdarpan@tintin# prl CORRECT>perl (y|n|e|a)? y..arpan@tintin# fignerCORRECT>finger (y|n|e|a)? y..[/td][/tr][/table]
[color=#000000]定期执行特定的命令[/color]
系统管理员最常见的任务之一是监视磁盘使用量,并在磁盘使用量接近 100% 时采取措施。tcsh 的一个出色特性使我们能够轻松地定期执行特定的命令。把 [font=新宋体]periodic[/font] 映射到要定期执行的任务,并把 shell 内置变量 [font=新宋体]tperiod[/font] 设置为执行任务的时间间隔(以分钟为单位)。清单 14 演示如何使用 [font=新宋体]tperiod[/font] 和 [font=新宋体]periodic[/font]。注意,[font=新宋体]periodic[/font] 映射到脚本 [font=新宋体]checkdiskusage[/font],这个脚本检查磁盘使用量,tcsh 每 10 分钟运行它一次。

[b][color=#000000]清单 14. 使用 tcsh 内置变量定期执行命令[/color][/b]
[table=98%][tr][td]arpan@tintin# set tperiod=10arpan@tintin# alias periodic checkdiskusagearpan@tintin# cat checkdiskusagedf -k | awk -F" " '{print $5}' | grep "9[0-9]*"if ($status <> 0) then   mail –s "disk quota exceeded 90%" [email=root@officemail.comendifexit]root@officemail.comendifexit[/email] $status[/td][/tr][/table]
[color=#000000]针对每个终端分别设置历史文件[/color]
同一位 UNIX 系统用户常常从多个终端登录。为了针对每个终端分别维护命令执行历史,可以使用 [font=新宋体]histfile[/font] 和 [font=新宋体]savehist[/font] 环境变量。[font=新宋体]histfile[/font] 变量用来指定存储命令执行历史的文件;默认设置是 $HOME/.history。[font=新宋体]savehist[/font] 变量让 tcsh 存储用户在 shell 提示上输入的最后 [i]N[/i] 个命令。清单 15 中定义的 [font=新宋体]histfile[/font] 变量指定多个历史文件,这样就可以监视多个终端。

[b][color=#000000]清单 15. 使用 histfile 和 savehist 变量存储用户的命令历史[/color][/b]
[table=98%][tr][td]arpan@tintin# tty/dev/pts/0arpan@tintin# set savehist=25arpan@tintin# set histfile=~/.history_`tty | sed –e 's/\//_/g' `arpan@tintin# echo $histfile~/.history_dev_pts_0[/td][/tr][/table]
[color=#000000]监视运行一个命令花费的时间[/color]
为了监视执行一个 UNIX 进程花费的时间,可以设置 [font=新宋体]time[/font] 变量。输出显示用户时间、内核时间和实际流逝时间。[url=http://www.ibm.com/developerworks/cn/aix/library/au-tcsh/index.html#listing16][color=#996699]清单 16[/color][/url] 给出一个示例。
注意,可以用 tcsh 的内置命令 [font=新宋体]time[/font] 产生相同的输出,但是要对脚本做大量修改 —— 每个命令必须加上前缀 [font=新宋体]time[/font](例如,[font=新宋体]time du –sm /opt[/font])。如果使用 [font=新宋体]time[/font] 变量,那么只需在脚本的开头加上一行 [font=新宋体]set time[/font],就可以显示各个命令的执行时间。

[b][color=#000000]清单 16. 使用 time 显示各个命令的执行时间[/color][/b]
[table=98%][tr][td]arpan@tintin# cat scriptset timedu –sm /optdf –k /libarpan@tintin# tcsh –f ./script198  /opt0.628u 0.008s 0:02.00 0.0%      0+0k 0+0io 0pf+0wFilesystem           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[/td][/tr][/table]
[color=#000000]调试 shell 脚本:在发生错误时自动输出退出值[/color]
shell 变量 [font=新宋体]printexitvalue[/font] 是一个很有用的 tcsh 特性,它对脚本调试非常有帮助。在通常情况下,shell 脚本和 UNIX 程序在成功完成时返回零。如果设置这个变量,那么当脚本或程序返回非零值时 tcsh 会显示退出状态,这会指出潜在的错误。见清单 17。

[b][color=#000000]清单 17. 使用 printexitvalue 帮助调试[/color][/b]
[table=98%][tr][td]arpan@tintin# set printexitvaluearpan@tintin# ls /tmp/optls: /tmp/opt: No such file or directoryExit 2arpan@tintin# cat error_scriptls –l; return 2arpan@tintin# ./error_script./error_script: line 1: return: can only `return' from a function or sourced scriptExit 1arpan@tintin# unset printexitvalue; ls /tmp/optls: /tmp/opt: No such file or directory[/td][/tr][/table]
注意,在这个变量与一个 shell 脚本结合使用时,显示的是脚本的非零返回值,而不是脚本内部使用的命令或用户程序的返回值。
页: [1]
查看完整版本: tcsh shell 变量
Baidu