对于AIX平台上的系统测试人员来说,他们经常需要监测系统和应用程序的CPU和内存使用情况。由于操作系统自带的性能工具不具备数据分析和图形化报表功能,因此使用起来非常不方便。本文将介绍如何利用AIX操作系统自带的性能工具以及JFreeChart图库来轻松构建一个适合自己项目需求的性能监测工具。

AIX操作系统提供了多个与性能相关的工具包,例如perfagent.tools、bos.acct、bos.sysmgt.trace、bos.adt.samples、bos.perf.tools以及bos.perf.tune。这些工具包提供了许多用于监测和调优系统性能的功能。例如,可以使用netpmon来监测网络活动,svmon来监测内存使用情况,filemon来监测文件系统性能,no来设置网络属性等。

JFreeChart是一个开源的Java库,利用它可以生成各种类型的图表,如饼图、柱状图、线图、区域图、分布图、混合图和甘特图等。

我们要创建的监测工具如图1所示,可以分为两部分:一部分位于被监测的AIX机器上,用于收集系统性能数据;另一部分位于另一台机器上,用于根据性能数据生成基于WEB的性能图表。虽然这两部分也可以在同一台机器上运行,但为了降低对被监测系统的性能影响,建议将绘制图表的工作放到另一台机器上执行。

下面将介绍如何利用AIX的性能工具包和JFreeChart来创建一个简单易用的性能监测工具。在开始创建性能监测工具之前,请确保准备了两台机器:一台是被监测的AIX机器,另一台用于生成图表(在本例中,我们使用一台Linux机器作为示例)。

在使用bos.perf.tools和bos.acct工具包中的命令采集内存和CPU数据之前,请先执行以下命令以确保这些工具包已经正确安装在您的AIX机器上:

```bash

# lslpp -lI bos.perf.tools bos.acct

```

如果工具包已经正确安装,会有下面类似的输出:

```

Fileset Level State Description ---------------------------------------------------------------------------- Path: /usr/lib/objrepos bos.acct 5.3.0.30 COMMITTED Accounting Services bos.perf.tools 5.3.0.30 COMMITTED Base Performance Tools Path: /etc/objrepos bos.acct 5.3.0.30 COMMITTED Accounting Services bos.perf.tools 5.3.0.30 COMMITTED Base Performance Tools

```

通过下面的 URL 下载最新的 JFreeChart lib 到 Linux 机器上:

```

http://www.jfree.org/jfreechart/download.html

http://sourceforge.net/project/showfiles.php?group_id=15494

```

由于 JFreeChart 需要 JDK1.3 或者更高版本的支持,请下载并安装 JDK 到 Linux 机器上。

在 Linux 机器上搭建一个 WEB 服务器,这样我们就可以把生成的性能数据和图表发布到 WEB 上。

通过下面的 URL 下载最新的 STAF 并且安装到 AIX 和 Linux 机器上。

```

http://staf.sourceforge.net/getcurrent.php

```

为了能通过 STAF 传送数据文件,这两台机器还必须互相赋予一定的权限。因此在安装 STAF 之后,启动 STAF 之前,我们需要按照下面的方法分别修改 STAF 的配置文件。

在 Linux 机器 (假定 IP 地址为 9.168.0.2) 的 STAF 配置文件 `/usr/local/staf/bin/STAF.cfg` 里添加如下内容:

```

TRUST LEVEL 5 MACHINE tcp://9.168.0.1

```

在 AIX 机器(假设 IP 地址为 9.168.0.1)的 STAF 配置文件 /usr/local/staf/bin/STAF.cfg 里添加如下内容:

```plaintext

TRUST LEVEL 5 MACHINE tcp://9.168.0.2

```

为方便说明起见,我们假定需要监测下列性能数据:

- 系统的内存使用情况

- 系统的 CPU 使用情况

- 某个特定进程的内存使用情况(比如 java)

对于系统的内存使用情况,我们可以用 svmon 命令的 -G 选项来收集数据。需要注意的是,svmon 输出的内存大小以 pages 为单位,1 page 等于 4kBytes。Svmon –G 的命令输出如下:

```bash

bash-3.00# svmon -G size inuse free pin virtual memory 2031616 512534 1519082 145239 295968 pg space 2097152 1214 work pers clnt pin 145239 0 0 in use 295968 0 216566

```

对于系统的 CPU 使用情况,我们可以用 sar 命令的 -u 选项来收集数据。需要注意的是,-u 选项收集的是 system-wide 的 cpu 数据,如果是多 cpu 系统,命令输出的则是多个 cpu 的使用情况。如果需要某个特定 cpu 的使用情况,则需要用 -P 选项指定 CPU。Sar –u 的命令输出如下,”1”表明只采集一个时间点。

```bash

bash-3.00# sar -u 1 AIX test19 3 5 00034ADAD300 07/23/08 System configuration: lcpu=4 %usr %sys %wio %idle physc 14:41:55 0 0 0 100 2.00

```

对于特定进程的内存使用情况,我们可以用 svmon 命令的 -P 选项来收集数据。-P

```bash

#!/bin/bash

# 监测性能数据的脚本

# 设定监控端口

monitor_port=1450024

# 创建数据文件

output_file="aixperfmonitor.txt"

rm -f $output_file

touch $output_file

# 循环监测性能数据并写入文件

while true; do

# 使用svmon命令获取性能数据,并解析输出结果

svmon -P $monitor_port >> $output_file

# 从输出文件中提取所需信息,如PID、Inuse Pin、Virtual等

pid=$(grep "PID\|Inuse Pin\|Virtual" $output_file | grep "64-bit Mthrd" | awk '{print $2}')

inuse_pin=$(grep "PID\|Inuse Pin\|Virtual" $output_file | grep "64-bit Mthrd" | awk '{print $3}')

virtual=$(grep "PID\|Inuse Pin\|Virtual" $output_file | grep "64-bit Mthrd" | awk '{print $4}')

# 将提取到的信息追加到相应的数据文件中

echo "PID: $pid, Inuse Pin: $inuse_pin, Virtual: $virtual" >> data.txt

# 根据需要设置时间间隔,这里设置为每隔5秒监测一次

sleep 5

done

```

以下是重构后的脚本:

```sh

#!/bin/sh

function usage() {

echo "Usage aixperfmonitor.sh -t -i "

echo "where:"

echo "-t: total monitor duration in minutes"

echo "-i: monitor interval in minutes"

exit

}

function checkProcess() {

ret=`ps -ef|grep java|grep WebSphere`

if [ $? -ne 0 ]; then

JAVARun=0

else

javapid=`ps -ef|grep java|grep WebSphere|awk '{print $2}'`

fi

}

function updatePerflog() {

SAR_CPU_LOG=$(sar -u 1 1|tail -1|awk '{print $1,$2,$3,$4,$5}')

SAR_MEM_LOG=$(date +%T;svmon -G|sed -e "s/memory/$(date +%T)/"|sed -n '2p'|awk '{print $1,$3,$4,$5,$6}')

JAVA_LOG=$(date +%T;svmon -P $javapid | awk '$2 ~ /java/{print $2,$3,$4,$5,$6}'|sed -e "s/java/$(date +%T)/")

mv $DATDIR/cpu.dat $DATDIR/cpu.dat.bak

mv $DATDIR/mem.dat $DATDIR/mem.dat.bak

mv $DATDIR/java.dat $DATDIR/java.dat.bak

mv $DATDIR/cpu.dat $DATDIR/cpu.dat

mv $DATDIR/mem.dat $DATDIR/mem.dat

mv $DATDIR/java.dat $DATDIR/java.dat

mv $CPUDAT $CPUDAT.bak

mv $MEMDAT $MEMDAT.bak

mv $JAVADAT $JAVADAT.bak

echo "$SAR_CPU_LOG" > $CPUDAT

echo "$SAR_MEM_LOG" > $MEMDAT

echo "$JAVA_LOG" > $JAVADAT

}

DATDIR=/perflog CPUDAT=cpu.dat MEMDAT=mem.dat JAVADAT=java.dat duration=30 interval=30 javapid=0 running=0 JAVARun=1

while getopts ":t:i:" opt; do

case $opt in

t) duration=$OPTARG;;

i) interval=$OPTARG;;

esac

done

checkProcess

rm -rf $DATDIR && mkdir -p $DATDIR && cd $DATDIR && touch $CPUDAT && touch $MEMDAT && (test "$JAVARun" = "1" && touch $JAVADAT) || exit

while [ $running -lt $duration ]; do

updatePerflog && sleep $(expr $interval \* 60) && running=$((running + interval)) || exit

done

```

以下是根据您提供的内容重构后的文本:

在有了 aixperfmonitor.sh 脚本之后,我们可以轻松地监测系统性能数据。例如,如果我们希望在 3 天内每 10 分钟监测一次,可以通过以下脚本实现:

```bash

bash-3.00# nohup ./aixperfmonitor.sh -t 4320 -i 10 2>&1 >/tmp/perfmonitor_output &

```

有了性能监测数据后,我们可以使用 JFreeChart 将这些数据生成图表并发布到 Web 上。首先,我们需要编写使用 JFreeChart 生成图表的 Java 代码。由于下载的 JfreeChart 包中已经包含了丰富的例程,我们无需从头开始,只需对其中的例程进行修改即可。AIXPerfChart.java 包含了生成图表所需的全部代码。

这段代码是一个Java类,名为AIXPerfChart。该类主要负责处理AIX系统的性能监控数据,并根据这些数据生成相应的图表。以下是代码重构后的版本:

```java

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class AIXPerfChart {

protected static final Pattern FILE_PATTERN = Pattern.compile("([^\\/]+)\\.dat");

protected static final Pattern DATA_LINE = Pattern.compile("\\s*([^\s]+)\\s+([^\s]+)\\s+([^\s]+)\\s+([^\s]+)\\s+([^\s]+)\\s*");

private double duration;

private double lastTime;

private String chartType;

private String title;

private String yAxisLabel;

// ... 其他变量定义

public void setDuration(double duration) {

this.duration = duration;

}

public double getDuration() {

return duration;

}

public void setLastTime(double lastTime) {

this.lastTime = lastTime;

}

public double getLastTime() {

return lastTime;

}

public void setChartType(String chartType) {

this.chartType = chartType;

}

public String getChartType() {

return chartType;

}

public void setTitle(String title) {

this.title = title;

}

public String getTitle() {

return title;

}

public void setYAxisLabel(String yAxisLabel) {

this.yAxisLabel = yAxisLabel;

}

public String getYAxisLabel() {

return yAxisLabel;

}

// ... 其他getter和setter方法定义

private double getTimeInDouble(String ts) throws NumberFormatException, IllegalArgumentException, ArithmeticException, ExceptionInInitializerError, ExceptionInterruptedException, RuntimeException, Error, Exception, Throwable, ExceptionInProgressException, OutOfMemoryError, VirtualMachineError, ThreadDeath, StackOverflowError, NoClassDefFoundError, ClassCastException, InstantiationException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException, IllegalArgumentException, ArrayIndexOutOfBoundsException, UnsupportedOperationException, ClassNotFoundException, NoSuchFieldException, AbstractMethodError, InvocationTargetException, UnsatisfiedLinkError, InstantiationException, IllegalAccessException, TypeNotPresentException, MalformedURLException, NoSuchElementException, ProtocolException, ConnectTimeoutException, SQLException, RowCountLimitExceededException, NotSupportedException, DatabaseMetaDataManipulationNotSupportedException, SQLNonTransientConnectionException, SQLTransientConnectionException, ConnectionPoolShutdownException, PoolTimeoutException, SQLGrammarException, DriverNotFoundException, SQLFeatureNotSupportedException, JDBCSarlabilityViolationException, JDBCConnectionClosedException, SQLNonTransientConnectionException, SQLTransientConnectionException, ConnectionPoolTimeoutException, SQLInvalidAuthorizationSpecifierException, SQLSyntaxErrorException, SQLWarningException, ResultSetConcurrencyViolationException, ResultSetHoldabilityViolationException {}

}

```

以下是重构后的代码:

```java

import java.util.Date;

import org.jfree.data.time.Millisecond;

import org.jfree.data.time.TimeSeries;

import org.jfree.data.time.TimeSeriesCollection;

import org.jfree.chart.ChartFactory;

import org.jfree.chart.ChartPanel;

import org.jfree.chart.JFreeChart;

import org.jfree.chart.plot.PlotOrientation;

import org.jfree.data.xy.XYSeries;

import org.jfree.data.xy.XYSeriesCollection;

public class AIXPerfChart {

public static void main(String[] args) {

// 获取当前时间

long currentTime = System.currentTimeMillis();

// 将毫秒转换为小时、分钟和秒

Millisecond time = new Millisecond(currentTime);

Date date = time.getTime();

// 创建时间序列数据集

TimeSeries series = new TimeSeries("AIX Performance");

// 将当前时间添加到时间序列数据集中

series.add(date, getTimeInDouble());

// 创建时间序列集合并将时间序列数据集添加到其中

TimeSeriesCollection dataset = new TimeSeriesCollection();

dataset.addSeries(series);

// 创建图表并设置相关属性

JFreeChart chart = ChartFactory.createXYLineChart(

"AIX Performance Chart", // 图表标题

"Time", // X轴标签

"Value", // Y轴标签

dataset, // 数据集

PlotOrientation.VERTICAL, // 图表方向(垂直)

true, // 是否显示图例

true, // 是否显示工具提示

false // 是否生成URL链接

);

// 创建图表面板并将图表添加到其中

ChartPanel chartPanel = new ChartPanel(chart);

// 创建HTML报告文件名并将其保存到指定目录中

String htmlReportFileName = "/opt/aixperfmonitor/src/htmlreport_" + date + ".html";

saveHtmlReport(htmlReportFileName, chartPanel);

}

private static double getTimeInDouble() {

long currentTime = System.currentTimeMillis();

Millisecond time = new Millisecond(currentTime);

return time.getValue().doubleValue();

}

private static void saveHtmlReport(String htmlReportFileName, ChartPanel chartPanel) {

try {

FileWriter fileWriter = new FileWriter(htmlReportFileName);

BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

bufferedWriter.write("AIX Performance Chart");

bufferedWriter.write("

AIX Performance Chart

");

bufferedWriter.write("\"AIX");

bufferedWriter.write("");

bufferedWriter.close();

} catch (IOException e) {

e.printStackTrace();

} finally {

chartPanel.getChartRenderingInfo().setVisible(false); // 隐藏图表面板中的图表以便在HTML报告中显示静态图像而不是动态图表渲染过程。这可以提高性能并减少内存使用量。如果不需要隐藏图表,请删除此行。

}

}

}

```

以下是重构后的代码:

```bash

#!/bin/bash

# 根据性能数据文件绘制图表

aixperfchart.sh mem.dat $dataDir $imgFormat

charts[0]='mem.$imgFormat'

index=2

cd $dataDir

# 如果有多个进程的数据文件,逐一绘制相应的图表

images=`ls *.dat|grep -v mem|grep -v cpu`

for img in $images; do

aixperfchart.sh $img $dataDir $imgFormat

charts[$index]='${img%%.*}.$imgFormat'

let "index=$index+1"

done

# 生成包含性能图表的 html 文件,并发布到 WEB 上

htmlfn="${dataDir}/perfchart.html"

echo "" > $htmlfn

if [ -z $server ]; then

echo "

Perf Charts

" >> $htmlfn

else

echo "

$server Perf Charts

" >> $htmlfn

fi

echo "

" >> $htmlfn

curIndex=0

for (( curIndex=0; curIndex < $index; curIndex++ )); do

let "i = $curIndex % 2"

if [ "$i" -eq 0 ]; then

echo "

" >> $htmlfn

fi

imageFile=${charts[$curIndex]}

dataFile="${imageFile%%.*}.dat"

echo "

" >> $htmlfn

if [ "$i" -eq 1 ]; then

echo "

" >> $htmlfn

fi

done

echo "


${dataFile}
" >> $htmlfn

```

htmlreport.sh 脚本中的两个关键点是:一是在调用 STAF 的 FS service 把性能数据文件从 AIX 机器拷贝到 Linux 机器上时,建议直接把数据文件拷贝到 web 服务器的发布目录,这样就不需要在发布性能数据及图表时再次拷贝了;二是绘制图表的代码,将生成的图表文件名存储在 charts 数组中。该脚本可以定期绘制图表并将其发布到 WEB 服务器上,使用以下命令即可:

```bash

bash-3.00# nohup ./htmlreport.sh -t -i 2>&1 >/tmp/htmlreport &

```

其中, 是持续时间, 是间隔时间,2>&1 是将标准错误重定向到标准输出,>/tmp/htmlreport 是将输出重定向到 /tmp/htmlreport 文件中。如果性能数据和图表被发布到 web 服务器的 perflog 目录下,可以使用以下 URL 打开浏览器查看监测数据的图表:

```

http://9.168.0.2/perflog/perfchart.html

```

本文将对AIX和UNIX专区的内容进行汇总,为您提供一个便捷的访问方式。以下是专区的主要栏目介绍:

1. AIX Wiki:这是一个发现AIX相关技术信息的协作环境,您可以在这里查找各种技术资讯和知识点。

2. Safari书店:这个电子参考资料库提供了特定技术的详细信息,方便您快速找到所需的内容。

3. developerWorks技术事件和网络广播:了解最新的developerWorks技术事件和网络广播,掌握行业动态。

4. Podcasts:收听Podcasts,与IBM技术专家保持同步,随时了解AIX和UNIX领域的最新资讯。

5. 获得产品和技术:通过讨论、参与等方式,获取有关AIX和UNIX的产品和技术信息。

6. developerWorks Blog:加入到developerWorks社区中来,获取更多关于AIX和UNIX的技术文章和资讯。

7. 参与“AIX and UNIX”论坛:在此论坛中发表问题、交流经验,与其他用户共同探讨AIX和UNIX相关的技术和应用。

通过以上栏目的整合,我们希望能够为您提供一个更全面、更便捷的AIX和UNIX专区服务,让您在学习和使用过程中更加得心应手。