LTP是由 Linux Test Project 所开发的一套系统测试套件。它基于系统资源的利用率统计开发了一个测试的组合,为系统提供足够的压力。通过压力测试来判断系统的稳定性和可靠性。压力测试是一种破坏性的测试,即系统在非正常的、超负荷的条件下的运行情况 。用来评估在超越最大负载的情况下系统将如何运行,是系统在正常的情况下对某种负载强度的承受能力的考验。

        服务器产品一般进行72h压力测试,桌面产品一般进行24小时压力测试,常用测试命令:

# ./ltpstress.sh -n -t 72

        其中 -n参数表示不进行网络相关测试,-t参数指定测试时长(小时为单位,最小为 1,默认24),该脚本最终调用genload程序来运行,genload根据传入的进程个数fork子进程,每个子进程的读写的内存为1GB,启动多少个进程由测试时的内存状态(含SWAP分区情况)决定。

         该脚本测试与系统下的SWAP分区息息相关:

         1)当系统下存在SWAP分区时,测试所用的内存大小为:全部物理内存 + 1/2 SWAP分区大小

        2)当系统下不存在SWAP分区时(或使用swapoff -a命令关闭swap分区时),测试所用的内存大小为:通过free -m命令获取的当前空闲内存(多次测试间或有不同)

        这个测试用例的本质是调用genload程序,以1G为单位来不断申请内存,然后执行写内存及释放的过程,ltpstrees.sh中只调用一次genload, genload根据 PROC_NUM个数来决定fork多少个genload子进程。

        genload --vm $PROC_NUM --vm-bytes 1073741824 >/dev/null 2>&1 &

       genload每次申请内存均以1G为单位进行,不足1G的会以剩余内存大小单独生成一个进程,例如:如果有31.5G可用内存,那么就创建32个genload进程。脚本执行后,可通过以下命令查看genload的状态和数量:

# ps -ef | grep genload

        以下是ltpstress.sh脚本分析:

#!/bin/sh

#    Copyright (c) International Business Machines  Corp., 2003
#
#    This program is free software;  you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY;  without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
#    the GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program;  if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
#   FILE        : ltpstress.sh
#   DESCRIPTION : A script that will stress your system using the LTP testsuite.
#   REQUIREMENTS:
#                 1) The 'rsh' daemon must be running and NFS (versions 2 &3) must be
#                    configured into the kernel and installed for networking tests.
#		  2) The 'sar' application must be installed to use the "-S" option
#   HISTORY     :
#       02/11/2003 Robbie Williamson (robbiew@austin.ibm.com)
#               written
#	11/20/2008 Aime Le Rouzic (aime.lerouzic@bull.net)
#		adapt script to work with portmap and rpcbind
##############################################################

export LTPROOT=${PWD}      #  ltp/testscripts
echo $LTPROOT | grep testscripts > /dev/null 2>&1    # 不在ltp/testscripts目录下时返回1,在时返回0
if [ $? -eq 0 ]; then    # 最后运行的命令返回的结束代码(0表示正常,其他表示异常)
 cd ..
 export LTPROOT=${PWD}    # $LTPROOT=ltp/
fi
export TMPBASE="/tmp"
export PATH=$LTPROOT/testcases/bin:$PATH
memsize=0
hours=24
PROC_NUM=0
leftover_memsize=0
duration=86400
datafile="/tmp/ltpstress.data"
iofile="/tmp/ltpstress.iodata"
logfile="/tmp/ltpstress.log"
interval=10
Sar=0
Top=0
Iostat=0
LOGGING=0
PRETTY_PRT=""
QUIET_MODE=""
NO_NETWORK=0

usage()
{

	cat <<-END >&2
    usage: ${0##*/} [ -d datafile ] [ -i # (in seconds) ] [ -I iofile ] [ -l logfile ] [ -m # (in Mb) ]
    [ -n ] [ -p ] [ -q ] [ -t duration ] [ -x TMPDIR ] [-b DEVICE] [-B LTP_DEV_FS_TYPE] [ [-S]|[-T] ]

    -d datafile     Data file for 'sar' or 'top' to log to. Default is "/tmp/ltpstress.data".
    -i # (in sec)   Interval that 'sar' or 'top' should take snapshots. Default is 10 seconds.
    -I iofile       Log results of 'iostat' to a file every interval. Default is "/tmp/ltpstress.iodata".
    -l logfile      Log results of test in a logfile. Default is "/tmp/ltpstress.log"
    -m # (in Mb)    Specify the _minimum_ memory load of # megabytes in background. Default is all the RAM + 1/2 swap.
    -n              Disable networking stress.
    -p              Human readable format logfiles.
    -q              Print less verbose output to the output files.
    -S              Use 'sar' to measure data.
    -T              Use LTP's modified 'top' tool to measure data.
    -t duration     Execute the testsuite for given duration in hours. Default is 24.
    -x TMPDIR       Directory where temporary files will be created.
    -b DEVICE       Some tests require an unmounted block device
                    to run correctly. If DEVICE is not set, a loop device is
                    created and used automatically.
    -B LTP_DEV_FS_TYPE The file system of DEVICE.

	example: ${0##*/} -d /tmp/sardata -l /tmp/ltplog.$$ -m 128 -t 24 -S
	END
exit
}

check_memsize()    #函数作用:检查测试所用内存大小,计算得出PROC_NUM大小
{
  while [ $memsize -gt 1048576 ]   #if greater than 1GB   #测试所用内存大于1GB时,$memsize单位为KB,1048576=1024*1024
  do
    PROC_NUM=$(( PROC_NUM + 1 ))    #PROC_NUM初始值为0
    memsize=$(( $memsize - 1048576 ))  #以1GB为单位递减,计算PROC_NUM数量
  done
  leftover_memsize=$memsize   #leftover_memsize初始值为0,使用leftover_memsize记录小于1GB的内存部分,后续用来单独创建一个线程
}

while getopts d:hi:I:l:STt:m:npqx:b:B:\? arg    #遍历参数,初始化状态
do  case $arg in

	d)	datafile="$OPTARG";;

        h)      echo "Help info:"
		usage;;

	i)	interval=$OPTARG;;

	I)	Iostat=1
		iofile=$OPTARG;;

    l)  logfile=$OPTARG
		LOGGING=1;;

    m)	memsize=$(($OPTARG * 1024))    # -m参数指定的测试内存大小,单位为MB
		check_memsize;;

	n)	NO_NETWORK=1;;

	p)	PRETTY_PRT=" -p ";;

	q)	QUIET_MODE=" -q ";;

    S)  if [ $Top -eq 0 ]; then
            Sar=1
        else
            echo "Cannot specify -S and -T...exiting"
            exit
        fi;;

	T)	if [ $Sar -eq 0 ]; then
                  $LTPROOT/testcases/bin/top -h 2>&1 | grep "\-f filename" >/dev/null
		  if [ $? -eq 0 ]; then
                    Top=1
          else
		    echo "ERROR: Please build and install the version of top in the /tools dir"
		    exit
 		  fi
        else
          echo "Cannot specify -S and -T...exiting"
          exit
        fi;;

    t)  hours=$OPTARG
		duration=$(($hours * 60 * 60));;   #duration单位为秒

	x)	export TMPBASE=$(readlink -f ${OPTARG});;

	b)	export LTP_DEV=${OPTARG};;

	B)	export LTP_DEV_FS_TYPE=${OPTARG};;

        \?)     echo "Help info:"
		usage;;
        esac
done

export TMP="${TMPBASE}/ltpstress-$$"    # $$ shell本身的pid    #TMP=/tmp/ltpstress-pid
export TMPDIR=${TMP}
mkdir -p ${TMP}    #创建临时目录,修改权限并进入目录

# to write as user nobody into tst_tmpdir()
chmod 777 $TMP || \
{
	echo "unable to chmod 777 $TMP ... aborting"
	exit 1
}

cd $TMP || \
{
	echo "could not cd ${TMP} ... exiting"
	exit 1
}

if [ $NO_NETWORK -eq 0 ];then    #测试时未加-n参数,进行网络相关测试,测试时未使用
  # Networking setup
  echo `hostname` >> /root/.rhosts
  chmod 644 /root/.rhosts

  netstat -an | grep 514
  if [ $? -eq 1 ];then
    echo "Error: 'rsh' daemon not active on this machine."
    exit 1
  fi

  ps -ef | grep portmap | grep -v grep
  if [ $? -eq 1 ];then
    ps -ef | grep rpcbind | grep -v grep
    if [ $? -eq 1 ];then
      echo "Portmap and rpcbind not running"
      echo "Let's start portmap"
      /sbin/portmap &
      sleep 1
      ps -ef | grep portmap | grep -v grep
      if [ $? -eq 1 ];then
        echo "Could not start portmap, Let's start rpcbind"
        /sbin/rpcbind &
        sleep 1
        ps -ef | grep rpcbind | grep -v grep
        if [ $? -eq 1 ];then
          Echo "Error: Could not start rpcbind daemon."
          exit 1
        else
          echo "The RPC test suite is using rpcbind"
        fi
      else
	echo "The RPC test suite is using portmap"
      fi
    else
      echo "The RPC test suite is using rpcbind"
    fi
  else
    echo "The RPC test suite is using portmap"
  fi

  ps -e | grep nfsd
  if [ $? -eq 1 ];then
    /usr/sbin/rpc.nfsd
  fi
  sleep 1
  ps -e | grep nfsd
  if [ $? -eq 1 ];then
    echo "Error: Could not start nfs server daemon."
    exit 1
  fi

  ps -e | grep rpc.statd
  if [ $? -eq 1 ];then
    /sbin/rpc.statd
  fi
  sleep 1
  ps -e | grep rpc.statd
  if [ $? -eq 1 ];then
    echo "Error: Could not start statd daemon."
    exit 1
  fi

  ps -e | grep rpc.mountd
  if [ $? -eq 1 ];then
    /usr/sbin/rpc.mountd
  fi
  sleep 1
  ps -e | grep rpc.mountd
  if [ $? -eq 1 ];then
    echo "Error: Could not start mountd daemon."
    exit 1
  fi
  # End of network setup
fi   #结束网络相关测试

#If -m not set, use all the RAM + 1/2 swapspace
if [ $memsize -eq 0 ]; then     #$memsize初始值为0
  TOTALRAM=$(free -m | grep 内存: | awk {'print $2'})   #取出free输出的total mem数值,单位为MB
  TOTALSWAP=$(free -m | grep 交换: | awk {'print $2'})  #取出free输出的total Swap数值,单位为MB
  TESTSWAP=$(($TOTALSWAP / 2))   #测试用到的TESTSWAP空间为总SWAP大小的一半
  if [ $TESTSWAP -eq 0 ]; then   #没有SWAP空间或关闭了SWAP空间
       #if there is no swap in the system, use only the free RAM
       TESTMEM=$(free -m | grep Mem: | awk {'print $4'})  #没有SWAP参与的情况下,测试所用的TESTMEM大小为free输出的空闲空间大小(非total大小),单位为MB
  else
       TESTMEM=$(($TESTSWAP + $TOTALRAM))  #有SWAP参与的情况下,测试所用的TESTMEM大小为总内存+1/2SWAP空间大小,单位为MB
  fi
 #Convert to kilobytes
  memsize=$(($TESTMEM * 1024))  #将TESTMEM数值转换为KB,保存在memsize变量
  check_memsize   #调用check_memsize函数
fi

# Set max processes to unlimited.
ulimit -u unlimited    #解除最大线程限制

if [ $PROC_NUM -gt 0 ];then
  genload --vm $PROC_NUM --vm-bytes 1073741824 >/dev/null 2>&1 &   #-m, --vm n  spawn n procs spinning on malloc()
fi                                                                 #--vm-bytes b  malloc chunks of b bytes (default is 256MB),以字节Byte为单位,1073741824=1024*1024*1024,Byte转为GB,每个线程申请1GB内存
if [ $leftover_memsize -gt 0 ];then    #将小于1Gb的内存部分单独创建一个线程
  genload --vm 1 --vm-bytes $(($leftover_memsize * 1024)) >/dev/null 2>&1 &
fi

if [ $NO_NETWORK -eq 0 ];then    #加了-n参数则不执行if内语句
 netpipe.sh >/dev/null 2>/dev/null &
fi
${LTPROOT}/bin/rand_lines -g ${LTPROOT}/runtest/stress.part1 > ${TMP}/stress.part1
${LTPROOT}/bin/rand_lines -g ${LTPROOT}/runtest/stress.part2 > ${TMP}/stress.part2
${LTPROOT}/bin/rand_lines -g ${LTPROOT}/runtest/stress.part3 > ${TMP}/stress.part3

sleep 2

if [ $Sar -eq 1 ]; then
  sar -o $datafile $interval > /dev/null &
fi

if [ $Top -eq 1 ]; then
  screen -d -m $LTPROOT/testcases/bin/top -o $datafile -d $interval &
  SCREEN_PID=$(ps -e | grep screen | awk {'print $1'})
fi

sleep 2

if [ $Iostat -eq 1 ]; then
  while [ 0 = 0 ];do iostat -dt >> $iofile; sleep $interval;done &
  Iostat_PID=$?
fi

sleep 2

output1=${TMPBASE}/ltpstress.$$.output1
output2=${TMPBASE}/ltpstress.$$.output2
output3=${TMPBASE}/ltpstress.$$.output3

${LTPROOT}/bin/ltp-pan -e ${PRETTY_PRT} ${QUIET_MODE} -S -t ${hours}h -a stress1 -n stress1 -l $logfile -f ${TMP}/stress.part1 -o $output1 &
${LTPROOT}/bin/ltp-pan -e ${PRETTY_PRT} ${QUIET_MODE} -S -t ${hours}h -a stress2 -n stress2 -l $logfile -f ${TMP}/stress.part2 -o $output2 &
${LTPROOT}/bin/ltp-pan -e ${PRETTY_PRT} ${QUIET_MODE} -S -t ${hours}h -a stress3 -n stress3 -l $logfile -f ${TMP}/stress.part3 -o $output3 &

echo "Running LTP Stress for $hours hour(s) using $(($memsize/1024)) Mb"  #此处$memsize大小为经过check_memsize后小于1GB的部分
echo ""
echo "Test output recorded in:"
echo "        $output1"
echo "        $output2"
echo "        $output3"

# Sleep a little longer than duration to let ltp-pan "try" to gracefully end itself.
sleep $(($duration + 10))

if [ $Sar -eq 1 ]; then
  killall -9 sadc >/dev/null 2>&1
fi
if [ $Top -eq 1 ]; then
  kill $SCREEN_PID >/dev/null 2>&1
fi
killall -9 ltp-pan >/dev/null 2>&1
killall -9 genload >/dev/null 2>&1
if [ $NO_NETWORK -eq 0 ];then
  killall -9 netpipe.sh >/dev/null 2>&1
  killall -9 NPtcp >/dev/null 2>&1
fi
if [ $Iostat -eq 1 ];then
  kill -9 $Iostat_PID >/dev/null 2>&1
fi
rm -rf ${TMP}
echo "Testing done"
if [ $LOGGING -eq 1 ];then
  if [ ! -z $PRETTY_PRT ]; then
    grep FAIL $logfile > /dev/null 2>&1
  else
    grep 'stat=' $logfile | grep -v 'stat=0' > /dev/null 2>&1
  fi

  if [ $? -eq 1 ]; then
    echo "All Tests PASSED!"
  else
    echo "Testing yielded failures. See logfile: $logfile"
    if [ $NO_NETWORK -eq 1 ];then
      echo "The NFS related tests should fail because network stress was disabled"
    fi
  fi
fi

GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐