现在,您已经在 IBM?AIX?上工作了一段时间了 。您已经学习了几个基本命令,能够在目录结构中移动、创建和修改文件、查看正在运行的进程以及管理用户和系统 。这很不错,但是您希望了解 Unix?管理员输入的命令是什么意思 。这些命令中包含许多奇怪的符号 。在本文中,了解 |、>、>>、<、<<、[[ 和 ]] 等符号在 UNIX 和 Linux?中的意思,以及如何使用 &&、||、<、<= 和 != 操作符 。
管道
如果您熟悉 UNIX,那么管道(或 pipe)会是每天都要接触到的东西 。管道最初是由 Malcolm McIlroy 开发的,可以使用管道把一个命令的标准输出(stdout)定向到下一个命令的标准输入(stdin),这样就形成了连续执行的命令链 。可以在一个命令行上使用多个管道 。在许多时候,一个命令的 stdout 用作下一个命令的 stdin,第二个命令的 stdout 又被重定向到另一个命令的 stdin,依此类推 。
例如,在排除故障或执行日常检查时,大多数 UNIX 管理员首先做的事情之一是查看系统上当前正在运行的进程 。清单 1 演示这样的检查 。
清单 1. 日常进程检查示例
# ps –ef
UID PIDPPIDCSTIMETTY TIME CMD
root100Jul 27 - 0:05 /etc/init
root53442 1516740Jul 27 - 0:00 /usr/sbin/syslogd
root5742610Jul 27 - 0:00 /usr/lib/errdemon
root6151010Jul 27 - 23:55 /usr/sbin/syncd 60
root6563410Jul 27 - 0:00 /usr/ccs/bin/shlap64
root82002 1106520Jul 27 - 0:24 /usr/lpp/X11/bin/X -x abx
-x dbe -x GLX -D /usr/lib/X11//rgb -T -force :0 -auth /var/dt/A:0-SfIdMa
root8610210Jul 27 - 0:00 /usr/lib/methods/ssa_daemon -l ssa0
root 106538 1516740Jul 27 - 0:01 sendmail: accepting connections
root 11065210Jul 27 - 0:00 /usr/dt/bin/dtlogin -daemon
root 114754 1188540Jul 27 - 20:22 dtgreet
root 118854 1106520Jul 27 - 0:00 dtlogin <:0>-daemon
root 13108810Jul 27 - 0:07 /usr/atria/etc/lockmgr
-a /var/adm/atria/almd -q 1024 -u 256 -f 256
root 14758410Jul 27 - 0:01 /usr/sbin/cron
root 155816 1516740Jul 27 - 0:04 /usr/sbin/portmap
root 163968 1516740Jul 27 - 0:00 /usr/sbin/qdaemon
root 168018 1516740Jul 27 - 0:00 /usr/sbin/inetd
root 172116 1516740Jul 27 - 0:03 /usr/sbin/xntpd
root 180314 1516740Jul 27 - 0:19 /usr/sbin/snmpmibd
root 184414 1516740Jul 27 - 0:21 /usr/sbin/aixmibd
root 188512 1516740Jul 27 - 0:20 /usr/sbin/hostmibd
root 192608 1516740Jul 27 - 7:46 /usr/sbin/muxatmd
root 196718 1516740 11:00:27 - 0:00 /usr/sbin/rpc.mountd
root 200818 1516740Jul 27 - 0:00 /usr/sbin/biod 6
root 213108 1516740Jul 27 - 0:00 /usr/sbin/nfsd 3891
root 221304 2458940Jul 27 - 0:05 /bin/nsrexecd
daemon 225402 1516740 11:00:27 - 0:00 /usr/sbin/rpc.statd
root 229498 1516740 11:00:27 - 0:00 /usr/sbin/rpc.lockd
root 241794 1516740Jul 27 - 0:51 /usr/lib/netsvc/yp/ypbind
root 24589410Jul 27 - 0:00 /bin/nsrexecd
root 25396010Jul 27 - 0:00 ./mflm_manager
root 274568 1516740Jul 27 - 0:00 /usr/sbin/sshd -D
root 28276610Jul 27lft0 0:00 /usr/sbin/getty /dev/console
root 29095810Jul 27 - 0:00 /usr/lpp/diagnostics/bin/diagd
root 315646 1516740Jul 27 - 0:00 /usr/sbin/lpd
root 31966410Jul 27 - 0:00 /usr/atria/etc/albd_server
root 340144 1680180 12:34:56 - 0:00 rpc.ttdbserver 100083 1
root 376846 1680180Jul 30 - 0:00 rlogind
cormany 409708 5695220 19:29:27 pts/1 0:00 -ksh
root 569522 1680180 19:29:26 - 0:00 rlogind
cormany 733188 4097083 19:30:34 pts/1 0:00 ps -ef
root 749668 1680180Jul 30 - 0:00 rlogind
系统上当前正在运行的进程的列表可能像 清单 1 这么简单;但是,大多数生产系统运行的进程更多,这会使 ps 的输出更长 。为了把这个列表缩短到自己需要的范围,可以使用管道把 ps –ef 的标准输出重定向到 grep,从而搜索自己真正希望看到的结果 。清单 2 把 清单 1 产生的进程列表重定向到 grep,搜索字符串 “rpc 和 “ksh 。
清单 2. 把进程列表重定向到 grep
# ps –ef | grep –E "rpc|ksh"
root 196718 1516740 11:00:27 - 0:00 /usr/sbin/rpc.mountd
daemon 225402 1516740 11:00:27 - 0:00 /usr/sbin/rpc.statd
root 229498 1516740 11:00:27 - 0:00 /usr/sbin/rpc.lockd
root 340144 1680180 12:34:56 - 0:00 rpc.ttdbserver 100083 1
cormany 409708 5695220 19:29:27 pts/1 0:00 -ksh
cormany 733202 4097080 19:52:20 pts/1 0:00 grep -E rpc|ksh
当多次把 stdout 重定向到 stdin 时,管道的使用方法可以很复杂 。在下面的示例中,扩展了前面的 ps 和 grep 示例,把它的 stdout 重定向到另一个 grep,其作用是排除包含 “grep 或 “ttdbserver 的字符串 。当最后的 grep 操作完成时,再次使用管道把 stdout 重定向到一个 awk 语句,其作用是输出进程标识符(PID)大于 200,000 的所有进程:
# ps –ef | grep –E "rpc|ksh" | grep -vE "grep|rpc.ttdbserver" |
awk -v _MAX_PID=200000 '{if ($2 > _MAX_PID) {print "PID for
process",$8,"is greater than", _MAX_PID}}'
PID for process /usr/sbin/rpc.statd is greater than 200000
PID for process /usr/sbin/rpc.lockd is greater than 200000
PID for process -ksh is greater than 200000
图 1 通过图形说明命令的 stdout 重定向到后续命令的 stdin 的次序 。
图 1. 管道示例
用 >、>>、< 和 << 执行数据重定向
通过命令行界面(CLI)执行命令的另一个重要方面是,能够把各种输出写到一个设备,或者把来自另一个设备的输入读取到命令中 。要想写一个命令的输出,需要在执行的命令后面加上大于号(> 或 >>)和所需的目标文件名或设备 。如果目标文件不存在,而且您对目标目录有写权限,那么 > 和 >> 会创建这个文件并根据您的 umask 设置权限,然后把命令的输出写到刚创建的文件中 。但是,如果这个文件存在,> 会尝试打开文件并覆盖整个内容 。如果希望在这个文件中追加内容,那么只需使用 >> 。可以认为它的作用是把左边命令的输出数据流移动到右边的目标文件中(即 ->