스크립트의 실행 시간을 효과적으로 얻는 방법?


340

스크립트 완료 시간을 표시하고 싶습니다.

내가 현재하는 일은-

#!/bin/bash
date  ## echo the date at start
# the script contents
date  ## echo the date at end

이것은 단지 스크립트의 시작과 끝 시간을 보여줍니다. 프로세서 시간 / IO 시간 등과 같이 미세한 출력을 표시 할 수 있습니까?



나는 현존하는 대답이 일시적인 변동 때문에 실제로 충분하지 않다고 생각합니다.
Léo Léopold Hertz 준영

1
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功 제안한 스레드가 여전히 일시적인 이벤트의 영향을 제거하기에 충분하지 않다고 생각합니다.
Léo Léopold Hertz 준영


실행할 수있는 명령이있다가 모든 유닉스 명령을 자동으로 곱한 것입니다.
powder366

답변:


449

time스크립트를 호출 할 때 사용 하십시오.

time yourscript.sh

61
real, user및 세 번 출력 sys됩니다. 이것의 의미는 여기를 참조 하십시오 .
개럿

27
"실제"는 아마도 사람들이 알고 싶어하는 것입니다. "실제 시간은 벽시계 시간-통화 시작부터 끝까지의 시간"
Brad Parks

3
stdout을 파일로 캡처하는 방법이 있습니까? 예를 들어 다음과 같습니다time $( ... ) >> out.txt
Jon

1
명령 행에서 일련의 명령에 대해이를 수행 할 수도 있습니다. 예 :time (command1 && command2)
meetar

1
또는 그는, 자신의 스크립트에서 바로 할 수 있습니다 : $ 에코 초 ....이 떠들썩한 파티를 가정하고
Crossfit_and_Beer

170

time옵션이 아닌 경우

start=`date +%s`
stuff
end=`date +%s`

runtime=$((end-start))

30
초 미만의 정밀도가 필요하지 않은 경우에만 작동합니다. 일부 용도의 경우 허용되지 않을 수도 있습니다. 약간 더 정밀 (여전히 호출하고 들어 date예를 들어, 두 번, 그래서 당신은에서 수있는 최고의 아마 덜 실제로는 밀리 초 정밀도를 얻을 수 등), 사용해보십시오 date +%s.%N. ( %N전체 초 이후의 나노초입니다.)
CVn

좋은 지적. 나는 키보드를 떠난 직후에 그것을 생각했지만 돌아 오지 않았다. ^^ 또한 OP는 "날짜"자체가 런타임에 몇 밀리 초를 추가한다는 것을 기억하십시오.
Rob Bos

2
@ChrisH 오. 그것을 지적하는 것이 좋습니다. bash 산술 확장은 정수 전용입니다. 두 가지 분명한 옵션이 있습니다. 날짜 형식 문자열에서 마침표를 버리고 (결과 값을 에포크 이후 나노초로 처리)을 사용 date +%s%N하거나 bcjwchew가 제안한 두 값에서 실제 런타임을 계산하는 데 더 유용한 것을 사용하십시오. 아직도, 나는이 접근법이 최선의 방법이라고 생각합니다. time위에서 설명한 이유로 사용 가능한 경우 훨씬 더 좋습니다.
CVn

10
그냥 설치 bc하고이 수행runtime=$( echo "$end - $start" | bc -l )
연상

10
스크립트가 몇 분이 걸리면 다음을 사용하십시오.echo "Duration: $((($(date +%s)-$start)/60)) minutes
rubo77

75

그냥 전화 times스크립트를 끝낼 때 인수없이.

ksh또는 zsh, 당신은 또한 사용할 수 있습니다 time대신. 로 zsh, time또한뿐만 아니라 당신에게 벽 시계 시간을 줄 것이다 사용자시스템 CPU 시간.

스크립트의 종료 상태를 유지하려면 다음을 수행하십시오.

ret=$?; times; exit "$ret"

또는 트랩을 추가 할 수도 있습니다 EXIT.

trap times EXIT

이렇게하면 쉘이 종료 될 때마다 시간이 호출되고 종료 상태가 유지됩니다.

$ bash -c 'trap times EXIT; : {1..1000000}'
0m0.932s 0m0.028s
0m0.000s 0m0.000s
$ zsh -c 'trap time EXIT; : {1..1000000}'
shell  0.67s user 0.01s system 100% cpu 0.677 total
children  0.00s user 0.00s system 0% cpu 0.677 total

또한의 모든주의 bash, ksh그리고 zsh$SECONDS자동으로 매초마다 증가됩니다 특별한 변수. 모두에서 zsh하고 ksh93, 그 변수는 부동 소수점 (과를 만들 수 있습니다 typeset -F SECONDS더 정밀도를 얻기 위해). 이것은 CPU 시간이 아닌 벽시계 시간입니다.


12
그 $ SECONDS 변수는 매우 유용합니다!
andybuckley

당신의 접근 방식이 일시적 사건의 영향을 제거합니까? --귀하의 접근 time방식은 이전에 제시된 접근 방식과 거의 같습니다 . timeitMATLAB 코드로 제시된 접근법이 여기서 유용 할 수 있다고 생각합니다 .
Léo Léopold Hertz 준영

2
@ Stéphane Chazelas 님, 안녕하세요. times벽에 걸리지 않는다는 것을 알았 습니다. 예 :bash -c 'trap times EXIT;sleep 2'
user15964


32

나는 밴드 왜건에 약간 늦었지만 다른 사람들이 검색을 통해이 스레드를 우연히 발견 할 수 있도록 내 솔루션 (1 초 미만의 정확도)을 게시하고 싶었습니다. 출력은 일, 시간, 분 및 마지막으로 초 형식입니다.

res1=$(date +%s.%N)

# do stuff in here

res2=$(date +%s.%N)
dt=$(echo "$res2 - $res1" | bc)
dd=$(echo "$dt/86400" | bc)
dt2=$(echo "$dt-86400*$dd" | bc)
dh=$(echo "$dt2/3600" | bc)
dt3=$(echo "$dt2-3600*$dh" | bc)
dm=$(echo "$dt3/60" | bc)
ds=$(echo "$dt3-60*$dm" | bc)

printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds

누군가가 이것이 유용하다는 것을 알기를 바랍니다!


1
계산을 위해 'bc'를 사용하는 것을 제외하고는 다른 (bash 만) 방법이 없다고 생각합니다. BTW 정말 좋은 스크립트;)
tvl

1
FreeBSD date는 1 초 미만의 정밀도를 지원하지 않으며 N타임 스탬프에 리터럴“ ” 만 추가 합니다.
Anton Samsonov

1
아주 좋은 스크립트이지만 내 bash는 1 초 미만의 부분을 처리하지 않습니다. 나는 또한 BC의 / 1이 효과적으로 그것을 제거한다는 것을 알았으므로 $ ds 계산에 @ / 1 @을 추가했으며 지금은 매우 멋진 것을 표시합니다!
Daniel

1
bc는 모듈로를 지원합니다 : dt2=$(echo "$dt%86400" | bc). 그냥 말하기 ... BTW 나는 양식을 선호 dt2=$(bc <<< "${dt}%86400")하지만 그것은 전적으로 개인적입니다.
Dani_l

16

내 방법 bash:

# Reset BASH time counter
SECONDS=0
    # 
    # do stuff
    # 
ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"

이것은 경과 시간을 표시하지만 질문에 요청 된대로 "프로세서 시간, I / O 시간과 같은 미세한 출력"을 표시하지 않습니다.
roaima

3
제시된 질문에 대한 답변을 찾는 사람들은이 솔루션이 유용하다는 것을 알게 될 것입니다. 귀하의 의견은 OPs 질문에 더 잘 설명됩니다.
Mark

5
#!/bin/bash
start=$(date +%s.%N)

# HERE BE CODE

end=$(date +%s.%N)    
runtime=$(python -c "print(${end} - ${start})")

echo "Runtime was $runtime"

예, 이것은 Python을 호출하지만 그와 함께 살 수 있다면 이것은 아주 훌륭하고 간결한 솔루션입니다.


5
python서브 쉘에서 해당 명령 을 실행 하고 출력을 읽는 데 대부분의 최신 시스템에서 수백만 나노초가 소요 된다는 점에 유의하십시오 . 실행과 동일합니다 date.
Stéphane Chazelas

7
"수백만 나노초"는 몇 밀리 초입니다. bash 스크립트를 타이밍하는 사람들은 일반적으로 그것에 대해 크게 신경 쓰지 않습니다 (메가 초 당 수십억 개의 스크립트를 실행하지 않는 한).
Zilk

2
또한 파이썬 프로세스 내에서 계산을 수행하더라도 파이썬이 호출되기 전에 값이 완전히 수집됩니다. 스크립트의 실행 시간은 "백만 나노초"오버 헤드없이 정확하게 측정됩니다.
빅터 슈뢰더

5

이 질문은 꽤 오래되었지만 내가 좋아하는 방법을 찾으려고 노력 하면서이 스레드가 높아졌습니다 ... 그리고 아무도 그것을 언급하지 않은 것에 놀랐습니다.

perf stat -r 10 -B sleep 1

'perf'는 커널의 'tools / perf'에 포함 된 성능 분석 도구이며 별도의 패키지 (CentOS의 'perf'및 Debian / Ubuntu의 'linux-tools')로 설치하는 경우가 종종 있습니다. Linux Kernal perf Wiki 에는 이에 대한 자세한 정보가 있습니다.

'perf stat'를 실행하면 마지막에 평균 실행 시간을 포함하여 상당히 많은 세부 정보가 제공됩니다.

1.002248382 seconds time elapsed                   ( +-  0.01% )

2
무엇입니까 perf?
B 레이어

@B 레이어- 'perf'에 대한 간단한 설명을 제공하기 위해 내 답변을 편집했습니다.
Zaahid

1
perf stat이제 "통계 수집 권한이 없을 수 있습니다." 를 사용하여 일부 명령을 실행 sudo하지 않으면 대상 시스템을 완전히 소유하지 않은 모든 시나리오에서 쓸모가 없습니다.
alamar

4

명령 전에 시간을 측정하기 위해 추가 할 수있는 작은 쉘 기능 :

tm() {
  s=$(date +%s)
  $@
  rc=$?
  echo "took $[$(date +%s)-$s] seconds. return code $rc" >&2
  return $rc
}

그런 다음 스크립트 또는 명령 행에서 다음과 같이 사용하십시오.

tm the_original_command with all its parameters

밀리 초를 추가하고 ilke 시도해보십시오 s=$(date +%s000). 작동하는지 확실하지 않습니다.
loretoparisi

3

다음은 Alex의 답변 변형입니다. 몇 분과 몇 초 만 신경 쓰지만 다른 형식으로 원했습니다. 그래서 나는 이것을했다 :

start=$(date +%s)
end=$(date +%s)
runtime=$(python -c "print '%u:%02u' % ((${end} - ${start})/60, (${end} - ${start})%60)")

1
왜 공감해야합니까? 버그가 있습니까?
mpontillo

3
#!/bin/csh
#PBS -q glean
#PBS -l nodes=1:ppn=1
#PBS -l walltime=10:00:00
#PBS -o a.log
#PBS -e a.err
#PBS -V
#PBS -M shihcheng.guo@gmail.com
#PBS -m abe
#PBS -A k4zhang-group
START=$(date +%s)
for i in {1..1000000}
do
echo 1
done
END=$(date +%s)
DIFF=$(echo "$END - $START" | bc)
echo "It takes DIFF=$DIFF seconds to complete this task..."

7
이것은 date스크립트 전후에 어떤 용도로 사용하여 이미 주어진 다른 답변 과 어떻게 다른가요?
Eric Renouf

2

bash 사용 하면 쉘 스크립트의 일부 (또는 전체 스크립트의 경과 시간)에 대한 지속 시간 을 측정하고 계산할 수도 있습니다 .

start=$SECONDS

... # do time consuming stuff

end=$SECONDS

이제 차이점을 인쇄 할 수 있습니다.

echo "duration: $((end-start)) seconds."

증분 기간 만 필요한 경우 다음을 수행하십시오.

echo "duration: $((SECONDS-start)) seconds elapsed.."

기간을 변수에 저장할 수도 있습니다.

let diff=end-start

^ 이것은 응답자입니다. 또는 더 간단하게 말하면 $ SECONDS입니다. BUILT-IN Bash 변수입니다. 다른 모든 답변은이 바퀴를 재발 명하기 위해 추가 작업을하고 있습니다 ...
Crossfit_and_Beer

2

개인적으로 모든 스크립트 코드를 다음과 같은 "기본"기능으로 래핑하고 싶습니다.

main () {
 echo running ...
}

# stuff ...

# calling the function at the very end of the script
time main

time이 시나리오 에서 명령 을 사용하는 것이 얼마나 쉬운 지 확인하십시오 . 분명히 스크립트 구문 분석 시간을 포함하여 정확한 시간을 측정하지는 않지만 대부분의 상황에서 충분히 정확합니다.


1
#!/bin/bash
begin=$(date +"%s")

Script

termin=$(date +"%s")
difftimelps=$(($termin-$begin))
echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."

1

에 기반한 타이밍 기능 SECONDS은 2 차 수준의 입도로만 제한되며 외부 명령을 사용하지 않습니다.

time_it() {
  local start=$SECONDS ts ec
  printf -v ts '%(%Y-%m-%d_%H:%M:%S)T' -1
  printf '%s\n' "$ts Starting $*"
  "$@"; ec=$?
  printf -v ts '%(%Y-%m-%d_%H:%M:%S)T' -1
  printf '%s\n' "$ts Finished $*; elapsed = $((SECONDS-start)) seconds"
  # make sure to return the exit code of the command so that the caller can use it
  return "$ec"
}

예를 들면 다음과 같습니다.

time_it sleep 5

준다

2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished
sleep 5; elapsed = 5 seconds
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.