#!/usr/bin/env bash set -euo pipefail if [[ $# -lt 1 || $# -gt 2 || ! $1 =~ ^[0-9]+$ ]]; then printf 'usage: %s PID [SECONDS]\n' "$0" >&2 exit 64 fi sample_pid=$1 duration=${2:-600} if [[ ! ${duration} =~ ^[0-9]+$ || ${duration} -lt 1 ]]; then printf 'SECONDS must be a positive integer\n' >&2 exit 64 fi if [[ ! -r "/proc/${sample_pid}/stat" ]]; then printf 'PID %s is not readable\n' "${sample_pid}" >&2 exit 66 fi printf 'elapsed_s\tcpu_percent\trss_kib\n' clock_ticks=$(getconf CLK_TCK) read_ticks() { local stat_line stat_fields IFS= read -r stat_line < "/proc/${sample_pid}/stat" || return 1 stat_fields=${stat_line##*) } read -r -a stat_fields <<<"${stat_fields}" printf '%s\n' "$((stat_fields[11] + stat_fields[12]))" } previous_ticks=$(read_ticks) for ((elapsed = 1; elapsed <= duration; elapsed++)); do sleep 1 if [[ ! -r "/proc/${sample_pid}/stat" ]] || ! current_ticks=$(read_ticks); then printf 'process %s exited after %s seconds\n' "${sample_pid}" "${elapsed}" >&2 exit 1 fi delta_ticks=$((current_ticks - previous_ticks)) cpu=$(awk -v ticks="${delta_ticks}" -v hz="${clock_ticks}" \ 'BEGIN { printf "%.2f", ticks * 100 / hz }') rss=$(awk '/^VmRSS:/ { print $2; exit }' "/proc/${sample_pid}/status") printf '%s\t%s\t%s\n' "${elapsed}" "${cpu}" "${rss}" previous_ticks=${current_ticks} done