Comando History dentro do script bash

20

O histórico é um comando embutido no shell que eu não poderia usar dentro de um script BASH. Então, existe uma maneira de conseguir isso usando o script BASH?
Aqui vamos nós meu script para você:

#!/bin/bash
history |  tail -100 > /tmp/history.log
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com
Vijay Ramachandran
fonte

Respostas:

31

O Bash desabilita o histórico em shells não interativos por padrão, mas você pode ativá-lo.

#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | tail 

Mas se você está tentando monitorar a atividade nesse servidor, o histórico do shell é inútil (é trivial executar comandos que não aparecem no histórico). Consulte Como registrar todos os processos iniciados no Linux .

Se você estiver depurando um script, o histórico do shell não é a melhor maneira de obter informações úteis. Uma ferramenta muito melhor é o recurso de rastreamento de depuração: coloque set -xperto da parte superior do script. O rastreio é gravado no erro padrão.

Gilles 'SO- parar de ser mau'
fonte
Isso se recusa a trabalhar em um script:histtest.sh: 5: set: Illegal option -o history
Ken Sharp
4
@KenSharp Isso ocorre porque você tentou usá-lo em um script sh (e você shestá julgando pela letra exata da mensagem de erro). Para acessar o histórico do bash, você precisa usar o bash (script começando com #!/bin/bashou #!/usr/bin/env bash).
Gilles 'SO- stop be evil'
11
@KenSharp Sim, é. Obviamente, você o executou no painel, dada a mensagem de erro. O Bash não tem a mensagem de erro Illegal option(diria set: history: invalid option name).
Gilles 'SO- stop be evil'
o problema disso é que ele adiciona todos os comandos que seguem set -o history ao histórico, que serão preenchidos com entradas como if [... vars=$(...etc. #
nath
11
@ath Isso é o que a pergunta pediu. É praticamente inútil, como aponto. A atividade de monitoramento é um problema difícil que o histórico do shell não resolverá. Se você estiver depurando um script, set -xserá muito mais útil.
Gilles 'SO- stop be evil'
6

Não tenho certeza se ele realmente usa o recurso de histórico ao executar de maneira não interativa, caso contrário, todos os scripts de shell que você executar atrapalhariam seu histórico de comandos.

Por que não ir diretamente à fonte ${HOME}/.bash_history, substitua history | tail -100por tail -100 ${HOME}/.bash_history. (Se você usar registros de data e hora, provavelmente precisará fazer algo como esse grep -v ^# ${HOME}/.bash_history | tail -100).

Kjetil Jorgensen
fonte
Na verdade, com marcas de tempo, você deve realmente greq -v '^#[0-9]\+$'(eu, por vezes, "executar" comentários no meu shell ...)
PlasmaBinturong
E, na verdade, no meu caso, eu preciso usar o número correto linha de história , mas há uma diferença entre a saída historye a saída do grepmétodo ...
PlasmaBinturong
Ok, a correção foi para sincronizar a lista de história com o arquivo de histórico como este: history -a; history -c; history -r. (adicionar, limpar, ler)
PlasmaBinturong
2

Se você quiser usar a saída do historycomando de uma sessão ativa do shell em um script, poderá usar um alias para executar o comando primeiro. Em seguida, no mesmo alias, você pode chamar o restante do script. Com essa configuração, você pode obter essencialmente o mesmo resultado de ter o historycomando no script real.

Por exemplo, você pode criar um alias como este, assumindo que o nome do script seja script.sh:

alias hy_tmp='history | tail -100 > /tmp/history.log ; bash /patch/to/script.sh'

E mude o script para isto:

#!/bin/bash
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

Encontrei essa pergunta ao escrever um processo para combinar, classificar e sincronizar ~/bash_historyarquivos em dois computadores, para que seja fácil pesquisar comandos que usei no passado.

É muito menos complicado atualizar meu arquivo de histórico cumulativo sem precisar fazer login em um novo shell para ~/bash_historyatualizá-lo. Para monitorar um servidor, obviamente isso não funcionará, como mencionado nas outras respostas.

Meu uso em particular é:

alias hbye='history | cut -c 8- > /home/chris/.bash_history_c; bash /hby.sh

O script hby.shpuxa todas as entradas exclusivas de todos os ~/.bash_history*arquivos.

clk
fonte
1

Crie um script com o nome script.shabaixo. Ele cria um script chamado X e coloca Y Número de linhas do seu histórico nele.

#!/bin/bash
SCRIPT_NAME=$1
NUMBER_OF_LINES_BACK=$2

# Enable History in a non interactive shell
HISTFILE=~/.bash_history
set -o history

# echo shabang line and x number of lines of history to new script
echo \#\!\/bin\/bash > $SCRIPT_NAME.sh; history | tail -n $NUMBER_OF_LINES_BACK >> $SCRIPT_NAME.sh;
chmod u+x $SCRIPT_NAME.sh;

# Open the newly created script with vim
vim $SCRIPT_NAME.sh;
~

Então, se você deseja criar um script para realizar uma tarefa chamada "task" na qual você trabalhou nas últimas 14 linhas, execute

script.sh task 14

Depois limpe sua história para criar um bom roteiro!

Eric
fonte
histtest.sh: 5: set: Illegal option -o history
Ken Sharp
1

O comando history está desativado por padrão no script bash, por isso, mesmo o comando history não funciona no arquivo .sh. para seu redirecionamento, redirecione gentilmente o arquivo bash_history dentro do arquivo .sh.

ou mecanismo de histórico também pode ser ativado, mencionando o arquivo de histórico e alterando os parâmetros de tempo de execução, conforme mencionado abaixo

#!/bin/bash
HISTFILE=~/.bash_history
set -o history 

nota: mencionado acima de duas linhas na parte superior do arquivo de script. agora o comando history funcionará na história.

linux.cnf
fonte
0

Todo usuário tem seu próprio arquivo de histórico, resultado do comando history. Em vez de usar o comando history em seu script de shell, você pode usar o arquivo de histórico para o usuário. Haverá um.bash_history arquivo no diretório inicial do usuário, que será o arquivo de histórico para o usuário.

Amit Singh
fonte
-1

Resposta curta :

usar history -p para executar explicitamente a expansão do histórico.

Um exemplo a seguir.

Um caso de uso acontece muito para mim é:

  • O comando anterior obtém uma lista de nomes de arquivos e imprime em stdout,
  • Eu preciso editar esses arquivos com o vim.

Desde que minha festa foi set -o histexpand, geralmente o que eu fiz foi digitar

vim $(!!)

para editar os arquivos listados pelo comando anterior.

Às vezes, infelizmente, erros acontecem, então eu habilito a verificação por shopt -s histverify .

Agora posso verificar a expansão, com o custo de uma Returnchave extra .

Hoje eu quero agrupar esses detalhes em uma função bash, já que os uso muito,

function vk() {
    set -o history && set -o histexpand;
    vim -i ~/.viminfok $($(history -p !!));
}

Aqui eu uso dois aninhados command substitution, o interno para expandir !!para o comando anterior, o externo para executá-lo e obter a saída.

Agora eu posso conseguir o mesmo efeito, com apenas três chaves, e uma delas é Return!

qeatzy
fonte