44 lines
1.4 KiB
Bash
Executable File
44 lines
1.4 KiB
Bash
Executable File
#!/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
|