![PS1 프롬프트에 경과 시간이 표시됩니다.](https://linux55.com/image/80418/PS1%20%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8%EC%97%90%20%EA%B2%BD%EA%B3%BC%20%EC%8B%9C%EA%B0%84%EC%9D%B4%20%ED%91%9C%EC%8B%9C%EB%90%A9%EB%8B%88%EB%8B%A4..png)
현재 이것을 사용하여 bash 프롬프트에 현재 시간을 표시합니다.
PS1=\[\e[0;32m\]\t \W>\[\e[1;37m\]
20:42:23 ~>
마지막 프롬프트 이후 경과된 시간을 표시할 수 있습니까? 예를 들어:
00:00:00 ~> sleep 10
00:00:10 ~> sleep 20
00:00:20 ~>
이는 다음과 관련이 있습니다.백그라운드 스크립트를 통해 주기적으로 PS1을 변경할 수 있습니까?
답변1
한 가지 접근 방식은 bash의 PROMPT_COMMAND 함수를 사용하여 PS1을 수정하는 코드를 실행하는 것입니다. 아래 함수는 원래 제출한 것의 업데이트된 버전입니다. 이 함수는 두 개의 더 적은 환경 변수를 사용하고 기존 변수가 손상되지 않도록 "_PS1_" 접두사를 붙입니다.
prompt_command() {
_PS1_now=$(date +%s)
PS1=$( printf "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
$(( ( _PS1_now - _PS1_lastcmd ) / 3600)) \
$(( (( _PS1_now - _PS1_lastcmd ) % 3600) / 60 )) \
$(( ( _PS1_now - _PS1_lastcmd ) % 60)) \
)
_PS1_lastcmd=$_PS1_now
}
PROMPT_COMMAND='prompt_command'
_PS1_lastcmd=$(date +%s)
시작하려면 .bash_profile에 넣으세요.
프롬프트 매개변수와 일치하도록 매개변수를 빨리 입력해야 한다는 점에 유의하십시오 sleep
. 시간은 실제로 명령을 입력하는 데 걸리는 시간을 포함하여 프롬프트 간의 차이입니다.
00:00:02 ~> sleep 5 ## here I typed really quickly
00:00:05 ~> sleep 3 ## here I took about 2 seconds to enter the command
00:00:10 ~> sleep 30 ## more slow typing
00:01:35 ~>
나중에 추가된 내용:
현재 삭제된 @Cyrus의 답변을 바탕으로 추가 변수로 환경을 복잡하게 만들지 않는 버전은 다음과 같습니다.
PROMPT_COMMAND='
_prompt(){
PROMPT_COMMAND="${PROMPT_COMMAND%-*}-$SECONDS))\""
printf -v PS1 "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
"$(($1/3600))" "$((($1%3600)/60))" "$(($1%60))"
}; _prompt "$((SECONDS'"-$SECONDS))\""
추가 늦은 추가 사항:
Bash 버전 4.2부터 시작( echo $BASH_VERSION
), date
새로운 printf 형식 문자열을 사용하여 외부 호출을 방지할 $(date +%s)
수 있습니다 $(printf '%(%s)T' -1)
.버전 4.3부터-1
, "인수가 없음을 의미함"에 의존하기 위해 인수를 생략할 수 있습니다.지금" 행동.
답변2
PS1[3]=$SECONDS
PS1='${PS1[!(PS1[1]=!1&(PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600))
]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]/60%60), ${PS1[3]})):${PS1[1
]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]%60), ${PS1[3]})):${PS1[1
]#${PS1[3]%%*??}0}$((PS1[3]=(SECONDS), ${PS1[3]})):'$PS1
이는 서식을 계산적으로 처리하므로 몇 번 확장되지만 하위 쉘이나 파이프는 수행되지 않습니다.
단지 이를 $PS1
배열로 취급하고 더 높은 인덱스를 사용하여 프롬프트 사이에 필요한 모든/필요한 상태를 저장/계산합니다. 다른 쉘 상태에는 영향을 주지 않습니다.
00:00:46:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:00:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
00:00:15:[mikeserv@desktop tmp]$
00:00:15:[mikeserv@desktop tmp]$
00:00:02:[mikeserv@desktop tmp]$
00:02:27:[mikeserv@desktop tmp]$
조금 쪼개어 볼 수도 있겠네요...
먼저 현재 값을 저장합니다 $SECONDS
.
PS1[3]=$SECONDS
다음으로, 항상 올바른 값을 설정하는 동시에 자체 참조를 만드는 $PS1[0]
방식으로 자체 재귀를 정의합니다 . $PS1[1-3]
이 부분을 얻으려면 쉘 수학 표현식이 평가되는 순서를 고려해야 합니다. 가장 중요한 것은 쉘 수학이 항상 쉘 수학의 마지막 작업이라는 것입니다. 먼저, 쉘은 값을 확장합니다. 이 방법으로 할당을 사용한 후 수학 표현식에서 쉘 변수의 이전 값을 참조할 수 있습니다 $
.
먼저 간단한 예를 들어보겠습니다.
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
쉘은 먼저 참조된 위치 값을 달러 기호로 대체하여 $x
명령문을 평가 하므로 $
표현식은 다음과 같습니다.
(x+=5)+10+x
...쉘은 값에 5를 더한 다음 참조 변수에 실제 할당된 값만 유지하면서 $x
전체 표현식을 로 확장합니다 . x+10+x
따라서 수학적 표현의 확장된 값은 40이지만 최종 값은 $x
15입니다.
이는 $PS1
주로 방정식이 작동하는 방식이지만 배열 인덱싱에 활용되는 추가 수학적 확장/평가가 필요합니다.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
내가 왜 거기를 사용하기로 선택했는지 잘 모르겠습니다 PS1[1]=!1
. 아마도 어리석은 미학일 것 같습니다. 그러나 $PS1[1]
매개변수 대체를 위해 확장할 때 0이 할당됩니다. 0의 비트 AND 값과 다른 값은 항상 0이 되지만, &&
가장 왼쪽의 기본 값이 0이면 부울 값처럼 단락되지 않으므로 대괄호 표현식은 매번 평가됩니다. 물론 첫 번째 줄임표가 $PS1[2,3]
초기 값이 설정되는 위치이기 때문에 이것이 중요합니다.
그럼에도 불구하고 $PS1[1]
프롬프트 추첨 사이에 조작되더라도 여기서는 0이 보장됩니다. 괄호 안에는...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
$PS1[2]
... 합계의 차이가 할당 되고 해당 값과 3600의 몫이 할당됩니다. 모든 값은 여기에서 초기화됩니다. 그래서:$PS1[3]
$SECONDS
$PS1[3]
${PS1[1]#${PS1[3]%%*??}0}
...두 자리 이상이면 내부적으로 null로 확장되고, 0이라는 것을 $PS1[3]
알고 있으므로 if 를 null로 대체할 수 있으므로 else도 해당 값으로 확장할 수 있습니다. 이러한 방식으로 할당 반복당 단일 숫자 값만 선행 0으로 확장되고 자체적으로 모듈로 60으로 즉시 확장되는 동시에 각 시간, 분, 초에 다음 연속 작은 값이 할당됩니다.$PS1[1]
$PS1[3]
$PS1[1]
$PS1[3]
$PS1[3]
$PS1[3]
다음에 팁을 그릴 때 $SECONDS
다시 비교할 수 있도록 마지막 반복을 현재 값으로 덮어쓸 때까지 헹구고 반복합니다 .$SECONDS
답변3
지금까지 내가 찾은 최고의 솔루션은 다음과 같습니다.https://github.com/jichu4n/bash-command-timer
명령을 실행한 후 오른쪽에 경과 시간이 인쇄 되므로 [ 1s011 | May 25 15:33:44 BST ]
PS1이 복잡해지지 않습니다.
전체 문자열과 시간 형식을 구성할 수 있습니다. 색상과 정밀도도 구성 가능합니다. 일부 미니멀리스트에게는 이것이 다소 과할 수도 있다는 것을 알고 있지만 꽤 멋집니다.
답변4
Bash 이후 매우 가능함4.4PS0
, 환경 변수를 소개합니다 .
export PS0='$(date +%s%03N > ~/.execStart.$$)'
printElapsedCommandTime () {
local execStart execEnd execDur elaStr
if [ -e ~/.execStart.$$ ]; then
read execStart < ~/.execStart.$$ 2>/dev/null
rm -f ~/.execStart.$$
if [ -n "$execStart" ]; then
execEnd=`date +%s%03N`
execDur=$((execEnd-execStart))
printf -v elaStr "Ela %u.%03u" $((execDur / 1000)) $((execDur % 1000))
printf "%*s\e[32;7m%s\e[0m\n" $((COLUMNS-${#elaStr})) "" "$elaStr"
fi
fi
}
export PROMPT_COMMAND='printElapsedCommandTime'
PS0
( 디스플레이뒤쪽에Bash는 명령을 읽었지만앞으로Bash가 실행을 시작했습니다.) 출력을 임시 파일에 저장합니다 date +%s%03N
. 이는 에포크 초와 나노초의 처음 3자리입니다. 전체적인 효과는 에포크 마이크로초를 저장하는 것입니다.
PROMPT_COMMAND
(평가 하다뒤쪽에Bash가 명령 실행을 완료했지만앞으로Bash는 기본 프롬프트를 표시했습니다 PS1
. 다시 Epoch 마이크로초를 찾아 임시 파일에 저장된 측정값을 뺍니다.
경과 시간은 오른쪽의 별도 줄에 표시됩니다. 낮은 수준은 printf
조금 더 까다롭습니다.
- 형식 지정자
%*s
소비둘매개변수, 정수 및 문자열. 전자는 후자를 인쇄할 때 사용할 열 수를 나타냅니다. 우리가 제공하는 두 개의 매개변수는 N =$((COLUMNS-${#elaStr}))
이고 빈 문자열은""
N 공백을 인쇄하는 것입니다. \e[32;7m
7
녹색(" "32
) 배경의 역상 비디오(" ") 텍스트를 요청합니다.%s
우리 문자열을 소비하는 것입니다$elaStr
.\e[0m
글꼴 색상을 일반 색상으로 재설정합니다.
불다5.0EPOCHREALTIME
두 번 호출하는 것을 방지하는 환경 변수가 도입되었습니다 date(1)
. EPOCHREALTIME
는 마이크로초 단위의 소수 초입니다. .
제거하면 와 동일한 출력이 되므로 date +%s%03N
개선된 솔루션을 얻으려면 두 가지 작은 변경만 하면 됩니다.
export PS0='echo ${EPOCHREALTIME/./} > ~/.execStart.$$)' ### change here...
printElapsedCommandTime () {
local execStart execEnd execDur elaStr
if [ -e ~/.execStart.$$ ]; then
read execStart < ~/.execStart.$$ 2>/dev/null
rm -f ~/.execStart.$$
if [ -n "$execStart" ]; then
execEnd=`${EPOCHREALTIME/./} ### ...and here
execDur=$((execEnd-execStart))
printf -v elaStr "Ela %u.%03u" $((execDur / 1000)) $((execDur % 1000))
printf "%*s\e[32;7m%s\e[0m\n" $((COLUMNS-${#elaStr})) "" "$elaStr"
fi
fi
}
export PROMPT_COMMAND='printElapsedCommandTime'