ps
ps参数
[root@www ~]# ps aux <==观察系统所有的程序数据 [root@www ~]# ps -lA <==也是能够观察所有系统的数据 [root@www ~]# ps axjf <==连同部分程序树状态 选项与参数: -A :所有的 process 均显示出来,与 -e 具有同样的效用; -a :不与 terminal 有关的所有 process ; -u :有效使用者 (effective user) 相关的 process ; x :通常与 a 这个参数一起使用,可列出较完整资讯。 输出格式规划: l :较长、较详细的将该 PID 的的资讯列出; j :工作的格式 (jobs format) -f :做一个更为完整的输出。
鸟哥个人认为 ps 这个命令的 man page 不是很好查阅,因为很多不同的 Unix 都使用这个 ps 来查阅程序状态, 为了要符合不同版本的需求,所以这个 man page 写的非常的庞大!因此,通常鸟哥都会建议你,直接背两个比较不同的选项, 一个是只能查阅自己 bash 程序的『 ps -l 』一个则是可以查阅所有系统运行的程序『 ps aux 』!注意,你没看错,是『 ps aux 』没有那个减号 (-) !先来看看关於自己 bash 程序状态的观察:
仅观察自己的 bash 相关程序: ps -l
范例一:将目前属於您自己这次登陆的 PID 与相关资讯列示出来(只与自己的 bash 有关) [root@www ~]# ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 13639 13637 0 75 0 - 1287 wait pts/1 00:00:00 bash 4 R 0 13700 13639 0 77 0 - 1101 - pts/1 00:00:00 ps
系统整体的程序运行是非常多的,但如果使用 ps -l 则仅列出与你的操作环境 (bash) 有关的程序而已, 亦即最上一级的父程序会是你自己的 bash 而没有延伸到 init 这支程序去!那么 ps -l 秀出来的数据有哪些呢? 我们就来观察看看:
- F:代表这个程序旗标 (process flags),说明这个程序的总结权限,常见号码有:
- 若为 4 表示此程序的权限为 root ;
- 若为 1 则表示此子程序仅进行复制(fork)而没有实际运行(exec)。
- S:代表这个程序的状态 (STAT),主要的状态有:
- R (Running):该程序正在运行中;
- S (Sleep):该程序目前正在睡眠状态(idle),但可以被唤醒(signal)。
- D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>列印)
- T :停止状态(stop),可能是在工作控制(背景暂停)或除错 (traced) 状态;
- Z (Zombie):僵尸状态,程序已经终止但却无法被移除至内存外。
- UID/PID/PPID:代表『此程序被该 UID 所拥有/程序的 PID 号码/此程序的父程序 PID 号码』
- C:代表 CPU 使用率,单位为百分比;
- PRI/NI:Priority/Nice 的缩写,代表此程序被 CPU 所运行的优先顺序,数值越小代表该程序越快被 CPU 运行。详细的 PRI 与 NI 将在下一小节说明。
- ADDR/SZ/WCHAN:都与内存有关,ADDR 是 kernel function,指出该程序在内存的哪个部分,如果是个 running 的程序,一般就会显示『 - 』 / SZ 代表此程序用掉多少内存 / WCHAN 表示目前程序是否运行中,同样的, 若为 - 表示正在运行中。
- TTY:登陆者的终端机位置,若为远程登陆则使用动态终端介面 (pts/n);
- TIME:使用掉的 CPU 时间,注意,是此程序实际花费 CPU 运行的时间,而不是系统时间;
- CMD:就是 command 的缩写,造成此程序的触发程序之命令为何。
所以你看到的 ps -l 输出信息中,他说明的是:『bash 的程序属於 UID 为 0 的使用者,状态为睡眠 (sleep), 之所以为睡眠因为他触发了 ps (状态为 run) 之故。此程序的 PID 为 13639,优先运行顺序为 75 , 下达 bash 所取得的终端介面为 pts/1 ,运行状态为等待 (wait) 。』这样已经够清楚了吧? 您自己尝试解析一下那么 ps 那一行代表的意义为何呢?
观察系统所有程序: ps aux
范例二:列出目前所有的正在内存当中的程序: [root@www ~]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2064 616 ? Ss Mar11 0:01 init [5] root 2 0.0 0.0 0 0 ? S< Mar11 0:00 [migration/0] root 3 0.0 0.0 0 0 ? SN Mar11 0:00 [ksoftirqd/0] .....(中间省略)..... root 13639 0.0 0.2 5148 1508 pts/1 Ss 11:44 0:00 -bash root 14232 0.0 0.1 4452 876 pts/1 R+ 15:52 0:00 ps aux root 18593 0.0 0.0 2240 476 ? Ss Mar14 0:00 /usr/sbin/atd
你会发现 ps -l 与 ps aux 显示的项目并不相同!在 ps aux 显示的项目中,各栏位的意义为:
- USER:该 process 属於那个使用者帐号的?
- PID :该 process 的程序识别码。
- %CPU:该 process 使用掉的 CPU 资源百分比;
- %MEM:该 process 所占用的实体内存百分比;
- VSZ :该 process 使用掉的虚拟内存量 (Kbytes)
- RSS :该 process 占用的固定的内存量 (Kbytes)
- TTY :该 process 是在那个终端机上面运行,若与终端机无关则显示 ?,另外, tty1-tty6 是本机上面的登陆者程序,若为 pts/0 等等的,则表示为由网络连接进主机的程序。
- STAT:该程序目前的状态,状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)
- START:该 process 被触发启动的时间;
- TIME :该 process 实际使用 CPU 运行的时间。
- COMMAND:该程序的实际命令为何?
一般来说,ps aux 会依照 PID 的顺序来排序显示,我们还是以 13639 那个 PID 那行来说明!该行的意义为『 root 运行的 bash PID 为 13639,占用了 0.2% 的内存容量百分比,状态为休眠 (S),该程序启动的时间为 11:44 , 且取得的终端机环境为 pts/1 。』与 ps aux 看到的其实是同一个程序啦!这样可以理解吗? 让我们继续使用 ps 来观察一下其他的资讯吧!
范例三:以范例一的显示内容,显示出所有的程序: [root@www ~]# ps -lA F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 76 0 - 435 - ? 00:00:01 init 1 S 0 2 1 0 94 19 - 0 ksofti ? 00:00:00 ksoftirqd/0 1 S 0 3 1 0 70 -5 - 0 worker ? 00:00:00 events/0 ....(以下省略).... # 你会发现每个栏位与 ps -l 的输出情况相同,但显示的程序则包括系统所有的程序。 范例四:列出类似程序树的程序显示: [root@www ~]# ps axjf PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 1 1 1 ? -1 Ss 0 0:01 init [5] .....(中间省略)..... 1 4586 4586 4586 ? -1 Ss 0 0:00 /usr/sbin/sshd 4586 13637 13637 13637 ? -1 Ss 0 0:00 \_ sshd: root@pts/1 13637 13639 13639 13639 pts/1 14266 Ss 0 0:00 \_ -bash 13639 14266 14266 13639 pts/1 14266 R+ 0 0:00 \_ ps axjf .....(后面省略).....
看出来了吧?其实鸟哥在进行一些测试时,都是以网络连线进主机来测试的,所以罗,你会发现其实程序之间是有相关性的啦! 不过,其实还可以使用 pstree 来达成这个程序树喔!以上面的例子来看,鸟哥是透过 sshd 提供的网络服务取得一个程序, 该程序提供 bash 给我使用,而我透过 bash 再去运行 ps axjf !这样可以看的懂了吗?其他各栏位的意义请 man ps (虽然真的很难 man 的出来!) 罗!
范例五:找出与 cron 与 syslog 这两个服务有关的 PID 号码? [root@www ~]# ps aux | egrep '(cron|syslog)' root 4286 0.0 0.0 1720 572 ? Ss Mar11 0:00 syslogd -m 0 root 4661 0.0 0.1 5500 1192 ? Ss Mar11 0:00 crond root 14286 0.0 0.0 4116 592 pts/1 R+ 16:15 0:00 egrep (cron|syslog) # 所以号码是 4286 及 4661 这两个罗!就是这样找的啦!
除此之外,我们必须要知道的是『僵尸 (zombie) 』程序是什么? 通常,造成僵尸程序的成因是因为该程序应该已经运行完毕,或者是因故应该要终止了, 但是该程序的父程序却无法完整的将该程序结束掉,而造成那个程序一直存在内存当中。 如果你发现在某个程序的 CMD 后面还接上 <defunct> 时,就代表该程序是僵尸程序啦,例如:
apache 8683 0.0 0.9 83384 9992 ? Z 14:33 0:00 /usr/sbin/httpd <defunct>
当系统不稳定的时候就容易造成所谓的僵尸程序,可能是因为程序写的不好啦,或者是使用者的操作习惯不良等等所造成。 如果你发现系统中很多僵尸程序时,记得啊!要找出该程序的父程序,然后好好的做个追踪,好好的进行主机的环境最佳化啊! 看看有什么地方需要改善的,不要只是直接将他 kill 掉而已呢!不然的话,万一他一直产生,那可就麻烦了! @_@
事实上,通常僵尸程序都已经无法控管,而直接是交给 init 这支程序来负责了,偏偏 init 是系统第一支运行的程序, 他是所有程序的父程序!我们无法杀掉该程序的 (杀掉他,系统就死掉了!),所以罗,如果产生僵尸程序, 而系统过一阵子还没有办法透过核心非经常性的特殊处理来将该程序删除时,那你只好透过 reboot 的方式来将该程序抹去了!
pstree
[root@www ~]# pstree [-A|U] [-up] 选项与参数: -A :各程序树之间的连接以 ASCII 字节来连接; -U :各程序树之间的连接以万国码的字节来连接。在某些终端介面下可能会有错误; -p :并同时列出每个 process 的 PID; -u :并同时列出每个 process 的所属帐号名称。 范例一:列出目前系统上面所有的程序树的相关性: [root@www ~]# pstree -A init-+-acpid |-atd |-auditd-+-audispd---{audispd} <==这行与底下一行为 auditd 分出来的子程序 | `-{auditd} |-automount---4*[{automount}] <==默认情况下,相似的程序会以数字显示 ....(中间省略).... |-sshd---sshd---bash---pstree <==就是我们命令运行的那个相依性! ....(底下省略).... # 注意一下,为了节省版面,所以鸟哥已经删去很多程序了! 范例二:承上题,同时秀出 PID 与 users [root@www ~]# pstree -Aup init(1)-+-acpid(4555) |-atd(18593) |-auditd(4256)-+-audispd(4258)---{audispd}(4261) | `-{auditd}(4257) |-automount(4536)-+-{automount}(4537) <==程序相似但 PID 不同! | |-{automount}(4538) | |-{automount}(4541) | `-{automount}(4544) ....(中间省略).... |-sshd(4586)---sshd(16903)---bash(16905)---pstree(16967) ....(中间省略).... |-xfs(4692,xfs) <==因为此程序拥有者并非运行 pstree 者!所以列出帐号 ....(底下省略).... # 在括号 () 内的即是 PID 以及该程序的 owner 喔!不过,由於我是使用 # root 的身份运行此一命令,所以属於 root 的程序就不会显示出来啦!
如果要找程序之间的相关性,这个 pstree 真是好用到不行!直接输入 pstree 可以查到程序相关性,如上表所示,还会使用线段将相关性程序连结起来哩! 一般连结符号可以使用 ASCII 码即可,但有时因为语系问题会主动的以 Unicode 的符号来连结, 但因为可能终端机无法支持该编码,或许会造成乱码问题。因此可以加上 -A 选项来克服此类线段乱码问题。
由 pstree 的输出我们也可以很清楚的知道,所有的程序都是依附在 init 这支程序底下的! 仔细看一下,这支程序的 PID 是一号喔!因为他是由 Linux 核心所主动呼叫的第一支程序!所以 PID 就是一号了。 这也是我们刚刚提到僵尸程序时有提到,为啥发生僵尸程序需要重新启动? 因为 init 要重新启动,而重新启动 init 就是 reboot 罗!
如果还想要知道 PID 与所属使用者,加上 -u 及 -p 两个参数即可。我们前面不是一直提到, 如果子程序挂点或者是老是砍不掉子程序时,该如何找到父程序吗?呵呵!用这个 pstree 就对了! ^_^
进程的信号
程序之间是可以互相控制的!举例来说,你可以关闭、重新启动服务器软件,服务器软件本身是个程序, 你既然可以让她关闭或启动,当然就是可以控制该程序啦!那么程序是如何互相管理的呢?其实是透过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么!因此这个讯号就很重要啦!
要给予某个已经存在背景中的工作某些动作时,是直接给予一个讯号给该工作号码即可。那么到底有多少 signal 呢? 你可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查询到!主要的讯号代号与名称对应及内容是:
代号 | 名称 | 内容 |
1 | SIGHUP | 启动被终止的程序,可让该 PID 重新读取自己的配置档,类似重新启动 |
2 | SIGINT | 相当於用键盘输入 [ctrl]-c 来中断一个程序的进行 |
9 | SIGKILL | 代表强制中断一个程序的进行,如果该程序进行到一半, 那么尚未完成的部分可能会有『半产品』产生,类似 vim会有 .filename.swp 保留下来。 |
15 | SIGTERM | 以正常的结束程序来终止该程序。由於是正常的终止, 所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时, 输入这个 signal 也是没有用的。 |
17 | SIGSTOP | 相当於用键盘输入 [ctrl]-z 来暂停一个程序的进行 |
上面仅是常见的 signal 而已,更多的讯号资讯请自行 man 7 signal 吧!一般来说,你只要记得『1, 9, 15』这三个号码的意义即可。那么我们如何传送一个讯号给某个程序呢?就透过 kill 或 killall 吧!
kill
kill 可以帮我们将这个 signal 传送给某个工作 (%jobnumber) 或者是某个 PID (直接输入数字)。 要再次强调的是: kill 后面直接加数字与加上 %number 的情况是不同的! 这个很重要喔!因为工作控制中有 1 号工作,但是 PID 1 号则是专指『 init 』这支程序!你怎么可以将 init 关闭呢? 关闭 init ,你的系统就当掉了啊!所以记得那个 % 是专门用在工作控制的喔!
以 ps 找出 syslog 这个程序的 PID 后,再使用 kill 传送信息,使得 syslog 可以重新读取配置档。
由於需要重新读取配置档,因此 signal 是 1 号。至於找出 syslog 的 PID 可以是这样做: ps aux | grep 'syslog' | grep -v 'grep'| awk '{print $2}' 接下来则是实际使用 kill -1 PID,因此,整串命令会是这样: kill -SIGHUP $(ps aux|grep 'syslog'|grep -v 'grep'|awk '{print $2}') 如果要确认有没有重新启动 syslog ,可以参考登录档的内容,使用如下命令查阅: tail -5 /var/log/messages 如果你有看到类似『Mar 19 15:08:20 www syslogd 1.4.1: restart』之类的字样,就是表示 syslogd 在 3/19 有重新启动 (restart) 过了!
了解了这个用法以后,如果未来你想要将某个莫名其妙的登陆者的连线删除的话,就可以透过使用 pstree -p 找到相关程序, 然后再以 kill -9 将该程序删除,该条连线就会被踢掉了!这样很简单吧!
killall
由於 kill 后面必须要加上 PID (或者是 job number),所以,通常 kill 都会配合 ps, pstree 等命令,因为我们必须要找到相对应的那个程序的 ID 嘛!但是,如此一来,很麻烦~有没有可以利用『下达命令的名称』来给予讯号的?举例来说,能不能直接将 syslog 这个程序给予一个 SIGHUP 的讯号呢?可以的!用 killall 吧!
[root@www ~]# killall [-iIe] [command name] 选项与参数: -i :interactive 的意思,互动式的,若需要删除时,会出现提示字节给使用者; -e :exact 的意思,表示『后面接的 command name 要一致』,但整个完整的命令 不能超过 15 个字节。 -I :命令名称(可能含参数)忽略大小写。 范例一:给予 syslogd 这个命令启动的 PID 一个 SIGHUP 的讯号 [root@www ~]# killall -1 syslogd # 如果用 ps aux 仔细看一下,syslogd 才是完整的命令名称。但若包含整个参数, # 则 syslogd -m 0 才是完整的呢! 范例二:强制终止所有以 httpd 启动的程序 [root@www ~]# killall -9 httpd 范例三:依次询问每个 bash 程序是否需要被终止运行! [root@www ~]# killall -i -9 bash Kill bash(16905) ? (y/N) n <==这个不杀! Kill bash(17351) ? (y/N) y <==这个杀掉! # 具有互动的功能!可以询问你是否要删除 bash 这个程序。要注意,若没有 -i 的参数, # 所有的 bash 都会被这个 root 给杀掉!包括 root 自己的 bash 喔! ^_^
总之,要删除某个程序,我们可以使用 PID 或者是启动该程序的命令名称, 而如果要删除某个服务呢?呵呵!最简单的方法就是利用 killall , 因为他可以将系统当中所有以某个命令名称启动的程序全部删除。 举例来说,上面的范例二当中,系统内所有以 httpd 启动的程序,就会通通的被删除啦!
pidof
[root@www ~]# pidof [-sx] program_name 选项与参数: -s :仅列出一个 PID 而不列出所有的 PID -x :同时列出该 program name 可能的 PPID 那个程序的 PID 范例一:列出目前系统上面 init 以及 syslogd 这两个程序的 PID [root@www ~]# pidof init syslogd 1 4286 # 理论上,应该会有两个 PID 才对。上面的显示也是出现了两个 PID 喔。 # 分别是 init 及 syslogd 这两支程序的 PID 啦。
很简单的用法吧,透过这个 pidof 命令,并且配合 ps aux 与正规表示法,就可以很轻易的找到您所想要的程序内容了呢。
转自 http://vbird.dic.ksu.edu.tw/linux_basic/0440processcontrol_3.php