$ BASH_COMMAND 변수는 무엇입니까?


25

Bash 매뉴얼 에 따르면 환경 변수 BASH_COMMAND에는

쉘이 트랩의 결과로 명령을 실행하지 않는 한, 현재 실행 중이거나 실행 되려는 명령.

함정 코너 케이스를 제쳐두고, 올바르게 이해하면 명령을 실행할 때 변수 BASH_COMMAND에 해당 명령이 포함된다는 것을 의미합니다 . 절대적으로 그 변수는 명령 실행 후 해제 여부를 명확하지 않다 (즉, 만 있음입니다 동안 하나가이기 때문에 "명령이 주장 할 수 있지만, 명령이 아닌 한 후, 실행) 현재 실행 중이거나 되려 실행" 방금 실행 된 명령이 아닙니다 .

그러나 확인하자 :

$ set | grep BASH_COMMAND=
$ 

빈. 나는 BASH_COMMAND='set | grep BASH_COMMAND='아마 BASH_COMMAND='set'보았을 것입니다.

다른 것을 시도해 보자.

$ echo $BASH_COMMAND
echo $BASH_COMMAND
$ 

글쎄요. 명령을 실행하면 echo $BASH_COMMAND변수 BASH_COMMAND에 문자열이 포함 echo $BASH_COMMAND됩니다. 이번에는 왜 작동했지만 이전에는 작동하지 않았습니까?

년대하자 set다시 일을 :

$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

기다려 그것은 내가 그 실행될 때 설정 echo명령을, 그리고 그것을 하지 않았다 이후 해제. 그러나 set다시 실행했을 때 명령으로 설정 BASH_COMMAND 되지 않았습니다set . set여기서 얼마나 자주 명령을 실행 하더라도 결과는 동일하게 유지됩니다. 따라서 실행할 때 변수가 설정되어 echo있지만 실행할 때는 설정되어 있지 set않습니까? 보자

$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

뭐? 변수 그래서 내가 실행될 때 설정 echo $BASH_COMMAND하지만, 하지 내가 실행될 때 echo Hello AskUbuntu? 지금 차이점은 어디에 있습니까? 변수가 현재 명령 자체가 실제로 쉘이 변수를 평가하도록 할 때만 설정됩니까? 다른 것을 시도해 봅시다. 이번에는 bash 내장이 아닌 외부 명령으로 변경을 시도했을 수 있습니다.

$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$

흠, 좋아 ... 다시 변수가 설정되었습니다. 내 현재 추측이 맞습니까? 변수를 평가해야 할 때만 설정됩니까? 왜? 왜? 성능상의 이유로? 한 번 더 해보자. 우리는 $BASH_COMMAND파일에서 grep을 시도 할 것이고 , $BASH_COMMAND그 후 grep명령 을 포함해야 하고 , grepgrep명령을 위해 grep해야합니다 (즉, 그 자체로). 적절한 파일을 만들어 봅시다 :

$ echo -e "1 foo\n2 grep\n3 bar\n4 grep \$BASH_COMMAND tmp" > tmp
$ grep $BASH_COMMAND tmp
grep: $BASH_COMMAND: No such file or directory
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
$ set | grep BASH_COMMAND=
BASH_COMMAND='grep --color=auto $BASH_COMMAND tmp'
$

좋아, 흥미 롭군 명령 grep $BASH_COMMAND tmp이 확장되었습니다 grep grep $BASH_COMMAND tmp tmp(변수는 물론 한 번만 확장 됩니다) . 존재하지 않는 grep파일에서 한 $BASH_COMMAND번, 파일에서 두 번 grepp했습니다 tmp.

Q1 : 현재의 가정은 다음과 같이 정확합니까?

  • BASH_COMMAND명령이 실제로 평가하려고 할 때만 설정됩니다. 과
  • 비록 설명이 우리를 믿게 할지라도 명령을 실행 한 후에 는 설정 되지 않습니다 .

Q2 : 그렇다면 왜 그렇습니까? 공연? 그렇지 않다면, 위의 명령 순서의 동작을 어떻게 설명 할 수 있습니까?

Q3 : 마지막으로이 변수를 실제로 의미있게 사용할 수있는 시나리오가 있습니까? 나는 실제로 내에서 사용하려고했던 $PROMPT_COMMAND때문에 빨리 내에서 같이 실행되는 명령을 분석 (어떤 물건이에 따라 작업을 수행) 할 수 있지만, 그럴 수 없어 $PROMPT_COMMAND, 내가 변수를보고 명령을 실행 $BASH_COMMAND변수 해당 명령으로 설정합니다. 할당이 명령이기 때문에 MYVARIABLE=$BASH_COMMAND내 시작 부분에서 바로 할 때도 문자열 $PROMPT_COMMANDMYVARIABLE포함합니다 MYVARIABLE=$BASH_COMMAND. (이 질문은 $PROMPT_COMMAND실행 내에서 현재 명령을 얻는 방법에 관한 것이 아닙니다 . 다른 방법이 있습니다.)

하이젠 베르크의 불확실성 원리와 약간 비슷합니다. 변수를 관찰하면 변경됩니다.


5
좋았지 만 아마도 unix.stackexchange.com에 더 적합 할 것입니다 ... 실제 우버bash 전문가가 있습니다.
Rmano

글쎄, 저쪽으로 옮길 수 있습니까? 개조?
Malte Skoruppa

어떻게해야할지 잘 모르겠습니다 --- Mod 권한이라고 생각합니다. 다른 한편으로는 플래그를 지정하는 것이 합리적이라고 생각하지 않습니다.
Rmano

1
세 번째 점의 경우, 이것은 당신이 검색하는 것입니다. 아마도 그 기사를 기반으로 처음 두 지점에 대한 답을 찾을 수도 있습니다.
Radu Rădeanu

2
+1 도덕적으로 혼란 스러웠지만 읽는 것이 재미있었습니다!
Joe

답변:


15

세 번째 질문에 대한 답변 : 물론 Bash 매뉴얼에서 힌트와 같은 방식으로 의미있게 사용될 수 있습니다.

$ trap 'echo ‘$BASH_COMMAND’ failed with error code $?' ERR
$ fgfdjsa
fgfdjsa: command not found
fgfdjsa failed with error code 127
$ cat /etc/fgfdjsa
cat: /etc/fgfdjsa: No such file or directory
cat /etc/fgfdjsa failed with error code 1

아, 참 좋습니다. 트랩이이 변수가 의미있는 유일한 컨텍스트라고 말할 수 있습니까? 매뉴얼에서 코너 케이스처럼 들렸습니다. " 쉘이 트랩의 결과로 명령을 실행하지 않는 한 명령이 실행 중입니다 ..."
Malte Skoruppa

@DocSalvager의 답변에 연결된 기사를 읽은 후에 $BASH_COMMAND실제로 트랩 이외의 컨텍스트에서도 의미있게 사용될 수 있음이 분명합니다 . 그러나, 당신이 묘사하는 사용은 아마도 가장 일반적이고 간단합니다. 따라서 귀하의 답변과 DocSalvager의 답변이 내 Q3에 가장 잘 응답 하며 이것이 가장 중요했습니다. @zwets로 표시되는 Q1 및 Q2의 경우 이러한 사항이 정의되지 않았습니다. $BASH_COMMAND성능을 위해 액세스 한 경우에만 값이 주어질 수 있습니다. 그렇지 않으면 이상한 내부 프로그램 조건이 해당 동작을 유발할 수 있습니다. 누가 알아?
Malte Skoruppa

1
각주에서, 나는 당신 각 명령 전에 $BASH_COMMAND평가를 강제함으로써 항상 강제 로 설정 될 있음을 발견했습니다 $BASH_COMMAND. 이를 위해 DEBUG 트랩을 사용할 수 있습니다. DEBUG 트랩은 모든 단일 명령 (모든 em) 전에 실행됩니다. 우리가 실행하는 경우, 예를 들어, trap 'echo "$BASH_COMMAND" > /dev/null' DEBUG다음, $BASH_COMMAND항상 각 명령 앞에 평가 (그 값을 할당됩니다 $COMMAND). set | grep BASH_COMMAND=트랩이 활성화 된 상태에서 실행하면 무엇을 알고 있습니까? BASH_COMMAND=set예상대로 출력은 다음 과 같습니다 :)
Malte Skoruppa

6

이제 Q3가 정답에 도달했습니다 (정확하게는 제 생각으로 BASH_COMMAND는 트랩에 유용하고 다른 곳에서는 거의 사용되지 않습니다).

Q1에 대한 답은 가정의 정확성이 결정 불가능하다는 것입니다. 그들이 불특정 한 행동에 대해 물었을 때 총알의 진실은 확립 될 수 없다. 사양에 따라의 값 BASH_COMMAND은 해당 명령이 실행되는 동안 명령의 텍스트로 설정됩니다. 스펙은 다른 상황, 즉 명령이 실행되지 않을 때 그 값이 무엇인지 명시하지 않습니다. 값이 있거나 전혀 없을 수 있습니다.

Q2에 대한 답변 "아니라면 위의 명령 시퀀스의 동작을 어떻게 설명 할 수 있습니까?" 그런 다음 논리적으로 (약간 비현실적이라면) 따라 BASH_COMMAND갑니다. 값이 정의되어 있지 않기 때문에 시퀀스에 표시되는 값을 가질 수 있습니다.

추신

실제로 스펙에서 소프트 스팟을 타격한다고 생각하는 지점이 있습니다. 당신이 말하는 곳 :

$ PROMPT_COMMAND의 시작 부분에서 MYVARIABLE = $ BASH_COMMAND를 수행하더라도 할당도 명령이기 때문에 MYVARIABLE에는 MYVARIABLE = $ BASH_COMMAND 문자열이 포함 됩니다 .

내가 bash 맨 페이지를 읽는 방식은 기울임 꼴로 표시되지 않습니다. 이 섹션에서는 SIMPLE COMMAND EXPANSION명령 줄에서 변수 할당을 먼저 설정 한 다음 설명합니다.

명령 이름이 없으면 (즉, 변수 지정 만있는 경우) 변수 지정은 현재 쉘 환경에 영향을줍니다.

이것은 변수 할당이 BASH_COMMAND다른 프로그래밍 언어에서와 같이 명령이 아니므로 (에 표시되지 않음) 제안합니다 . 이것은 또한 BASH_COMMAND=set의 출력에 왜 라인이 없는지 설명 set하고 set본질적으로 변수 할당에 대한 구문 '마커'입니다.

OTOH, 해당 섹션의 마지막 단락에서

확장 후에 명령 이름이 남아 있으면 다음과 같이 실행이 진행됩니다. 그렇지 않으면 명령이 종료됩니다.

... 그렇지 않으면 제안하고 변수 할당도 명령입니다.


1
어떤 가정을 할 수 없다고해서 그것이 틀렸다는 의미는 아닙니다. 아인슈타인은 빛의 속도가 상대성 이론에 대한 하나의 기본 가설과 같이 어떤 속도에서든 모든 관찰자에 대해 같다고 가정했다. 그것은 확립 될 수 없지만 이것이 잘못되었다는 것을 의미하지는 않습니다. "설정 가능"및 "정확한"특성은 직교입니다. 기껏해야 "우리는 그것이 확립 될 수 없기 때문에 그것이 정확한지 모른다"고 말할 수 있습니다. 또한,이 되어 지정된 : 그것은 실행하는 동안 현재의 명령입니다. 내가 타이핑 하면 출력의 어딘가에 set표시되어야합니다.BASH_COMMAND='set'
Malte Skoruppa

...하지만 그렇지 않습니다. 비록 그것이 명령을 실행하는 동안set 입니다. 따라서 사양에 따라 작동해야합니다. 구현이 사양에 충실하게 따르지 않습니까, 아니면 사양을 오해합니까? 그 질문에 대한 답을 찾는 것은 Q1의 목적 중 하나입니다. 포스트 스크립트 +1
Malte Skoruppa

@MalteSkoruppa 좋은 지적. 이에 따라 답변을 수정하고에 대한 설명을 추가했습니다 set.
zwets

1
bash 인터프리터에서 set"명령"이 아닐 수도 있습니다. ="명령"이 아닌 것처럼 . 해당 토큰 다음 / 서라운드 텍스트 처리는 "명령"처리와 완전히 다른 논리를 가질 수 있습니다.
DocSalvager

둘 다 좋은 점. :) set"명령"으로 간주되지 않을 수도 있습니다 . $BASH_COMMAND많은 상황에서 그렇게 많이 지정 되지 않은 것으로 생각되지 않았습니다 . 나는 최소한 맨 페이지가 분명히 더 명확 해 질 있다고 생각했다.)
Malte Skoruppa

2

$ BASH_COMMAND에 대한 독창적 인 사용

최근 에 매크로와 같은 기능을 구현할 때 $ BASH_COMMAND인상적으로 사용 되었습니다.

이것은 별칭의 핵심 트릭이며 DEBUG 트랩 사용을 대체합니다. 이전 게시물에서 DEBUG 트랩에 대한 부분을 읽으면 $ BASH_COMMAND 변수를 인식하게됩니다. 그 게시물에서 DEBUG 트랩을 호출하기 전에 명령 텍스트로 설정되었다고 말했습니다. 글쎄, 그것은 모든 명령, DEBUG 트랩 또는 no (예 : 'echo“this command = $ BASH_COMMAND”'를 실행하여 내가 무엇을 말하는지 확인하기 전에) 전에 실행 된 것으로 나타났습니다. 변수를 (해당 행에 대해서만) 할당하면 명령의 가장 바깥 쪽 범위에서 BASH_COMMAND를 캡처하는데 여기에는 전체 명령이 포함됩니다.

필자의 이전 기사 는 DEBUG를 사용하여 기술을 구현하는 동안 좋은 배경 지식을 제공합니다 trap. 는 trap향상된 버전에서 제거된다.


+1 마침내 그 두 기사를 읽었습니다. 와우! 이거 읽어! 매우 깨달음. 그 남자는 배쉬 전문가입니다 ! 명성! 이것은 또한 $BASH_COMMAND이외의 상황에서 의미있게 사용될 수 있는지에 대한 Dmitry의 답변에 대한 나의 의견에 대한 답변 trap입니다. 그리고 그것은 얼마나 사용입니까! 이것을 사용하여 bash에서 매크로 명령을 구현하십시오. 누가 가능하다고 생각했을까요? 포인터 주셔서 감사합니다.
Malte Skoruppa

0

trap ... debug의 일반적인 사용은 "screen"을 사용할 때 windowlist (^ A ")에 나타나는 제목을 향상시키는 것입니다.

"스크린", "윈도우 목록"을보다 유용하게 만들려고했기 때문에 "trap ... debug"를 참조하는 기사를 찾기 시작했습니다.

"널 제목 시퀀스"를 전송하기 위해 PROMPT_COMMAND를 사용하는 메소드가 제대로 작동하지 않음을 발견하여 trap ... debug 메소드로 되돌 렸습니다.

방법은 다음과 같습니다.

1 "shelltitle '$ | bash :'"를 "$ HOME / .screenrc"에 넣어서 "screen"에게 이스케이프 시퀀스를 찾도록합니다 (활성화).

2 디버그 트랩이 하위 쉘로 전파되는 것을 끕니다. 활성화 된 경우 모든 것이 막혀 "set + o functrace"를 사용하기 때문에 이것은 중요합니다.

3 "screen"의 제목 이스케이프 시퀀스를 해석하여 다음을 해석하십시오. trap 'printf "\ ek $ (date + % Y % m % d % H % M % S) $ (whoami) @ $ (hostname) : $ (pwd) $ {BASH_COMMAND} \ e \ " '"DEBUG "

완벽하지는 않지만 도움이 되며이 방법을 사용하여 원하는대로 원하는 것을 제목에 넣을 수 있습니다

다음 "윈도우 목록"(5 개 화면)을 참조하십시오.

숫자 이름 플래그

1 bash : 20161115232035 mcb @ ken007 : / home / mcb / ken007 RSYNCCMD = "sudo rsync"myrsync.sh -R -r "$ {1}" "$ {BACKUPDIR} $ {2 : +"/ $ {2} " } "$ 2 bash : 20161115230434 mcb @ ken007 : / home / mcb / ken007 ls --color = auto -la $ 3 bash : 20161115230504 mcb @ ken007 : / home / mcb / ken007 고양이 bin / psg.sh $ 4 bash : 20161115222415 mcb @ ken007 : / home / mcb / ken007 ssh ken009 $ 5 bash : 20161115222450 mcb @ ken007 : / home / mcb / ken007 mycommoncleanup $

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.