bash 파일에서 터미널 기록을 파일로 저장하는 방법은 무엇입니까?


7

터미널 기록을 hist.txt라는 파일에 저장하는 bash 스크립트를 만들려고합니다. 사용 history > hist.txt은 bash 스크립트에서 작동하지 않는 것 같지만 명령 줄에서 실행될 때 정상적으로 작동합니다.

모든 안내는 대단히 감사합니다.

주디 감사합니다


3
귀하의 질문은 약간 혼란 스럽습니다. "bash 파일에서는 작동하지 않지만 명령 행에서 실행될 때 제대로 작동합니다"는 무슨 뜻입니까? 실행중인 bash 스크립트에서 명령 기록을 저장하려고한다는 의미입니까? 스크립트에서 실행 한 명령을 저장 하시겠습니까? 이 경우 스크립트 자체는 역사입니다.
Stephen

6
아니면 특정 사용자의 bash 기록을 출력 하시겠습니까? 사용자 ~/.bash_history파일을 읽을 수 있습니다.
Arronical

1
@Arronical은 사용자가 Bash를 쉘로 사용하는 경우에만 작동하며 항상 그런 것은 아닙니다.

1
@ p0llard 물론, Bash 스크립트에서와 마찬가지로 Bash가 사용자의 셸로 사용된다는 가정하에 뛰어 들었습니다.하지만 말한 것처럼 그렇지 않을 수도 있습니다. 귀하의 답변 BTW에 좋은 세부 사항 및 배경.
Arronical

답변:


11

짧은 답변

source또는로 스크립트를 실행하십시오 ..

source ./script_name.sh

또는

. ./script_name.sh

후자는 다른 쉘에서 약간 더 호환됩니다.

긴 답변

이 질문은 쉘 스크립트가 자체 컨텍스트에서 실행된다는 중요한 점을 강조합니다. 이것이 무엇을 의미하는지 보려면 다음 쉘 스크립트를 고려하십시오.

#!/bin/bash

cd /
ls

이것을 실행하면 다음과 같은 출력이 나타납니다.

bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

그러나 스크립트를 실행 한 후에도 스크립트를 실행하기 전의 디렉토리에 여전히 cd /있습니다. 스크립트 내부는 실제로 세션에 영향을 미치지 않았습니다. 스크립트가 실행중인 컨텍스트에만 영향을 미쳤습니다. 스크립트가 실행될 수 있도록 생성되고 일단 반환되면 파괴됩니다.

source명령은 '현재 쉘 컨텍스트의 filename 인수에서 명령을 읽고 실행'하므로 cd내부 와 같은 명령은 현재 세션에 영향을 미칩니다. 위의 스크립트를 전달하여 실행 source하면 루트 디렉토리가 실행 된 후에 종료됩니다.

이 경우 문제는 history명령이 현재 쉘 컨텍스트의 히스토리를 제공한다는 것입니다. 스크립트를 사용하지 않고 실행하는 쉘 컨텍스트 source에는 히스토리가 없으므로 출력 파일에 아무것도 쓰지 않습니다. 사용 source하면 올바른 컨텍스트에서 실행되고 예상대로 작동합니다.

NB가 : source쉘 내장되어 아니라 프로그램 자체 - 배쉬에서, source대명사 .,하지만 일부 껍질 만이 .작동합니다 - 내가 사용했던 source이보다 쉽게 읽을 때문에이 답변에 .있지만, 최대의 호환성을 위해 .해야 사용하십시오.


매우 흥미로운 읽기. 나는 항상 '사라진'히스토리 명령에 대해 궁금해했지만 이제는 이유를 알고 있습니다. 감사!
Tico

10

우선, 당신의 역사는 이미 파일에 있습니다. bash를 실행하는 경우 일반적으로 이름은 ~/.bash_history입니다. 보다 구체적으로, 변수 HISTFILE를 설정 한 모든 것 입니다. 다른 파일로 복사하려면 다음을 실행하십시오.cat "$HISTFILE" > hist.txt

이제 historybash 쉘 스크립트에서 명령이 작동하지 않는 이유는 스크립트가 현재 쉘 세션의 비 대화식 자식 쉘에서 실행되기 때문입니다. 자식 셸은 부모의 모든 환경을 상속하지 않으며 (따라서 모든 설정 변수가 아니라) 내 보낸 변수 만 상속합니다. 예를 들어 아래 스크립트는 변수 값을 에코합니다 $var.

#!/bin/bash
echo "$var"

이제 $var무언가로 설정 하고 스크립트를 실행하십시오.

$ var="foo"
$ foo.sh
VAR: 

다음으로 변수를 먼저 내 보냅니다.

$ var="foo"
$ export var
$ foo.sh
VAR: foo

보시다시피, 변수가 내보내지면 자식 셸에서 변수를 사용할 수 있습니다.

앞에서 언급했듯이 이력은 변수가 가리키는 파일에 저장됩니다 $HISTFILENAME. 기본적으로 내보내지지 않기 때문에 스크립트를 실행할 때 설정되지 않습니다.

$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history

위의 예에서 볼 수 있듯이 변수 HISTFILE는 일반 쉘 세션에서 설정되지만 스크립트를 실행할 때 비어 있습니다.

따라서 기록을 얻으려면 몇 가지 옵션이 있습니다.

  1. 기본값 HISTFILE$HOME/.bash_history입니다. 변경하지 않은 경우 스크립트에서 다음 명령을 실행하면됩니다.

    cat "$HOME/.bash_history" > history
  2. $HISTFILE변수를 스크립트에 전달하면 다음과 cat같습니다.

    #!/bin/bash
    cat "$1" > history

    위와 같이 저장 foo.sh하고 다음과 같이 실행하십시오.

    ./foo.sh "$HISTORY"
  3. 변수가 내보내 졌는지 확인하십시오. 이 줄을 ~/.bash_profile존재하는 ~/.profile경우 또는 ~/.bash_profile존재하지 않는 경우 파일에 추가하십시오.

    export HISTFILE

    그런 다음 로그 아웃했다가 다시 로그인 history > hist.txt하면 스크립트를 예상대로 실행할 수 있습니다 . 이것은 export VAR"자식 쉘에 $ VAR을 사용할 수있게" 하기 때문 입니다. 실제로, 이는 HISTFILE스크립트 실행에 사용하는 비 대화식 쉘이 값을 상속 함을 의미합니다 .

    이제는 HISTFILE설정되지만 스크립트를 실행하는 셸에서 읽지 않았습니다. 따라서 작동하게하려면 history -r먼저 읽어야합니다 . 전체 스크립트는 다음과 같습니다.

    $!/bin/bash
    history -r
    history > hist.txt

    또는 스크립트를 실행하기 전에 수동으로 내보내십시오.

    $ export HISTFILE

    그러나 여전히 history -r스크립트에 있어야합니다 .

  4. @ p0llard 's answer에서source 제안한대로 할 수 있습니다 .

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