마지막 명령의 실제 시간을 Bash 프롬프트에 어떻게 넣을 수 있나요?

StackOverflow https://stackoverflow.com/questions/1862510

  •  16-09-2019
  •  | 
  •  

문제

마지막 명령의 경과된 실제 시간을 세게 때리다 즉각적인?나는 다음과 같은 것을 기대하고 있습니다.

[last: 0s][/my/dir]$ sleep 10
[last: 10s][/my/dir]$

배경

나는 종종 장기간의 데이터 처리 작업을 수행하는데, 소요 시간을 아는 것이 유용하므로 향후 작업에 소요되는 시간을 예측할 수 있습니다.매우 일반적인 작업의 경우 적절한 로깅 기술을 사용하여 이 정보를 엄격하게 기록합니다.덜 공식적인 작업의 경우 명령 앞에 다음을 추가하겠습니다. time.

자동으로 하면 좋겠지만 time 모든 단일 대화형 명령을 실행하고 타이밍 정보를 3줄이 아닌 몇 글자로 인쇄합니다.

도움이 되었습니까?

해결책

이 ZSH 차용 후크를 Bash에 활용할 수 있습니다. http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

이 후크 (Mac OS X)로 수행 된 타이밍 : 으르렁 거리는 growl을 사용하여 장기 실행 쉘 명령을 모니터링하십시오

다른 팁

이것은 원하는 것을 달성하기위한 최소한의 독립형 코드입니다.

function timer_start {
  timer=${timer:-$SECONDS}
}

function timer_stop {
  timer_show=$(($SECONDS - $timer))
  unset timer
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}s][\w]$ '

귀하의 답변과 다른 스레드를 사용하여, 나는 당신과 공유하고 싶은이 프롬프트를 썼습니다. 나는 당신이 볼 수있는 wich에서 스크린 샷을 찍었습니다.

  • 흰색 : 마지막 반환 코드
  • 녹색과 스타크 마크는 성공을 의미합니다 (반환 코드는 0)
  • 빨간색과 크로스 마크는 오류를 의미합니다 (반환 코드는> 0)
  • (녹색 또는 빨간색) : 괄호 안에서의 마지막 명령 실행 시간
  • (녹색 또는 빨간색) : 현재 날짜 시간 ( t)
  • (루트가 아닌 경우 녹색, 루트 인 경우 빨간색) : 로그인 한 사용자 이름
  • (녹색) : 서버 이름
  • (파란색) : PWD 디렉토리 및 일반 $

Custom prompt

다음은 ~/.bashrc 파일에 넣을 코드입니다.

function timer_now {
    date +%s%N
}

function timer_start {
    timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
    local delta_us=$((($(timer_now) - $timer_start) / 1000))
    local us=$((delta_us % 1000))
    local ms=$(((delta_us / 1000) % 1000))
    local s=$(((delta_us / 1000000) % 60))
    local m=$(((delta_us / 60000000) % 60))
    local h=$((delta_us / 3600000000))
    # Goal: always show around 3 digits of accuracy
    if ((h > 0)); then timer_show=${h}h${m}m
    elif ((m > 0)); then timer_show=${m}m${s}s
    elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
    elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
    elif ((ms >= 100)); then timer_show=${ms}ms
    elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
    else timer_show=${us}us
    fi
    unset timer_start
}


set_prompt () {
    Last_Command=$? # Must come first!
    Blue='\[\e[01;34m\]'
    White='\[\e[01;37m\]'
    Red='\[\e[01;31m\]'
    Green='\[\e[01;32m\]'
    Reset='\[\e[00m\]'
    FancyX='\342\234\227'
    Checkmark='\342\234\223'


    # Add a bright white exit status for the last command
    PS1="$White\$? "
    # If it was successful, print a green check mark. Otherwise, print
    # a red X.
    if [[ $Last_Command == 0 ]]; then
        PS1+="$Green$Checkmark "
    else
        PS1+="$Red$FancyX "
    fi

    # Add the ellapsed time and current date
    timer_stop
    PS1+="($timer_show) \t "

    # If root, just print the host in red. Otherwise, print the current user
    # and host in green.
    if [[ $EUID == 0 ]]; then
        PS1+="$Red\\u$Green@\\h "
    else
        PS1+="$Green\\u@\\h "
    fi
    # Print the working directory and prompt marker in blue, and reset
    # the text color to the default.
    PS1+="$Blue\\w \\\$$Reset "
}

trap 'timer_start' DEBUG
PROMPT_COMMAND='set_prompt'

또 다른 최소한의 접근 방식은 다음과 같습니다.

trap 'SECONDS=0' DEBUG
export PS1='your_normal_prompt_here ($SECONDS) # '

마지막 단순 명령이 시작된 이후의 시간(초)을 표시합니다.명령을 입력하지 않고 Enter만 누르면 카운터가 재설정되지 않습니다. 이는 터미널에서 마지막 작업을 수행한 이후 터미널이 얼마나 오랫동안 작동했는지 확인하려는 경우에 유용할 수 있습니다.Red Hat과 Ubuntu에서는 잘 작동합니다.Cygwin에서는 작동하지 않았지만 이것이 버그인지 아니면 Windows에서 Bash를 실행하려고 할 때의 제한인지는 확실하지 않습니다.

이 접근 방식의 한 가지 가능한 단점은 SECONDS를 계속 재설정한다는 것입니다. 그러나 초기 셸 호출 이후 SECONDS를 초 단위로 유지해야 하는 경우 SECONDS를 직접 사용하는 대신 PS1 카운터에 대한 고유한 변수를 만들 수 있습니다.또 다른 가능한 단점은 "999999"와 같은 큰 초 값이 일+시+분+초로 표시되는 것이 더 나을 수 있지만 다음과 같은 간단한 필터를 쉽게 추가할 수 있다는 것입니다.

seconds2days() { # convert integer seconds to Ddays,HH:MM:SS
  printf "%ddays,%02d:%02d:%02d" $(((($1/60)/60)/24)) \
  $(((($1/60)/60)%24)) $((($1/60)%60)) $(($1%60)) |
  sed 's/^1days/1day/;s/^0days,\(00:\)*//;s/^0//' ; }
trap 'SECONDS=0' DEBUG
PS1='other_prompt_stuff_here ($(seconds2days $SECONDS)) # '

이는 "999999"를 "11일,13:46:39"로 변환합니다.마지막에 있는 sed는 "1days"를 "1day"로 변경하고 "0days,00:"과 같은 빈 선행 값을 잘라냅니다.입맛에 맞게 조절하세요.

장기 실행 업무를 시작하기 전에 다른 답변을 설정하지 않았고 작업이 얼마나 오래 걸렸는지 알고 싶다면 간단한 일을 할 수 있습니다.

$ HISTTIMEFORMAT="%s " history 2

그리고 그것은 같은 것으로 대답 할 것입니다

  654  1278611022 gvn up
  655  1278611714 HISTTIMEFORMAT="%s " history 2

그런 다음 두 타임 스탬프를 시각적으로 빼면 쉘 내장 기록 명령의 출력을 캡처하는 방법을 알고 있습니까?)

나는 Ville Laurikari로부터 답을 가져 와서 time 초 초 정확도를 표시하는 명령 :

function timer_now {
  date +%s%N
}

function timer_start {
  timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
  local delta_us=$((($(timer_now) - $timer_start) / 1000))
  local us=$((delta_us % 1000))
  local ms=$(((delta_us / 1000) % 1000))
  local s=$(((delta_us / 1000000) % 60))
  local m=$(((delta_us / 60000000) % 60))
  local h=$((delta_us / 3600000000))
  # Goal: always show around 3 digits of accuracy
  if ((h > 0)); then timer_show=${h}h${m}m
  elif ((m > 0)); then timer_show=${m}m${s}s
  elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
  elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
  elif ((ms >= 100)); then timer_show=${ms}ms
  elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
  else timer_show=${us}us
  fi
  unset timer_start
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}][\w]$ '

물론 이것은 프로세스를 시작해야하므로 효율적이지 않지만 눈치 채지 못할 정도로 충분히 빠릅니다.

나는 그것을 발견했다 trap ... DEBUG 매번 달리고있었습니다 $PROMPT_COMMAND 타이머를 재설정하여 호출되었으므로 항상 0을 반환합니다.

그러나 나는 그것을 발견했다 history 시간을 기록하고 나는 이것들을 통해 내 대답을 얻었습니다.

HISTTIMEFORMAT='%s '
PROMPT_COMMAND="
  START=\$(history 1 | cut -f5 -d' ');
  NOW=\$(date +%s);
  ELAPSED=\$[NOW-START];
  $PROMPT_COMMAND"
PS1="\$ELAPSED $PS1"

그래도 완벽하지는 않습니다.

  • 만약에 history 명령 (예 : 반복 또는 무시 된 명령)을 등록하지 않으면 시작 시간이 잘못됩니다.
  • 멀티 라인 명령은 날짜가 올바르게 추출되지 않습니다 history.

Bash 4.x 이상의 또 다른 접근 방식은 사용하는 것입니다. coproc ~와 함께 PS0 그리고 PS1 아래처럼 :

cmd_timer()
{
    echo $(( SECONDS - $(head -n1 <&"${CMD_TIMER[0]}") ))
}

coproc CMD_TIMER ( while read; do echo $SECONDS; done )
echo '' >&"${CMD_TIMER[1]}" # For value to be ready on first PS1 expansion
export PS0="\$(echo '' >&${CMD_TIMER[1]})"
export PS1="[ \$(cmd_timer) ] \$"

이것은 .bashrc 준비된 스 니펫. 특히 사용하는 모든 사람에게 유용합니다 undistract-me 덮어 쓰는 것 trap DEBUG 자체 목적을 위해.

PS1에 A를 넣는 것이 효과가 있습니까?

경과 시간을주지는 않지만 필요한 경우 시간을 빼기에 충분히 쉽습니다.

$ export PS1='[\t] [\w]\$ '
[14:22:30] [/bin]$ sleep 10
[14:22:42] [/bin]$

그가 이미 t를 사용하고 있다는 OP의 의견에 따라. Bash 대신 TCSH를 사용할 수있는 경우 시간 변수를 설정할 수 있습니다.

/bin 1 > set time = 0
/bin 2 > sleep 10
0.015u 0.046s 0:10.09 0.4%      0+0k 0+0io 2570pf+0w
/bin 3 >

인쇄 형식을 덜 추악하게 변경할 수 있습니다 (TCSH Man Page).

/bin 4 > set time = ( 0 "last: %E" )
/bin 5 > sleep 10
last: 0:10.09
/bin 6 >

나는 Bash의 비슷한 시설을 모른다

이것은 내 버전입니다

  • 날짜를 사용하여 시간을 형식화하고 계산 일만 사용하십시오
  • 터미널 제목을 설정하십시오
  • 사용자 $ + root #에 ps1에서 $를 사용하십시오.
  • 리턴 코드 / 종료 코드를 표시합니다
  • DST를 비활성화하려면 날짜 -U를 사용하십시오
  • _foo와 같은 숨겨진 이름을 사용하십시오
_x_dt_min=1 # minimum running time to show delta T
function _x_before {
    _x_t1=${_x_t1:-$(date -u '+%s.%N')} # float seconds
}
function _x_after {
    _x_rc=$? # return code
    _x_dt=$(echo $(date -u '+%s.%N') $_x_t1 | awk '{printf "%f", $1 - $2}')
    unset _x_t1
    #_x_dt=$(echo $_x_dt | awk '{printf "%f", $1 + 86400 * 1001}') # test
    # only show dT for long-running commands
    # ${f%.*} = int(floor(f))
    (( ${_x_dt%.*} >= $_x_dt_min )) && {
        _x_dt_d=$((${_x_dt%.*} / 86400))
        _x_dt_s='' # init delta T string
        (( $_x_dt_d > 0 )) && \
            _x_dt_s="${_x_dt_s}${_x_dt_d} days + "
        # format time
        # %4N = four digits of nsec
        _x_dt_s="${_x_dt_s}$(date -u -d0+${_x_dt}sec '+%T.%4N')"
        PS1='rc = ${_x_rc}\ndT = ${_x_dt_s}\n\$ '
    } || {
        PS1='rc = ${_x_rc}\n\$ '
    }
    # set terminal title to terminal number
    printf "\033]0;%s\007" $(tty | sed 's|^/dev/\(pts/\)\?||')
}
trap '_x_before' DEBUG
PROMPT_COMMAND='_x_after'
PS1='\$ '

샘플 출력 :

$ sleep 0.5
rc = 0
$ sleep 1
rc = 0
dT = 00:00:01.0040
$ sleep 1001d
rc = 0
dT = 1001 days + 00:00:00.0713
$ false
rc = 1
$ 

여기 토마스에 대한 나의 취향이 있습니다.

용도 date +%s%3N 기본 단위로 밀리 초를 얻으려면 다음 코드를 단순화했습니다 (덜 0)

function t_now {
    date +%s%3N
}

function t_start {
    t_start=${t_start:-$(t_now)}
}

function t_stop {
    local d_ms=$(($(t_now) - $t_start))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then t_show=${h}h${m}m
    elif ((m > 0)); then t_show=${m}m${s}s
    elif ((s >= 10)); then t_show=${s}.$((ms / 100))s
    elif ((s > 0)); then t_show=${s}.$((ms / 10))s
    else t_show=${ms}ms
    fi
    unset t_start
}
set_prompt () {
t_stop
}

trap 't_start' DEBUG
PROMPT_COMMAND='set_prompt' 

그런 다음 추가하십시오 $t_show PS1에

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top