添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Oracle Account

Manage your account and access personalized content. Sign up for an Oracle Account

Sign in to Cloud

Access your cloud dashboard, manage orders, and more. Sign up for a free trial

DBA:Linux
下载
 适用于 Linux 的 Oracle 数据库 10g
关键词
linux , database , dba , 全部

高级 Linux 命令精通指南,第 2 部分


作者:Arup Nanda Oracle ACE

2007 年 2 月发表

在本系列的 第 1 部分 中,您学习了一些有用但并不广为人知的命令,以及各种常用命令的一些人们并不熟知的参数,它们可以帮助您更高效地完成工作。继续学习本系列,您将了解到一些对 Oracle 用户(无论是开发人员还是 DBA)很有帮助的更高级的 Linux 命令。

alias 和 unalias

假设您要检查 shell 中设置的 ORACLE_SID 环境变量。您必须键入:

echo $ORACLE_HOME

作为 DBA 或开发人员,您需要频繁使用此命令,很快就会对输入这 16 个字符感到厌倦。有没有更简单的方法?

当然有:您可以使用 alias 命令。使用该方法,您可以创建一个简短的别名(如 "os")来代表整条命令:

alias os='echo $ORACLE_HOME'

现在,每次要检查 ORACLE_SID 时,您只需键入 "os"(没有引号),Linux 就会执行别名代表的命令。

然而,如果您注销并重新登录,别名就不见了,您需要再次输入 alias 命令。要取消这个步骤,您只需将该命令置于 shell 的配置文件中。对于 bash,配置文件为主目录中的 .bash_profile(注意文件名前面的句点,它是文件名的一部分)。对于 bourne 和 korn shell,配置文件为 .profile;对于 c-shell,配置文件为 .chsrc。

您可以使用任何名称创建别名。例如,我总是将 rm -i 命令的别名创建为 rm ,从而使它成为交互式命令。

alias rm=’rm -i’

我每次执行 rm 命令后,如果不输入 "y",Linux 就会提示我进行确认,而不会删除该文件,因此不会出现意外删除重要文件的情况。另外,我也以相同的方式使用 mv (以一个新名称另存该文件,防止意外覆盖现有的文件)和 cp (复制该文件)。

以下是一些我喜欢定义的非常有用的别名:

alias bdump='cd $ORACLE_BASE/admin/$ORACLE_SID/bdump'
alias l='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias mv='mv -i'
alias oh='cd $ORACLE_HOME'
alias os='echo $ORACLE_SID'
alias rm='rm -i'
alias tns='cd $ORACLE_HOME/network/admin'

要查看 shell 中已定义的别名,使用 alias 即可,无需任何参数。

但这里有一个小问题。我已经定义了一个别名 rm 来执行 rm -i 。每次我试图删除一个文件时,该命令都会提示我进行确认。但如果我要删除多个文件并确信无需确认即可删除时,该怎么办?

解决方案很简单:要取消该别名,然后只使用命令,我需要输入两个单引号:

$ ''rm *

注意,rm 命令前面有两个单引号 ('),而不是两个双引号。这将取消别名 rm 。另一种方法是使用反斜线 (\):

$ \rm *

要删除一个以前定义的别名,只需使用 unalias 命令:

$ unalias rm

ls

ls 是简单的常用命令,但几乎从未发挥其全部潜力。如果不加任何选项,则 ls 仅以表格格式显示所有文件和目录。

admin            has                  mesg         precomp
apex             hs                   mgw          racg
assistants       install              network      rdbms
                                ... output snipped ...
                            

要以列表形式显示所有文件和目录,使用 -1 选项(数字 1,不是字母 "l")。

$ ls -1
admin
assistants
                                ... output snipped ...
                            

在其中的文件名需要传给另一个程序或命令以进行操作的 shell 脚本中,该选项很有用。

您一定使用过用来显示文件和目录所有属性的 -l 选项(字母 "l",不是数字 "1")。让我们再看看它的作用方式:

$ ls -l 
total 272
drwxr-xr-x    3 oracle   oinstall     4096 Sep  3 03:27 admin
drwxr-x---    7 oracle   oinstall     4096 Sep  3 02:32 apex
drwxr-x---    7 oracle   oinstall     4096 Sep  3 02:29 assistants

第一列显示了文件类型及文件的权限:"d" 代表目录,"-" 代表普通文件,"c" 代表字符设备,"b" 代表块设备,"p" 代表命名管道,"l"(字母 L 的小写形式,不是 I)代表符号链接。

一个非常有用的选项是 --color,它根据文件类型用多种颜色显示文件。以下是一个示例屏幕截图:

注意,file1 和 file2 是普通文件。link1 是符号链接,显示为红色;dir1 是目录,显示为黄色;pipe1 是命名管道,显示为其它颜色以便于识别。

在某些版本中, ls 命令自带预先安装的别名(在上一部分中进行了描述),如 ls --color; ,因此您键入 "ls" 时将看到彩色的文件。然而,该方法可能并不符合需要,尤其是当您的输出如上所示时。您可以更改颜色,但只需关闭别名就可以更快地达成您的需要:

$ alias ls="''ls"  

另一个有用的选项是 -F 选项,它在每个文件后面添加一个符号来显示文件的类型:在目录后面添加 "/",在符号链接后面添加 "@",在命名管道后面添加 "|"。

$ ls -F
dir1/  file1  file2  link1@  pipe1|

如果某个目录下面包含一个子目录,您希望只列出该目录,则 ls -l 还将显示该子目录中的内容。例如,假设该目录结构如下所示:

/dir1
+-->/subdir1
+--> subfile1
+--> subfile2

目录 dir1 含有一个子目录 subdir1 和两个文件:subfile1 和 subfile2。如果您只希望查看目录 dir1 的属性,则执行以下命令:

$ ls -l dir1
total 4
drwxr-xr-x    2 oracle   oinstall     4096 Oct 14 16:52 subdir1
-rw-r--r--    1 oracle   oinstall        0 Oct 14 16:48 subfile1
-rw-r--r--    1 oracle   oinstall        0 Oct 14 16:48 subfile2

注意,输出中未列出目录 dir1,而是显示了该目录的内容。处理目录时需要该行为。如果仅希望显示 dir1 目录,则需要使用 -d 命令。

$ ls -dl dir1
drwxr-xr-x    3 oracle   oinstall     4096 Oct 14 16:52 dir1

如果您注意以下 ls -l 的输出:

-rwxr-x--x    1 oracle   oinstall 10457761 Apr  6  2006 rmanO
-rwxr-x--x    1 oracle   oinstall 10457761 Sep 23 23:48 rman
-rwsr-s--x    1 oracle   oinstall 93300507 Apr  6  2006 oracleO
-rwx------    1 oracle   oinstall 93300507 Sep 23 23:49 oracle

您会发现文件的大小是用字节显示的。显示小文件时,这样做可能很简单。当文件大小很大时,较长的数字可能难以阅读。此时,使用选项 "-h" 以易读的格式来显示大小就很方便了。

$ ls -lh
-rwxr-x--x    1 oracle   oinstall      10M Apr  6  2006 rmanO
-rwxr-x--x    1 oracle   oinstall      10M Sep 23 23:48 rman
-rwsr-s--x    1 oracle   oinstall      89M Apr  6  2006 oracleO
-rwx------    1 oracle   oinstall      89M Sep 23 23:49 oracle

注意文件大小是如何用 M(代表兆字节)、K(代表千字节)等显示的。

$ ls -lr

参数 -r 以相反的顺序显示输出。在该命令中,文件将以相反的字母顺序显示。

$ ls -lR

-R 操作符使 ls 命令以递归方式执行,即进入子目录并显示其中的文件。

如果希望按从大到小的顺序显示文件怎么办?使用 -S 参数即可以实现此操作。

$ ls -lS
total 308
-rw-r-----    1 oracle   oinstall    52903 Oct 11 18:31 sqlnet.log
-rwxr-xr-x    1 oracle   oinstall     9530 Apr  6  2006 root.sh
drwxr-xr-x    2 oracle   oinstall     8192 Oct 11 18:14 bin
drwxr-x---    3 oracle   oinstall     8192 Sep 23 23:49 lib

xargs

大多数 Linux 命令都会产生输出:文件列表、字符串列表等。但如果要使用其他某个命令并将前一个命令的输出作为参数该怎么办?例如, file 命令显示文件类型(可执行文件、ascii 文本等);您可以处理输出,使其仅显示文件名,现在您希望将这些名称传递给 ls -l 命令以查看时间戳记。 xargs 命令就是用来完成此项工作的。它允许您对输出执行其他某些命令。记住下面这个来自于第 1 部分中的语法:

file -Lz * | grep ASCII | cut -d":" -f1 | xargs ls -ltr
让我们来剖析这个命令字符串。第一个, file -Lz * ,用于查找是符号链接或者经过压缩的文件。它将输出传递给下一个命令 grep ASCII ,该命令在其中搜索 "ASCII" 字符串并产生如下所示的输出:
alert_DBA102.log:        ASCII English text
alert_DBA102.log.Z:      ASCII text (compress'd data 16 bits)
dba102_asmb_12307.trc.Z: ASCII English text (compress'd data 16 bits)
dba102_asmb_20653.trc.Z: ASCII English text (compress'd data 16 bits)
由于我们只对文件名感兴趣,因此我们应用下一个命令 cut -d":" -f1 ,仅显示第一个字段:
alert_DBA102.log
alert_DBA102.log.Z
dba102_asmb_12307.trc.Z
dba102_asmb_20653.trc.Z

现在,我们希望使用 ls -l 命令,将上述列表作为参数进行传递,一次传递一个。 xargs 命令允许您这样做。最后一部分, xargs ls -ltr ,用于接收输出并对其执行 ls -ltr 命令,如下所示:

ls -ltr alert_DBA102.log
ls -ltr alert_DBA102.log.Z
ls -ltr dba102_asmb_12307.trc.Z
ls -ltr dba102_asmb_20653.trc.Z

因此, xargs 本身虽然没有多大用处,但在与其他命令相结合时,它的功能非常强大。

下面是另一个示例,我们希望计算这些文件中的行数:

$ file * | grep ASCII | cut -d":" -f1  | xargs wc -l
  47853 alert_DBA102.log
     19 dba102_cjq0_14493.trc
  29053 dba102_mmnl_14497.trc
    154 dba102_reco_14491.trc
     43 dba102_rvwr_14518.trc
  77122 total

(注:上述任务还可用以下命令完成:)

$ wc -l ‘file * | grep ASCII | cut -d":" -f1 | grep ASCII | cut -d":" -f1‘

xargs 版本用于阐释概念。Linux 可以用几种方法来完成同一个任务;请使用最适合您的情况的方法。

使用该方法,您可以快速重命名目录中的文件。

$ ls | xargs -t -i mv {} {}.bak

-i 选项告诉 xargs 用每项的名称替换 {}。-t 选项指示 xargs 先打印命令,然后再执行。

另一个非常有用的操作是当您使用 vi 打开要编辑的文件时:

$ file * | grep ASCII | cut -d":" -f1 | xargs vi

该命令使用 vi 逐个打开文件。当您希望搜索多个文件并打开它们进行编辑时,使用该命令非常方便。

它还有几个选项。最有用的可能是 -p 选项,它使操作具有可交互性:

$ file * | grep ASCII | cut -d":" -f1 | xargs -p vi
vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc
  dba102_reco_14491.trc dba102_rvwr_14518.trc ?...
                            

此处的 xarg 要求您在运行每个命令之前进行确认。如果您按下 "y",则执行命令。当您对文件进行某些可能有破坏且不可恢复的操作(如删除或覆盖)时,您会发现该选项非常有用。

-t 选项使用一个详细模式;它显示要运行的命令,是调试过程中一个非常有帮助的选项。

如果传递给 xargs 的输出为空怎么办?考虑以下命令:

$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t wc -l
wc -l 
在此处,搜索 "SSSSSS" 后没有匹配的内容;因此 xargs 的输入均为空,如第二行所示(由于我们使用 -t 这个详细选项而产生的结果)。虽然这可能会有所帮助,但在某些情况下,如果没有要处理的内容,您可能希望停止 xargs ;如果是这样,可以使用 -r 选项:
$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t -r wc -l

如果没有要运行的内容,该命令退出。

假设您希望使用 rm 命令(该命令将作为 xargs 命令的参数)删除文件。然而, rm 只能接受有限数量的参数。如果您的参数列表超出该限制怎么办?xargs 的 -n 选项限制单个命令行的参数个数。

下面显示了如何限制每个命令行仅使用两个参数:即使向 xargs ls -ltr 传递五个文件,但每次向 ls -ltr 仅传递两个文件。

$ file * | grep ASCII | cut -d":" -f1 | xargs -t -n2 ls -ltr  
ls -ltr alert_DBA102.log dba102_cjq0_14493.trc 
-rw-r-----    1 oracle   dba           738 Aug 10 19:18 dba102_cjq0_14493.trc
-rw-r--r--    1 oracle   dba       2410225 Aug 13 05:31 alert_DBA102.log
ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc 
-rw-r-----    1 oracle   dba       5386163 Aug 10 17:55 dba102_mmnl_14497.trc
-rw-r-----    1 oracle   dba          6808 Aug 13 05:21 dba102_reco_14491.trc
ls -ltr dba102_rvwr_14518.trc 
-rw-r-----    1 oracle   dba          2087 Aug 10 04:30 dba102_rvwr_14518.trc

使用该方法,您可以快速重命名目录中的文件。

$ ls | xargs -t -i mv {} {}.bak

-i 选项告诉 xargs 用每项的名称替换 {}。

rename

正如您所知道的那样, mv 命令对文件进行重命名。例如,

$ mv oldname newname
将 oldname 文件重命名为 newname。但如果您不知道文件名,那该怎么办? rename 命令在此处就可以大显身手了。
rename .log .log.‘date +%F-%H:%M:%S‘ *

用 .log.<日期格式> 替换所有扩展名为 .log 的文件。因此,sqlnet.log 变为 sqlnet.log.2006-09-12-23:26:28。

find

最受 Oracle 用户欢迎的命令之一是 find 命令。到目前为止,您了解了如何使用 find 在给定目录中查找文件。下面的示例显示在当前目录中查找以单词 "file" 开头的文件:

$ find . -name "file*"
./file2
./file1
./file3
./file4

然而,如果您希望搜索 FILE1、FILE2 等名称怎么办?-name "file*" 不会与之匹配。对于区分大小写的搜索,可以使用 -iname 选项:

$ find . -iname "file*"
./file2
./file1
./file3
./file4
./FILE1
./FILE2

您可以限制搜索范围,仅搜索特定类型的文件。例如,上述命令将获得所有类型的文件:普通文件、目录、符号链接等。如果仅搜索普通文件,可使用 -type f 参数。

$ find . -name "orapw*" -type f 
./orapw+ASM
./orapwDBA102
./orapwRMANTEST
./orapwRMANDUP
./orapwTESTAUX

-type 可以接受修饰符 f(普通文件)、l(符号链接)、d(目录)、b(块设备)、p(命名管道)、c(字符设备)、s(套接字)。

对上述命令的一个小技巧是,将其与您在第 1 部分中学到的 file 命令相结合。 file 命令告诉您文件的类型。您可以将其作为 find 命令的输出的后处理器进行传递。-exec 参数执行该参数后面的命令。在该示例中,在 find 后执行的命令是 file

$ find . -name "*oraenv*" -type f -exec file {} \;
./coraenv: Bourne shell script text executable
./oraenv: Bourne shell script text executable

当您希望弄清楚 ASCII 文本文件是否可能是某种类型的 shell 脚本时,该命令非常有用。

如果您用 -ok 替换 -exec,则执行该命令之前要求您先进行确认。下面就是一个例子:

$ find . -name "sqlplus*" -ok {} \;      
< {} ... ./sqlplus > ? y
SQL*Plus: Release 9.2.0.5.0 - Production on Sun Aug 6 11:28:15 2006
Enter user-name: / as sysdba
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
SQL> exit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
< È* ... ./sqlplusO > ? n
在此示例中,我们要求 shell 查找所有以 "sqlplus" 开头的程序并执行它们。注意,-ok 与 {} 之间什么都没有,因此仅执行找到的文件。shell 找到两个文件 — sqlplus 和 sqlplusO — 并在每次找到后询问您是否希望执行文件。我们针对 "sqlplus" 回答 "y",因此执行该文件。退出之后,shell 提示您找到了第二个文件 (sqlplusO),再次要求您确认,我们回答 "n",因此不执行该文件。

适用于 Oracle 用户的技巧

Oracle 产生许多不必要的文件:跟踪文件、日志文件、转储文件等。如果不定期清理,这些文件就会占满文件系统,从而导致数据库暂停。

为了避免出现这种情况,只需搜索扩展名为 "trc" 的文件,如果这些文件的存在时间超过三天,则将其删除。一个简单的命令即可实现该操作:

find . -name "*.trc" -ctime +3 -exec rm {} \;

要强制删除存在不到三天的文件,请使用 -f 选项。

find . -name "*.trc" -ctime +3 -exec rm -f {} \;

如果只想列出文件:

find . -name "*.trc" -ctime +3 -exec ls -l {} \;

m4

该命令接受一个输入文件并用所传递的参数替换其中的字符串,类似于替换变量。例如,以下是一个输入文件:

$ cat temp
The COLOR fox jumped over the TYPE fence.

如果要用 "brown" 替换字符串 "COLOR",用 "broken" 替换 "TYPE",您可以使用以下命令:

$ m4 -DCOLOR=brown -DTYPE=broken temp
The brown fox jumped over the broken fence.
Else, if you want to substitute "white" and "high" for the same:
$ m4 -DCOLOR=white -DTYPE=high temp  
The white fox jumped over the high fence.

whence 和 which

这两个命令用于找到所提到的可执行文件在用户路径中的存储位置。在路径中找到可执行文件之后,这两个命令的行为基本相同,都显示文件的路径:

$ which sqlplus  
/u02/app/oracle/products/10.2.0.1/db1/bin/sqlplus
$ whence sqlplus 
/u02/app/oracle/products/10.2.0.1/db1/bin/sqlplus
                            

输出完全相同。然而,如果在路径中未找到可执行文件,则两者的行为不同。 which 命令生成一条显式消息:

$ which sqlplus1
/usr/bin/which: no sqlplus1 in (/u02/app/oracle/products/10.2.0.1/db1/bin:/usr
                                /kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin)
                            

whence 命令不生成任何消息:

$ whence sqlplus1]

而是返回到 shell 提示符。如果在路径中未找到可执行文件,这将很有帮助(不显示消息):

$ whence invalid_command
$ which invalid_command
which: no invalid_command in (/usr/kerberos/sbin:/usr/kerberos/bin:/bin:/sbin:
                              /usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:
                              /usr/bin/X11:/usr/X11R6/bin:/root/bin)     
                            

如果 whence 在路径中未找到可执行文件,它不返回任何消息,但返回代码不为零。在 shell 脚本中可以利用这个事实;例如:

RC=‘whence myexec‘
If [ $RC -ne "0" ]; then
   echo "myexec is not in the $PATH"

它的一个非常有用的选项是 -i 选项,该选项显示别名以及可执行文件(如果有的话)。例如,您在本文开始部分了解了别名的用法。 rm 命令实际上是我的 shell 中的一个别名,系统中某处也有一个 rm 命令。

$ which ls
/bin/ls
$ which -i ls
alias ls='ls --color=tty'
        /bin/ls

其默认行为是显示可执行文件在路径中的首次出现。如果可执行文件位于路径的多个目录中,则忽略其后的出现。您可以通过 -a 选项查看可执行文件的所有出现位置。

$ which java   
/usr/bin/java
$ which -a java
/usr/bin/java
/home/oracle/oracle/product/11.1/db_1/jdk/jre/bin/java

top

top 命令可能是 Oracle DBA 在 Linux 上管理数据库时最有用的命令。如果系统很慢,您可能希望查看谁在占用所有 CPU 和/或内存。要显示最大进程,可以使用 top 命令。

注意,与其他命令不同, top 不会产生输出,屏幕内容保持不变。它刷新屏幕以显示新信息。因此,如果您只执行 top 并保持屏幕一直开启,则屏幕始终显示最新信息。要停止并退出 shell,可以按下 Ctrl-C。

$ top
18:46:13  up 11 days, 21:50,  5 users,  load average: 0.11, 0.19, 0.18 
151 processes: 147 sleeping, 4 running, 0 zombie, 0 stopped 
CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
           total   12.5%    0.0%    6.7%   0.0%     0.0%    5.3%   75.2% 
Mem:  1026912k av,  999548k used,   27364k free,       0k shrd,  116104k buff 
                    758312k actv,  145904k in_d,   16192k in_c 
Swap: 2041192k av,  122224k used, 1918968k free                  590140k cached 
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
  451 oracle    15   0  6044 4928  4216 S     0.1  0.4   0:20   0 tnslsnr 
 8991 oracle    15   0  1248 1248   896 R     0.1  0.1   0:00   0 top 
    1 root      19   0   440  400   372 S     0.0  0.0   0:04   0 init 
    2 root      15   0     0    0     0 SW    0.0  0.0   0:00   0 keventd 
    3 root      15   0     0    0     0 SW    0.0  0.0   0:00   0 kapmd 
    4 root      34  19     0    0     0 SWN   0.0  0.0   0:00   0 ksoftirqd/0 
    7 root      15   0     0    0     0 SW    0.0  0.0   0:01   0 bdflush 
    5 root      15   0     0    0     0 SW    0.0  0.0   0:33   0 kswapd 
    6 root      15   0     0    0     0 SW    0.0  0.0   0:14   0 kscand 
    8 root      15   0     0    0     0 SW    0.0  0.0   0:00   0 kupdated 
    9 root      25   0     0    0     0 SW    0.0  0.0   0:00   0 mdrecoveryd
                                ... output snipped ...
                            

让我们来看看产生的不同类型的信息。第一行:

18:46:13  up 11 days, 21:50,  5 users,  load average: 0.11, 0.19, 0.18

显示当前时间 (18:46:13),该系统已经运行了 11 天;并且已经工作了 21 小时 50 秒。后面显示的分别是最近 1、5、15 分钟的系统平均负载 (0.11、0.19、0.18)。(顺便提一下,您也可以通过执行 uptime 命令来获得这些信息。)

如果不需要平均负载,按下字母 "l"(小写字母 L);它将关闭。要再次将其打开,按下 l。第二行:

151 processes: 147 sleeping, 4 running, 0 zombie, 0 stopped

显示进程数、运行的进程数、休眠的进程数等。第三行和第四行:

CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
           total   12.5%    0.0%    6.7%   0.0%     0.0%    5.3%   75.2%

显示 CPU 利用率的详细信息。上面一行显示用户进程占用了 CPU 的 12.5%,系统占用了 6.7%。用户进程中包括 Oracle 进程。按下 "t" 可以关闭和打开这三行。如果有多个 CPU,屏幕将在每行显示一个 CPU 的信息。

接下来的两行:

Mem:  1026912k av, 1000688k used,  26224k free,    0k shrd,  113624k buff 
                    758668k actv,  146872k in_d,  14460k in_c
Swap: 2041192k av, 122476k used,   1918716k free             591776k cached

显示可用的和已利用的内存。内存总量为 "1026912k av"(大约 1GB),其中只有 26224k(即 26MB)是可用的。交换空间为 2GB;但几乎并未使用。要关闭和打开这两行,可以按下 "m"。

其余的显示内容以表格格式显示进程。下面对各列进行解释:

描述

PID 进程的进程 ID
USER

运行该进程的用户
PRI

进程的优先级
NI nice 值:该值越高,任务的优先级越低
SIZE

该进程使用的内存(代码+数据+堆栈)
RSS

该进程使用的物理内存
SHARE

该进程使用的共享内存
STAT

该进程的状态,用代码显示。一些主要的状态代码包括:
R — 正在运行
S — 正在休眠
Z — 迟滞
T — 已停止

您还会看到第二个和第三个字符,它们表示:
W — 已换出的进程
N — 正 nice 值
%CPU

该进程使用的 CPU 百分比
%MEM

该进程使用的内存百分比
TIME

该进程使用的总 CPU 时间
CPU

如果这是一个多处理器系统,该列指明正在其上运行进程的 CPU 的 ID。
COMMAND 该进程发出的命令

显示 top 时,您可以按几个键来设置希望的显示格式。按下大写字母 M 键可根据内存使用情况对输出进行排序。(注意,使用小写字母 m 将在显示屏的顶部打开或关闭内存汇总行。)当您希望了解谁在占用内存时,该键非常有用。示例输出如下:

PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
31903 oracle    15   0 75760  72M 72508 S     0.0  7.2   0:01   0 ora_smon_PRODB2 
31909 oracle    15   0 68944  66M 64572 S     0.0  6.6   0:03   0 ora_mmon_PRODB2 
31897 oracle    15   0 53788  49M 48652 S     0.0  4.9   0:00   0 ora_dbw0_PRODB2

既然您了解了如何解释输出,我们来看看如何使用命令行参数。

最有用的参数是 -d,它指示两次屏幕刷新之间的延迟。要每秒刷新一次,则使用 top -d 1

另一个有用的选项是 -p。如果您希望只监视几个进程而并非全部,可以在 -p 选项后指定这几个进程。要监视进程 13609、13608 和 13554,执行以下命令:

top -p 13609 -p 13608 -p 13554

这将以和 top 命令相同的格式显示结果,但只显示特定进程的信息。

适用于 Oracle 用户的技巧

众所周知,使用 top 实用程序分析数据库服务器的性能非常方便。下面是部分 top 输出。

20:51:14  up 11 days, 23:55,  4 users,  load average: 0.88, 0.39, 0.27 
113 processes: 110 sleeping, 2 running, 1 zombie, 0 stopped 
CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
           total    1.0%    0.0%    5.6%   2.2%     0.0%   91.2%    0.0% 
Mem:  1026912k av, 1008832k used,   18080k free,       0k shrd,   30064k buff 
                    771512k actv,  141348k in_d,   13308k in_c 
Swap: 2041192k av,   66776k used, 1974416k free                  812652k cached 
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
16143 oracle    15   0 39280  32M 26608 D     4.0  3.2   0:02   0 oraclePRODB2...
    5 root      15   0     0    0     0 SW    1.6  0.0   0:33   0 kswapd
                                  ... output snipped ...
                              

我们来仔细分析此输出。首先,您需要注意 CPU states 下面的 "idle" 列;该列为 0.0%,这意味着 CPU 被完全占用来执行某项任务。问题是 CPU 在做什么?将注意力转向 "system" 列,就在左侧不远处;该列显示 5.6%。这说明,系统本身占用的 CPU 并不多。再向左就是 "user" 列,该列显示 1.0%。由于用户进程还包括 Oracle,因此 Oracle 并未占用 CPU 周期。那么,到底是什么占用了整个 CPU?

答案就在同一行右侧 "iowait" 列下面,该列为 91.2%。一切都明白了:91.2% 的 CPU 时间都在等待 IO。

为什么会有这么多的 IO 等待?答案在显示内容中。注意最消耗资源的进程的 PID:16143 您可以使用以下查询来确定该进程在做什么:

select s.sid, s.username, s.program
from v$session s, v$process p
where spid = 16143
and p.addr = s.paddr
       SID USERNAME PROGRAM
------------------- -----------------------------
       159 SYS      rman@prolin2 (TNS V1-V3)    

rman 进程在进行与 CPU 周期相关的 IO 等待。该信息可以帮助您确定接下来的操作流程。

skill 和 snice

通过前面的讨论,您已经了解了如何识别占用 CPU 的资源。如果您发现了一个占用大量 CPU 和内存的进程,但又不想停止它,该怎么办?考虑下面的 top 输出:

$ top -c -p 16514
23:00:44  up 12 days,  2:04,  4 users,  load average: 0.47, 0.35, 0.31 
1 processes: 1 sleeping, 0 running, 0 zombie, 0 stopped 
CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
           total    0.0%    0.6%    8.7%   2.2%     0.0%   88.3%    0.0% 
Mem:  1026912k av, 1010476k used,   16436k free,       0k shrd,   52128k buff 
                    766724k actv,  143128k in_d,   14264k in_c 
Swap: 2041192k av,   83160k used, 1958032k free                  799432k cached 
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
16514 oracle    19   4 28796  26M 20252 D N   7.0  2.5   0:03   0 oraclePRODB2...

既然您确认进程 16514 占用了大量内存,您就可以使用 skill 命令“冻结”它,而不是停止它。

$ skill -STOP 1

之后,检查 top 输出:

23:01:11  up 12 days,  2:05,  4 users,  load average: 1.20, 0.54, 0.38 
1 processes: 0 sleeping, 0 running, 0 zombie, 1 stopped 
CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
           total    2.3%    0.0%    0.3%   0.0%     0.0%    2.3%   94.8% 
Mem:  1026912k av, 1008756k used,   18156k free,       0k shrd,    3976k buff 
                    770024k actv,  143496k in_d,   12876k in_c 
Swap: 2041192k av,   83152k used, 1958040k free                  851200k cached 
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
16514 oracle    19   4 28796  26M 20252 T N   0.0  2.5   0:04   0 oraclePRODB2...

现在,CPU 从 0% 空闲变为 94% 空闲。该进程被有效冻结。过一段时间之后,您可能希望唤醒该进程:

$ skill -CONT 16514

如果希望暂时冻结进程以便为完成更重要的进程腾出空间,该方法非常有用。

此命令用途很广。如果您要停止 "oracle" 用户的所有进程,只需要一个命令即可实现:

$ skill -STOP oracle

可以使用用户、PID、命令或终端 id 作为参数。以下命令可停止所有 rman 命令。

$ skill -STOP rman

如您所见, skill 决定您输入的参数(进程 ID、用户 ID 或命令)并进行相应操作。这可能会导致在某些情况下出现这样的问题:您可能具有同名的用户和命令。最好的示例是 "oracle" 进程,通常由用户 "oracle" 运行。因此,当您希望停止名为 "oracle" 的进程时,可执行以下命令:

$ skill -STOP oracle

用户 "oracle" 的所有进程都停止,包括您可能要使用的会话。要非常明确地执行命令,您可以选择使用一个新参数指定参数的类型。要停止一个名为 oracle 的命令,可执行以下命令:

$ skill -STOP -c oracle

snice 命令的功能与 skill 类似。但它用于降低进程的优先级,而不是停止进程。首先,检查 top 输出:

  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
    3 root      15   0     0    0     0 RW    0.0  0.0   0:00   0 kapmd 
13680 oracle    15   0 11336  10M  8820 T     0.0  1.0   0:00   0 oracle 
13683 oracle    15   0  9972 9608  7788 T     0.0  0.9   0:00   0 oracle 
13686 oracle    15   0  9860 9496  7676 T     0.0  0.9   0:00   0 oracle 
13689 oracle    15   0 10004 9640  7820 T     0.0  0.9   0:00   0 oracle 
13695 oracle    15   0  9984 9620  7800 T     0.0  0.9   0:00   0 oracle 
13698 oracle    15   0 10064 9700  7884 T     0.0  0.9   0:00   0 oracle 
13701 oracle    15   0 22204  21M 16940 T     0.0  2.1   0:00   0 oracle

现在,将 "oracle" 进程的优先级降低四个点。注意,该值越高,优先级越低。

$ snice +4 -u oracle
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
16894 oracle    20   4 38904  32M 26248 D N   5.5  3.2   0:01   0 oracle

注意,NI 列(nice 值)现在是 4,优先级现在设置为 20,而不是 15。这对于降低优先级非常有帮助。


Arup Nanda ( arup@proligence.com ) 担任 Oracle DBA 已 12 余载,处理过从性能优化到安全性和灾难恢复等各方面的数据库管理问题。他与人合著了 PL/SQL for DBAs (O'Reilly Media, 2005),并曾在 2003 年荣获 Oracle Magazine 的 DBA 称号,现在为 Oracle ACE。