Bash 스크립트에서 시간을 측정하는 방법은 무엇입니까?

Bash 스크립트에서 시간을 측정하는 방법은 무엇입니까?

기반으로이것답변, 내 bash 스크립트에서 시간을 측정하려면 다음을 사용할 수 있습니다.

start_time="$(date -u +%s.%N)"
sleep 5
end_time="$(date -u +%s.%N)"

elapsed="$(bc <<<"$end_time-$start_time")"
echo "Total of $elapsed seconds elapsed for process"

그리고 그것은 훌륭하게 작동합니다. 하지만 스크립트 파일이 많기 때문에 코드를 단순화하고 건조시키고 싶습니다. 예를 들어 다음과 같은 코드를 구현하고 싶습니다.

. /time.sh

start_time=now
sleep 5
end_time=now

measure_time

즉, time.sh어디에든 포함될 수 있고 두 가지 기능을 갖는 또 다른 스크립트를 원합니다. 하나는 부품을 교체하는 것이고 "$(date -u +%s.%N)", 다른 하나는 "$(bc <<<"$end_time-$start_time")"부품을 교체하는 것입니다.

이러한 함수를 만들어 보았지만 쉘에서는 함수에서 값을 반환할 수 없다는 것을 깨달았습니다. 숫자만 반환할 수 있습니다.

위 코드를 아래 코드로 단순화할 수 있는 방법이 있나요?

답변1

무엇이 잘못되었나요 time ./script.sh?

간단한 예:-

취침 시간 5

real    0m5.001s
user    0m0.001s
sys 0m0.000s

답변2

최신 버전의 bash(5.0+)에는 시간을 마이크로초(소수점 6자리) 단위로 제공하는 변수가 있습니다. 이것이 귀하의 사용법에 충분히 정확하다면 다음 스크립트를 시도해 볼 수 있습니다.

#!/bin/bash --
time_diff(){ 
    local elapsed="$(bc <<<"${send}-${start}")"
    echo "Total of $elapsed seconds elapsed for process";
 }

start=$EPOCHREALTIME
sleep 5
end=$EPOCHREALTIME

time_diff

date스크립트는 동일한 작업을 수행하기 위해 외부 실행 파일( )을 호출하는 것보다 더 빠르게 시간 값을 가져옵니다 .

답변3

가장 간단한 형태로 보면 이것이 당신이 원하는 것과 비슷해 보입니다.

now(){
  date -u +%s.%N
}

measure_time(){
  local elapsed="$(bc <<<"$end_time-$start_time")"
  echo "Total of $elapsed seconds elapsed for process"
}

start_time="$(now)"
sleep 5
end_time="$(now)"

measure_time

now함수가 명명된 변수를 허용 하도록 하고 measure_time해당 변수를 처리하도록 함수를 조정할 수 있지만 사용 사례가 한 번에 하나의 프로세스를 추적하는 것이라면 이는 불필요하게 복잡해집니다.

그렇긴 하지만, 이것은 그 방향으로의 반복입니다. 임의의 레이블 start이므로 end여러 이벤트를 추적하려는 경우 적절한 이름으로 호출할 수 있습니다.

stamp(){
  time[$1]="$(date -u +%s.%N)"
}

measure_time(){
  local elapsed="$(bc <<<"${time[$2]}-${time[$1]}")"
  echo "Total of $elapsed seconds elapsed for process"
}

declare -A time=()

stamp start
sleep 5
stamp end

measure_time start end

편집하다:

경고하다

roaima의 답변에 있는 숫자에서 알 수 있듯이 모든 작업(특히 하위 쉘 및 외부 프로세스)이 보고된 시간 초과를 몇 분의 1초씩 채우기 때문에 이는 매우 정확하지 않습니다. 이는 수 분이 소요되는 프로세스에서는 중요하지 않을 수 있지만(이 경우 나노초를 측정하는 이유는 무엇입니까?) 런타임이 낮을수록 더 눈에 띄고 거의 의미가 없게 됩니다. 내 테스트에서는 문제가 roaima에 비해 그렇게 심각하지 않았습니다. 이는 데이터를 어떤 용도로 사용하는지에 따라 달라집니다.

또 다른 편집:

QuartzCrystal의 공정한 의견에 대한 응답으로 roaima의 답변에 수렴되는 추가 반복이 있습니다. 이는 아마도 그들이 "최고" 트랙에 있음을 보여줄 수 있습니다.

_stamp(){
  time[${1:?}]="$(date -u +%s.%N)"
}

_start() {
  _stamp "start${1:+_${1}}"
}

_end() {
  _stamp "end${1:+_${1}}"
}

measure_time(){
  local elapsed="$(bc <<<"${time[end${1:+_${1}}]}-${time[start${1:+_${1}}]}")"
  echo "Total of $elapsed seconds elapsed${1:+ for process ${1}}"
}

declare -A time=()

_start
sleep 5
_end

measure_time

_start foo
sleep 1
_start bar
sleep 2
_end foo
_end bar

measure_time foo
measure_time bar

답변4

bash연관 배열( 등) 이 필요한 버전은 다음과 같습니다.

예를 들어timers.sh

#!/bin/bash
########################################################################
declare -A _timers

# Declare and start a timer. Optional name
startTimer() {
    _timers[${1:-_}_s]=$(date -u +'%s.%N')
}

# End a timer. Optional name
endTimer() {
    _timers[${1:-_}_e]=$(date -u +'%s.%N')
}

# Report on the duration of a timer. Optional name
diffTimer() {
    local s=${_timers[${1:-_}_s]} e=${_timers[${1:-_}_e]}
    bc <<< "${e:-$(date -u +'%s.%N')} - ${s:-0}"
}

메인 코드

#!/bin/bash
. timers.sh

startTimer
sleep 2
startTimer sub
sleep 0.1
endTimer sub
endTimer

echo "Elapsed $(diffTimer) and for sub $(diffTimer sub)"

산출

Elapsed 2.321831200 and for sub .183521000

매개변수가 없으면 함수는 기본 타이머에 따라 작동합니다. 그렇지 않으면 지정된 타이머에 따라 작동합니다. 호출되지 않거나 startTimer기본값 endTimer을 사용하는 0경우지금사용된. 타이머는 전역 연관 배열에 저장됩니다._timers[]

관련 정보