Table of Contents

toolbox.sh

toolbox.sh
#!/usr/bin/env bash
 
insert_date()
{
  while read
  do
    local date_value
    date_value="$(date +"%b %d %T %s.%N")"
    echo "${date_value} ${REPLY}"
  done
}
 
fatal_error_handler()
{
  local result="$?"
  local p_message="$1"
  local pid="${BASHPID}"
  (exit "${result}") ||
  {
    (
      cd "${BASH_SOURCE[1]%/*}"
      echo -n "${FUNCNAME[0]}: $(echo | insert_date)${PWD}/${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]} ${FUNCNAME[1]}() PID(${pid})"
    )
    [ "${p_message}" != "" ] && echo -n " ${p_message}"
    echo
    return "${result}"
  } >&2
}
 
execute_with_retry()
{
  local p_max_try_count="$1"
  shift
  false
  local result="$?"
  local try_number=0
  while ((try_number < p_max_try_count))
  do
    echo "Execute command($@): try #$((try_number+1))/${p_max_try_count}" >&2
    "$@" && return
    result="$?"
    sleep 1
    ((++try_number))
  done
  return "${result}"
}
 
get_own_process_group()
{
  local ps_output
  ps_output=($(ps --no-heading -o pgrp "$$")) || fatal_error_handler || return
  [ "${#ps_output[@]}" = "1" ] || fatal_error_handler || return
  echo "${ps_output[0]}"
}

dd_benchmark.sh

dd_benchmark.sh
#!/usr/bin/env bash
 
cd "${0%/*}" || exit
PATH+=":${PWD}"
cd - &> /dev/null
source "toolbox.sh" || exit
 
set -o pipefail
 
declare -r g_mode_read="READ"
declare -r g_mode_write="WRITE"
 
terminate_process_group()
{
  kill -TERM -"$(get_own_process_group)"
}
 
exit_handler()
{
  terminate_process_group
}
 
int_handler()
{
  terminate_process_group
}
 
child()
{
  local p_mode="$1"
  local p_file="$2"
  local p_log_file="$3"
  if [ "${p_mode}" = "${g_mode_write}" ]
  then
    dd if=/dev/zero of="${p_file}" bs=8M 2>&1 | stdbuf -o0 grep 'copied' | insert_date | tee "${p_log_file}" || fatal_error_handler
  elif [ "${p_mode}" = "${g_mode_read}" ]
  then
    dd if="${p_file}" of=/dev/null bs=8M 2>&1 | stdbuf -o0 grep 'copied' | insert_date | tee "${p_log_file}" || fatal_error_handler
  else
    fatal_error_handler
  fi
  terminate_process_group
}
 
get_dd_pid()
{
  local pid_container
  pid_container=($(pgrep -g "$(get_own_process_group)" dd)) || fatal_error_handler || return
  [ "${#pid_container[@]}" = "1" ] || fatal_error_handler || return
  echo "${pid_container[0]}"
}
 
main()
{
  local p_mode="$1"
  local p_file="$2"
  local p_log_file="$3"
  trap exit_handler EXIT
  trap int_handler SIGINT
  child "${p_mode}" "${p_file}" "${p_log_file}" &
  local dd_pid
  execute_with_retry 5 eval 'dd_pid="$(get_dd_pid)"' || fatal_error_handler || return
  while true
  do
    sleep 1
    kill -USR1 "${dd_pid}" || fatal_error_handler || return
  done
}
 
LANG="C"
main "$@" || fatal_error_handler

Utilisation