# How long a PID has been running (taking multiple inputs)

Tonight I tried to write a POSIX shell script which would allow me to check how long a process is running (via it's ID) and be able to handle multiple inputs:

#!/bin/sh

is_this_a_number()
{
if [ "$1" -eq "$1" ] 2> /dev/null
then
return 0
else
return 1
fi
}

does_pid_exist()
{
if ps --pid "$1" > /dev/null 2>&1 then return 0 else return 1 fi } how_long_pid_has_been_running() { ps --pid "$1" --format etime=
}

{
awk '{$1=$1;print}'
}

arg_pos=0

while [ "$#" -gt 0 ] do arg_val="$1"
arg_pos=$((arg_pos + 1)) if ! is_this_a_number "$arg_val"
then

echo "The argument at position $arg_pos is not a number." else echo "Process ID$arg_val"

if ! does_pid_exist "$arg_val" then echo "This process does not exist." else how_long_pid_has_been_running "$arg_val" | trim_leading_and_trailing_spaces

fi

fi

printf "\\n"

shift

done


Usage:

./how-long-pid-is-running 1 10078 c 40545454


Where 10078 is an instance of Chrome.

The output is as follows:

Process ID 1
09:04:31

Process ID 10078
07:32:32

The argument at position 3 is not a number.

Process ID 40545454
This process does not exist.


• GNU long options are not POSIX, so instead of ps --pid "$1" --format etime=, write ps -p "$1" -o etime=.
• kill -s 0 "$1" >/dev/null 2>&1 is much faster than ps --pid "$1" > /dev/null 2>&1, partly because kill is a builtin in most shells. Signal 0 is used to test for the existence of a process without sending it a signal.
• Consider redirecting the echo messages to the appropriate output streams, i.e. stdout and stderr.
• is_this_a_number, does_pid_exist: these are used directly in if clauses, so it'd read more naturally if they are renamed to is_a_number and pid_exists.
• A minor point here, but I'd reverse the if-else statements to remove the ! negations.
• Another minor point: during the short time span between testing the existence of a PID and querying the elapsed time since the process with that PID was started, the process with that PID could have finished running or even been substituted with a newly spawned one. You could avoid that by running the second command first, saving the output in a variable and then check for nullness, like thus:

echo "Process ID $arg_val" running_time=$(how_long_pid_has_been_running "$arg_val" 2>/dev/null | trim_leading_and_trailing_spaces) if [ -z "${running_time}" ]
then
echo "This process does not exist."
else
echo "${running_time}" fi  • I've seen you write printf "\\n" in another post also, so I'm curious: is it any different from printf "\n"? And in any case, an echo would do the job just as well. Functions forward the exit status of the last command, so the pattern f() { if$command
then
return 0
else
return 1
fi
}


can be replaced with

f()
{
\$command
}


unless you really must force all error returns to 1.