Bash script to calculate time elapsed
Either $(())
or $[]
will work for computing the result of an arithmetic operation. You're using $()
which is simply taking the string and evaluating it as a command. It's a bit of a subtle distinction. Hope this helps.
As tink pointed out in the comments on this answer, $[]
is deprecated, and $(())
should be favored.
How to calculate time elapsed in bash script?
Bash has a handy SECONDS
builtin variable that tracks the number of seconds that have passed since the shell was started. This variable retains its properties when assigned to, and the value returned after the assignment is the number of seconds since the assignment plus the assigned value.
Thus, you can just set SECONDS
to 0 before starting the timed event, simply read SECONDS
after the event, and do the time arithmetic before displaying.
#!/usr/bin/env bash
SECONDS=0
# do some work
duration=$SECONDS
echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed."
As this solution doesn't depend on date +%s
(which is a GNU extension), it's portable to all systems supported by Bash.
Shell script to calculate time elapsed
The output of time
goes to stderr. You have to redirect it.
TIMEFORMAT=%R
r=$( { time /home/pop/Daa/./a.out; } 2>&1 )
And you can't have spaces around the equal sign. It is preferable to use $()
instead of backticks since it's easier to read, there's no confusion with single quotes and it's easier to nest them.
Adjust elapsed time for 5 hours?
You can use bash regular expression to get different components :
#!/bin/bash
PROC_NAME=my_proc_name
# Get all PIDs for process name
procs=(`ps aux | grep $PROC_NAME | awk '{print $2}'`)
pattern='((.*)-)?((..):)?(..):(..)'
for pid in ${procs[@]}; do
if [[ "$(ps -o etime= -p $pid)" =~ $pattern ]] && {
[ -n "${BASH_REMATCH[2]}" ] || # if day component exists, then it's more than 5 hours
{ [ -n "${BASH_REMATCH[4]}" ] && ((10#${BASH_REMATCH[4]} >= 5)); } }; then
echo kill -9 $pid
fi
done
Remove echo
(dry run) if you see the result is expected.
Explanation of pattern='((.*)-)?((..):)?(..):(..)' :
1) ((.*)-)? means optional day component
if present like 9- then ${BASH_REMATCH[1]} = 9-, ${BASH_REMATCH[2]} = 9
if absent, ${BASH_REMATCH[2]} is empty
2) ((..):)? means optional hour component
if present like 05 then ${BASH_REMATCH[3]} = 05:,${BASH_REMATCH[4]} = 05
if absent, ${BASH_REMATCH[4]} is empty
Bash: Calculate the time differences in hours from input like YYYYMMDDHH
For performance reasons we want to limit the number of sub-process calls we need to invoke:
- use
bash
substring functionality to convert inputs into usable date/time strings - use
bash
math to replacebc
call
bash
substring functionality to break the inputs into a usable date/time format, eg:
# convert to usable date/time format:
$ start_date=1996010100
$ echo "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00"
1996-01-01 00:00:00
# convert to epoch/seconds:
$ start=$(date -d "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00" +"%s")
$ echo $start
820476000
Applying to ${end_date}
and using bash
math:
$ end_date=1996010122
$ end=$(date -d "${end_date:0:4}-${end_date:4:2}-${end_date:6:2} ${end_date:8:2}:00:00" +"%s")
$ echo $end
820555200
$ hours=$(( (end - start) / 3600))
$ echo $hours
22
This leaves us with 2 sub-process calls ($(date ...)
). While other languages/tools (awk
, perl
, etc) can likely speed this up a bit, if you need to store the result in a bash
variable then you're looking at needing at least 1 sub-process call (ie, hours=$(awk/perl/??? ...)
).
If performance is really important (eg, needing to perform this 1000's of times) take a look at this SO answer that uses a fifo, background date
process and io redirection ... yeah, a bit more coding and a bit more convoluted but also a bit faster for large volumes of operations.
how to calculate total elapsed time
Limitation of this solution: Max 23 hours. For more, days need to be added.
StartTime="June 3, 2019 at 2:50:02 am"
EndTime="June 3, 2019 at 5:06:40 am"
StartTimeInEpoch=`echo $StartTime | sed 's/at //g' | date -f- +"%s"`
EndTimeInEpoch=`echo $EndTime | sed 's/at //g' | date -f- +"%s"`
echo $EndTimeInEpoch-$StartTimeInEpoch | bc | sed 's/^/@/g' | date -u -f- "+%_H hours %_M minutes %_S seconds"
Output:
2 hours 16 minutes 38 seconds
Assuming you've got your dates in variables StartTime
and EndTime
. It's necessary to remove at
from them, sed
do this. Then both dates are converted to epoch time +"%s"
do the trick. -f-
tells date
to take date from stdin (pipe). Then we can subtract the dates, add @
to the beginning and format with date
. -u
mean UTC time - no time shift.
Related Topics
Why Do I Get 'Permission Denied' After Using ./File2 in Linux
How to Delete History of Last 10 Commands in Shell
How to Have Tcpdump Write to File and Standard Output the Appropriate Data
How to Print Only the Hex Values from Hexdump Without the Line Numbers or the Ascii Table
Android Studio Error After ./Studio.Sh
Installed Clang++3.6 on Ubuntu, Can't Select as Alternative
How to Create a Waveform Image of an Mp3 in Linux
Maximum Resident Set Size Does Not Make Sense
How to Show a 'Grep' Result with the Complete Path or File Name
Permission Denied Error When Running Crontab
Learning Kernel Hacking and Embedded Development at Home
Find Files in Created Between a Date Range
Managing User Configuration Files Across Multiple Computers
Linux Script with Curl to Check Webservice Is Up
How to Get "Requests Per Second" for Apache in Linux