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.