Bash에서 실행 된 마지막 명령을 반향합니까?
bash 스크립트 내에서 실행 된 마지막 명령을 에코하려고합니다. history,tail,head,sed
명령이 파서 관점에서 스크립트의 특정 줄을 나타낼 때 잘 작동 하는 일부 작업 을 수행하는 방법을 찾았습니다 . 그러나 어떤 상황에서는 명령이 case
명령문 안에 삽입되는 경우와 같이 예상되는 출력을 얻지 못합니다 .
스크립트 :
#!/bin/bash
set -o history
date
last=$(echo `history |tail -n2 |head -n1` | sed 's/[0-9]* //')
echo "last command is [$last]"
case "1" in
"1")
date
last=$(echo `history |tail -n2 |head -n1` | sed 's/[0-9]* //')
echo "last command is [$last]"
;;
esac
출력 :
Tue May 24 12:36:04 CEST 2011
last command is [date]
Tue May 24 12:36:04 CEST 2011
last command is [echo "last command is [$last]"]
[Q] 누군가가 bash 스크립트 내에서이 명령이 호출되는 방법 / 위치에 관계없이 마지막 실행 명령을 에코하는 방법을 찾도록 도와 줄 수 있습니까?
내 대답
내 동료 SO'ers에서 많이 감사 기여에도 불구하고, 나는 쓰기를 선택했다 run
하나의 명령으로 모든 매개 변수를 실행하고 명령과 그 실패의 오류 코드를 표시 - - 기능 다음과 같은 혜택을 :
에 -I에만 필요 run
한 줄에 유지하고 스크립트의 간결성에 영향을주지 않는 확인하려는 명령을 앞에 추가합니다
.-스크립트가이 명령 중 하나에서 실패 할 때마다 스크립트의 마지막 출력 줄은 어떤 명령을 명확하게 표시하는 메시지입니다. 종료 코드와 함께 실패하므로 디버깅이 더 쉬워집니다.
예제 스크립트 :
#!/bin/bash
die() { echo >&2 -e "\nERROR: $@\n"; exit 1; }
run() { "$@"; code=$?; [ $code -ne 0 ] && die "command [$*] failed with error code $code"; }
case "1" in
"1")
run ls /opt
run ls /wrong-dir
;;
esac
출력 :
$ ./test.sh
apacheds google iptables
ls: cannot access /wrong-dir: No such file or directory
ERROR: command [ls /wrong-dir] failed with error code 2
여러 인수, bash 변수를 인수로, 따옴표로 묶은 인수로 다양한 명령을 테스트 run
했는데 함수가이를 깨뜨리지 않았습니다. 지금까지 내가 찾은 유일한 문제는 깨지는 에코를 실행하는 것이지만 어쨌든 에코를 확인할 계획은 없습니다.
명령 기록은 대화 형 기능입니다. 기록에는 완전한 명령 만 입력됩니다. 예를 들어, case
쉘이 구문 분석을 완료 하면 구성이 전체로 입력됩니다. history
내장 된 히스토리를 조회 하지도 (쉘 확장을 통해 인쇄하지도 않음 ( !:p
)) 단순한 명령 호출을 인쇄하는 것이 원하는대로 수행되지 않습니다.
DEBUG
트랩은 당신이 어떤 간단한 명령을 실행하기 전에 명령 권리를 실행할 수 있습니다. 실행할 명령의 문자열 버전 (공백으로 구분 된 단어 포함)을 BASH_COMMAND
변수 에서 사용할 수 있습니다 .
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
참고 previous_command
, 당신이 명령을 실행할 때마다 변경 그래서 그것을 사용하기 위해 변수에 저장합니다. 이전 명령의 반환 상태도 알고 싶다면 둘 다 단일 명령으로 저장하십시오.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
또한 실패한 명령 만 중단하려면 set -e
을 사용 하여 첫 번째 실패한 명령에서 스크립트를 종료하십시오. EXIT
트랩 의 마지막 명령을 표시 할 수 있습니다 .
set -e
trap 'echo "exit $? due to $previous_command"' EXIT
스크립트가 무엇을하는지보기 위해 스크립트를 추적하려는 경우이 모든 것을 잊어 버리고 set -x
.
Bash에는 실행 된 마지막 명령에 액세스하는 기능이 내장되어 있습니다. 그러나 이것은 case
당신이 원래 요청한 것과 같은 개별적인 간단한 명령이 아니라 마지막 전체 명령 (예 : 전체 명령)입니다.
!:0
= 실행 된 명령의 이름.
!:1
= 이전 명령의 첫 번째 매개 변수
!:*
= 이전 명령의 모든 매개 변수
!:-1
= 이전 명령의 마지막 매개 변수
!!
= 이전 명령 줄
기타
따라서 질문에 대한 가장 간단한 대답은 실제로 다음과 같습니다.
echo !!
... 또는 :
echo "Last command run was ["!:0"] with arguments ["!:*"]"
직접 시도해보십시오!
echo this is a test
echo !!
스크립트에서 히스토리 확장은 기본적으로 꺼져 있으며 다음을 사용하여 활성화해야합니다.
set -o history -o histexpand
Gilles 의 답변 을 읽은 후 트랩 에서 var도 사용할 수 있는지 (및 원하는 값) 확인하기로 결정했습니다 .$BASH_COMMAND
EXIT
따라서 다음 bash 스크립트는 예상대로 작동합니다.
#!/bin/bash
exit_trap () {
local lc="$BASH_COMMAND" rc=$?
echo "Command [$lc] exited with code [$rc]"
}
trap exit_trap EXIT
set -e
echo "foo"
false 12345
echo "bar"
출력은
foo
Command [false 12345] exited with code [1]
bar
is never printed because set -e
causes bash to exit the script when a command fails and the false command always fails (by definition). The 12345
passed to false
is just there to show that the arguments to the failed command are captured as well (the false
command ignores any arguments passed to it)
I was able to achieve this by using set -x
in the main script (which makes the script print out every command that is executed) and writing a wrapper script which just shows the last line of output generated by set -x
.
This is the main script:
#!/bin/bash
set -x
echo some command here
echo last command
And this is the wrapper script:
#!/bin/sh
./test.sh 2>&1 | grep '^\+' | tail -n 1 | sed -e 's/^\+ //'
Running the wrapper script produces this as output:
echo last command
history | tail -2 | head -1 | cut -c8-999
tail -2
returns the last two command lines from history head -1
returns just first line cut -c8-999
returns just command line, removing PID and spaces.
There is a racecondition between the last command ($_) and last error ( $?) variables. If you try to store one of them in an own variable, both encountered new values already because of the set command. Actually, last command hasn't got any value at all in this case.
Here is what i did to store (nearly) both informations in own variables, so my bash script can determine if there was any error AND setting the title with the last run command:
# This construct is needed, because of a racecondition when trying to obtain
# both of last command and error. With this the information of last error is
# implied by the corresponding case while command is retrieved.
if [[ "${?}" == 0 && "${_}" != "" ]] ; then
# Last command MUST be retrieved first.
LASTCOMMAND="${_}" ;
RETURNSTATUS='✓' ;
elif [[ "${?}" == 0 && "${_}" == "" ]] ; then
LASTCOMMAND='unknown' ;
RETURNSTATUS='✓' ;
elif [[ "${?}" != 0 && "${_}" != "" ]] ; then
# Last command MUST be retrieved first.
LASTCOMMAND="${_}" ;
RETURNSTATUS='✗' ;
# Fixme: "$?" not changing state until command executed.
elif [[ "${?}" != 0 && "${_}" == "" ]] ; then
LASTCOMMAND='unknown' ;
RETURNSTATUS='✗' ;
# Fixme: "$?" not changing state until command executed.
fi
This script will retain the information, if an error occured and will obtain the last run command. Because of the racecondition i can not store the actual value. Besides, most commands actually don't even care for error noumbers, they just return something different from '0'. You'll notice that, if you use the errono extention of bash.
It should be possible with something like a "intern" script for bash, like in bash extention, but i'm not familiar with something like that and it wouldn't be compatible as well.
CORRECTION
I didn't think, that it was possible to retrieve both variables at the same time. Although i like the style of the code, i assumed it would be interpreted as two commands. This was wrong, so my answer devides down to:
# Because of a racecondition, both MUST be retrieved at the same time.
declare RETURNSTATUS="${?}" LASTCOMMAND="${_}" ;
if [[ "${RETURNSTATUS}" == 0 ]] ; then
declare RETURNSYMBOL='✓' ;
else
declare RETURNSYMBOL='✗' ;
fi
Although my post might not get any positive rating, i solved my problem myself, finally. And this seems appropriate regarding the intial post. :)
참고URL : https://stackoverflow.com/questions/6109225/echoing-the-last-command-run-in-bash
'developer tip' 카테고리의 다른 글
Twitter Bootstrap으로 테이블에 스타일 적용 (0) | 2020.10.25 |
---|---|
GitHub 커밋은 'Your Contributions'캘린더에 기록되지 않습니다. (0) | 2020.10.25 |
속성 또는 인덱서는 out 또는 ref 매개 변수로 전달 될 수 없습니다. (0) | 2020.10.25 |
PHP를 사용하여 JSON 게시물 보내기 (0) | 2020.10.25 |
쉼표 천 단위 구분 기호가있는 문자열을 숫자로 구문 분석하려면 어떻게해야합니까? (0) | 2020.10.25 |