Unix/Linux 系统自动化管理 CPU 管理篇(5)
- UID
- 1066743
|
Unix/Linux 系统自动化管理 CPU 管理篇(5)
ps 命令的输出结果表示系统中共有八个 nfs 服务进程,是根用户在一天以前启动的。当前这些进程没有使用 CPU 时间或内存。并且分别处于不同的状态。ps 命令可以接受的状态种类共有七种,仅介绍清单 15 中的两个作为示例
- D 无法中断的休眠状态(通常 IO 的进程)
- S 处于休眠状态
可以看到有六个 nfs 服务进程处于无法中断的休眠状态,这表示 NFS 服务出现了问题。用户可以通过检查物理存储可用性,查看 /var/log/messages 文件或 sysrq-T 系统 trace 等手段来进一步定位和排查错误。
获得各处理器利用率和耗用处理器时间最多的进程的代码示例本段的最后给出一段例子代码,可以获得一段时间内的 CPU 利用率,并且找出系统中占用 CPU 较多的进程,已在 Redhat 企业服务器和 Suse 企业服务器上测试通过。代码首先选取两个相隔一分钟的两个时间段,分别读取文件 /proc/stat 的内容,获得 CPU 在两个时刻的进程占用时间等数值来计算 CPU 利用率。并且读取文件 /proc/loadavg 获得处理器上的集成负载。在负载较高的情况下,调用命令 ps 找出消耗 CPU 最多的几个进程,及其所在的处理器(processor)。
清单 15. 获得各处理器的利用率和耗用处理器时间最多的进程代码示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
| # 两次读取 /proc/stat 文件的内容
my $file = '/proc/stat';
open FILE, "<$file" or die "Failed to open file $file.\n";
my @fir_contents = <FILE>;
close FILE;
sleep 60;
open FILE, "<$file" or die "Failed to open file $file.\n";
my @sec_contents = <FILE>;
close FILE;
# 把 /proc/stat 文件的内容存入一个散列
my (%cpuinfo);
my $cpu_num = 0;
my $line_num = 0;
foreach my $line (@fir_contents, @sec_contents){
$line_num ++;
if ($line =~ m/^cpu/) {
# 判断当前数据来自第一次读取还是第二次读取
my $info_time;
if ($line_num <= scalar(@fir_contents)) {
$info_time = "first";
}else {
$info_time = "second";
}
# 向散列写入数据
chomp $line;
my ($cpu, $user, $nice, $sys, $idle, $io, $irq, $softirq, $steal, $guest) =
split /\s+/, $line;
$cpuinfo{$info_time}{$cpu}{'user'} = $user;
$cpuinfo{$info_time}{$cpu}{'nice'} = $nice;
$cpuinfo{$info_time}{$cpu}{'sys'} = $sys;
$cpuinfo{$info_time}{$cpu}{'idle'} = $idle;
$cpuinfo{$info_time}{$cpu}{'io'} = $io;
$cpuinfo{$info_time}{$cpu}{'irq'} = $irq;
$cpuinfo{$info_time}{$cpu}{'softirq'} = $softirq;
$cpuinfo{$info_time}{$cpu}{'$steal'} = $steal;
$cpuinfo{$info_time}{$cpu}{'guest'} = $guest;
$cpu_num ++;
}
}
# 读取散列中的数据以计算 CPU 利用率
my (%cpu_data, %cpu_usage);
foreach my $info_time (keys %cpuinfo)
{
foreach my $cpu (keys %{$cpuinfo{$info_time}}) {
$cpu_data{$cpu}{$info_time}{'total'} = 0;
$cpu_data{$cpu}{$info_time}{'idle'} = $cpuinfo{$info_time}{$cpu}{'idle'};
foreach my $key (keys %{$cpuinfo{$info_time}{$cpu}}) {
$cpu_data{$cpu}{$info_time}{'total'} += $cpuinfo{$info_time}{$cpu}{$key};
}
}
}
my $check_proc;
foreach my $cpu (keys %cpu_data){
my $idle_interval = $cpu_data{$cpu}{'second'}{'idle'} -
$cpu_data{$cpu}{'fisrt'}{'idle'};
my $total_interval = $cpu_data{$cpu}{'second'}{'total'} -
$cpu_data{$cpu}{'fisrt'}{'total'};
$cpu_usage{$cpu} = (1 - $idle_interval/$total_interval);
if ($cpu_usage{$cpu} > 0.5) {$check_proc = 1;}
}
# 从 /proc/loadavg 读取处理器上的进程负载
$file = '/proc/loadavg';
open FILE, "<$file" or die "Failed to open file $file.\n";
my @contents = <FILE>;
close FILE;
my ($load1, $load5, $load15, $proc_num, $pid);
foreach my $line (@contents) {($load1, $load5, $load15, $proc_num, $pid) = \n
split /\s+/, $line;}
if ($load1 > 5) {$check_proc = 1;}
# 如果处理器空闲,退出
if (!$check_proc){
print "CPU load on this machine is normal.\n";
exit 0;
}
# 如果处理器繁忙,找出占用 CPU 时间的进程
my @output = `ps -e -o pcpu,pid,user,sgi_p,cmd |grep -v PID| sort -k 1| tail -10`;
foreach my $line (@output){
$line =~ s/^\s+//g;
my ($cpu, $pid, $user, $proc, $cmd) = split /\s+/, $line;
if ($cpu < 5) {next;}
# 输出进程号和进程占用的 CPU 百分比
print "Process $pid of user $user takes $cpu% CPU time on processor $proc.\n";
}
exit 0;
|
在得到需要关注的进程以后,用户可以进一步查看进程的应用类型和状态。详情可以参考本系列文章之进程管理篇。 |
|
|
|
|
|