1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2023 Intel Corporation 4# All rights reserved. 5 6shopt -s nullglob extglob 7 8pmdir=$(readlink -f "$(dirname "$0")") 9rootdir=$(readlink -f "$pmdir/../../../") 10source "$pmdir/common" 11 12help() { 13 cat <<- HELP 14 15 Usage: $0 [-h] [-c count] [-d dir] [-l] [-p prefix] [-r reprint_header_count] 16 17 -h - Print this message. 18 -c - Execute count times. 0 is the default and it means to run 19 indefinitely. 20 -d - Directory where results should be saved. Default is /tmp. 21 -l - Save output of the script to a log file (dir/${0##*/}.pm.log). 22 -p - Add prefix to saved files. 23 -r - Stat count after which header should be re-printed. Default is 20. 24 -t - How long to wait before each stat dump. Default is 1s. 25 26 When started, ${0##*/} will enter loop to continuosly dump 27 vmstat. Each iteration will be logged to stderr and a log file 28 (dir/${0##*/}.pm.log). 29 30 HELP 31} 32 33get_extra_info() { 34 local match="" data 35 36 case "$PM_OS" in 37 Linux) 38 match+="|MemAvailable" 39 match+="|Shmem" 40 match+="|HugePages_(Total|Free)" 41 match+="|Hugepagesize" 42 43 data=($(grep -E "^($match):" /proc/meminfo | awk '{print $2}')) 44 ;& 45 *) data+=("$TEST_TAG") ;; 46 esac 47 echo "${data[*]}" 48} 49 50set_extra_info_header() { 51 local -n header_ref=$1 52 local _header 53 54 # Keep the header ordered as in get_extra_info() 55 case "$PM_OS" in 56 Linux) _header="avail shmem hp_total hp_free hp_size test" ;; 57 FreeBSD) _header="test" ;; 58 esac 59 60 header_ref[0]="${header_ref[0]} ----extra info----" 61 header_ref[1]="${header_ref[1]} $_header" 62} 63 64_vmstat() { 65 local count=$1 interval=$2 reprint_header=${3:-20} _count 66 local vmstat vmstat_cmdline=() _vmstat stat_idx header=() 67 68 [[ $PM_OS == Linux ]] && vmstat_cmdline+=(--timestamp) 69 70 _count=$count 71 while ((stat_idx = stat_idx == reprint_header ? 1 : ++stat_idx, count <= 0 ? 1 : _count--)); do 72 mapfile -t vmstat < <(vmstat "${vmstat_cmdline[@]}") 73 # Enhance output to include stuff we are most interested in 74 vmstat[2]="${vmstat[2]} $(get_extra_info)" 75 if ((stat_idx == 1)); then 76 header=("${vmstat[@]::2}") 77 set_extra_info_header header 78 _vmstat=("${header[@]}" "${vmstat[2]}") 79 else 80 _vmstat=("${vmstat[2]}") 81 fi 82 printf '%s\n' "${_vmstat[@]}" 83 sleep "${interval}" 84 done 85} 86 87cleanup() { 88 rm_pm_pid 89} 90 91count=0 92interval=1 93log_to_file=no 94prefix="" 95reprint_header=20 96 97while getopts c:d:hlp:r:t: opt; do 98 case "$opt" in 99 c) count=$OPTARG ;; 100 d) PM_OUTPUTDIR=$OPTARG ;; 101 h) 102 help 103 exit 0 104 ;; 105 l) log_to_file=yes ;; 106 p) prefix=$OPTARG ;; 107 r) reprint_header=$OPTARG ;; 108 t) interval=$OPTARG ;; 109 *) ;; 110 esac 111done 112 113declare -r log_file=${prefix:+${prefix}_}${0##*/}.pm.log 114 115mkdir -p "$PM_OUTPUTDIR" 116if [[ $log_to_file == yes ]]; then 117 printf 'Redirecting to %s\n' "$PM_OUTPUTDIR/$log_file" >&2 118 exec > "$PM_OUTPUTDIR/$log_file" 2>&1 119fi 120 121save_pm_pid 122trap 'cleanup' EXIT 123trap 'retag' USR1 124 125_vmstat "$count" "$interval" "$reprint_header" 126