Como salvar o histórico de terminal em um arquivo de um arquivo bash?

7

Estou tentando criar um script bash que salvará o histórico do terminal em um arquivo chamado hist.txt. Usar history > hist.txt parece não funcionar no script bash, mas funciona bem quando executado na linha de comando.

Qualquer orientação é muito apreciada.

Obrigado Judy

    
por Judy 29.09.2016 / 15:58

2 respostas

10

Resposta curta

Execute o script com source ou . :

source ./script_name.sh

ou

. ./script_name.sh

O último é um pouco mais compatível entre diferentes shells.

Resposta longa

Esta questão destaca um ponto importante, que é que os scripts de shell são executados em seu próprio contexto. Para ver o que isso significa, considere o seguinte script de shell:

#!/bin/bash

cd /
ls

Se você executar isto, você receberá uma saída como esta:

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

Mas você notará que depois de executar o script, você ainda está em qualquer diretório em que estava antes de executá-lo: o cd / dentro do script não afetou sua sessão - afetou apenas o contexto em que o script estava sendo executado, que é criado para o script ser executado e destruído quando retornar.

O comando source 'lerá e executará comandos do argumento filename no contexto atual do shell', portanto, qualquer comando como cd dentro dele afetará sua sessão atual. Se você tivesse que executar o script acima passando-o para source , descobriria que acabou no diretório raiz depois que ele foi executado.

Nesse caso, o problema é que o comando history fornece o histórico do contexto atual do shell; o contexto de shell em que seu script é executado sem usar source não possui histórico, portanto, ele não escreve nada no arquivo de saída. Se você usar source , ele será executado no contexto correto e funcionará como esperado.

NB: source é um shell embutido, não um programa per se - no Bash, source é sinônimo de . , mas em alguns shells somente . trabalho - usei source nesta resposta porque é mais fácil de ler que . , mas para compatibilidade máxima, . deve ser usado.

    
por p0llard 29.09.2016 / 17:05
10

Antes de tudo, observe que seu histórico já está em um arquivo. Se você está executando bash, seu nome é geralmente ~/.bash_history . Mais especificamente, é tudo o que você definiu a variável HISTFILE para. Se você quiser copiá-lo para outro arquivo, basta executar cat "$HISTFILE" > hist.txt

Agora, como o comando history não funciona em um script de shell bash, isso ocorre porque os scripts são executados em um shell filho não interativo de sua sessão atual do shell. As shells filho não herdam todo o ambiente do pai (portanto, nem todas as variáveis definidas), apenas as variáveis que foram exportadas. Para ilustrar, o script abaixo mostrará o valor da variável $var :

#!/bin/bash
echo "$var"

Agora, defina $var como algo e execute o script:

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

Em seguida, exporte a variável primeiro:

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

Como você pode ver, quando a variável foi exportada, ela está disponível para shells filho.

Como mencionei antes, o histórico é armazenado no arquivo apontado pela variável $HISTFILENAME . Como isso não é exportado por padrão, não é definido ao executar um script:

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

Como você pode ver no exemplo acima, a variável HISTFILE está definida na minha sessão normal de shell, mas está vazia ao executar o script.

Então, para obter o histórico, você tem algumas opções:

  1. O valor HISTFILE padrão é $HOME/.bash_history . Se você não mudou isso, você pode simplesmente executar este comando no seu script:

    cat "$HOME/.bash_history" > history
    
  2. Você pode passar a variável $HISTFILE para seu script e cat que:

    #!/bin/bash
    cat "" > history
    

    Salve os itens acima como foo.sh e execute assim:

    ./foo.sh "$HISTORY"
    
  3. Certifique-se de que a variável é exportada. Adicione esta linha aos arquivos ~/.bash_profile (se existir) ou ~/.profile (se ~/.bash_profile não existir):

    export HISTFILE
    

    Em seguida, efetue logout e logon novamente e você poderá executar history > hist.txt de um script conforme o esperado. Isso ocorre porque export VAR significa "disponibilizar $ VAR para shells filho". Em termos práticos, isso significa que o valor de HISTFILE será herdado pelo shell não interativo que você usa para executar seu script.

    Agora, enquanto o HISTFILE será definido, ele não foi lido pelo shell que está executando o script. Então, para que funcione, você precisa lê-lo com history -r primeiro. O script inteiro ficaria assim:

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

    Como alternativa, basta exportá-lo manualmente antes de executar o script:

    $ export HISTFILE
    

    Mas você ainda precisará history -r no script.

  4. Você pode source como sugerido pela @ p0llard's answer .

por terdon 29.09.2016 / 17:08