기반으로이것답변, 내 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[]