#!/bin/bash

function display_help
{
  cat << EOF
${0##*/} [-c column_index] [-e] [-f data_file] [-h] [-p] [-r refresh_rate_value] [-t column_title]
-c column_index
	You can use this parameter several times and you must use it as many times than column_title parameter.
	column_index starts at one.
-e
	Erase existing data file.
	Non-erase (append) mode by default.
-f data_file
	data_file will contain data to be plotted.
	If you omit this parameter, a temporary data file (provided by mktemp command) will be used.
-h
	This short help message.
-p
	Enable data producer.
	Disabled by default.
-r refresh_rate_value
	Refresh rate (in seconds) for plotting data.
	One second by default.
-t column_title
	You can use this parameter several times and you must use it as many times than column_index parameter.
	Title used as name for plotting data.
EOF
}

function parse_option
{
  local current_option
  while [ ! $# -lt ${OPTIND} ]
  do
    while getopts :c:ef:hpr:t: current_option
    do
      case ${current_option} in
        c)
          g_column_container+=("${OPTARG}")
          ;;
        e)
          g_erase_data='true'
          ;;
        f)
          g_data_file=${OPTARG}
          ;;
        h)
          display_help
          exit
          ;;
        p)
          g_enable_producer='true'
          ;;
        r)
          g_period=${OPTARG}
          ;;
        t)
          g_title_container+=("${OPTARG}")
          ;;
        \?)
          echo "invalid option: -${OPTARG}" >&2
          exit
          ;;
      esac
    done
    ((++OPTIND))
  done
}

function consolide_option
{
  [ -z "${g_data_file}" ] && { g_data_file=$(mktemp); g_enable_producer='true'; }
  g_period=${g_period:-1}
  g_column_container=("${g_column_container[@]:-4}")
  g_title_container=("${g_title_container[@]:-free}")
  g_enable_producer=${g_enable_producer:-false}
  g_erase_data=${g_erase_data:-false}
  [ "${g_enable_producer}" = 'false' ] && [ ! -f "${g_data_file}" ] && exit
  [ ${#g_column_container[@]} = ${#g_title_container[@]} ] || exit
  local idx=0
  while [ ${idx} -lt ${#g_column_container[@]} ]
  do
    g_container+=("${g_column_container[idx]}")
    g_container+=("${g_title_container[idx]}")
    ((++idx))
  done
}

function data_producer
{
  local p_data_output_file=$1
  local p_erase_data=$2
  
  if [ "${p_erase_data}" = 'true' ]
  then
    vmstat -n 1 | sed -u '1,2d' > "${p_data_output_file}"
  else
    local word_count1=$(tail -2 "${p_data_output_file}" | sed -n '1p' | wc -w)
    local word_count2=$(tail -2 "${p_data_output_file}" | sed -n '2p' | wc -w)
    if [ ${word_count1} -ne ${word_count2} ]
    then
      local last_line=$(tail -1 "${p_data_output_file}")
      sed -i '$d' "${p_data_output_file}"
      echo '# corrupted data: '${last_line} >> "${p_data_output_file}"
    fi
    echo '# append data begin here' >> "${p_data_output_file}"
    vmstat -n 1 | sed -u '1,2d' >> "${p_data_output_file}"
  fi
}

function data_extractor
{
  local p_data_input_file=$1
  local p_data_output_file=$2

  sed '$d' "${p_data_input_file}" | grep -v '^#' | nl -v0 > "${p_data_output_file}"
}

function compute_gnuplot_command
{
  local p_data_input_file=$1
  shift
  local p_data_column
  local p_data_title
  
  local gnuplot_command
  while [ $# -ne 0 ]
  do
    p_data_column=$1
    ((++p_data_column))
    shift
    p_data_title=$1
    shift
    gnuplot_command+=', '\'${p_data_input_file}\'' using 1:'${p_data_column}' title '\'${p_data_title}\'' with lines'
  done
  gnuplot_command='plot'${gnuplot_command#,}
  echo "${gnuplot_command}"
}

function main
{
  local p_data_file=$1
  shift
  local p_refresh_period=$1
  shift
  local p_enable_producer=$1
  shift
  local p_erase_data=$1
  shift
  
  trap 'kill -TERM -$$' INT
  [ "${p_enable_producer}" = 'true' ] && data_producer "${p_data_file}" "${p_erase_data}" &
  local tmp_data_file=$(mktemp)
  trap 'rm "'${tmp_data_file}'"' EXIT
  local gnuplot_command=$(compute_gnuplot_command "${tmp_data_file}" "$@")
  local previous_line_count=0
  while true
  do
    sleep ${p_refresh_period}
    local current_line_count=$(wc -l "${p_data_file}" | awk '{print $1}')
    if [ ${previous_line_count} -ne ${current_line_count} ]
    then
      data_extractor "${p_data_file}" "${tmp_data_file}"
      echo "${gnuplot_command}"
      previous_line_count=${current_line_count}
    fi
  done
}

parse_option "$@"
consolide_option
main "${g_data_file}" "${g_period}" "${g_enable_producer}" "${g_erase_data}" "${g_container[@]}" | gnuplot -persistent

MORE

plot.txt · Last modified: 2022/04/16 12:23 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki