Arquivos de log de histórico bash / zsh por diretório


14

Acho que trabalho bastante em um projeto em um diretório definido. Às vezes - alguns meses depois - preciso refazer algo nesse projeto, mas não consigo me lembrar do que fiz. Uso o mercurial ou o git para rastrear alterações nos arquivos, mas quero poder lembrar quais comandos foram emitidos nesse diretório.

Pesquisando meu histórico de shell não é muito informativo. Já registro tudo nos meus arquivos de histórico. * _, Mas quero uma lista das coisas que fiz em ~ / foo / bar, e não todas as outras (milhões) de coisas que fiz naquela semana. Provavelmente nem me lembro em que mês trabalhei pela última vez naquele projeto em particular.

Alguém tem alguma idéia de como um arquivo de log do diretório do projeto de todos os comandos do shell que eu usei? Estou visualizando um comando algo como:

workon myproject

... que definiria o arquivo de log do shell como ~ / myproject / .history.log, carregaria o histórico anterior desse arquivo de log e talvez atualizasse minha solicitação para me dizer em que diretório estou trabalhando (como, por exemplo, vcprompt para fornecer a versão informações de controle).

Existe algo assim por aí?

Respostas:


4

Caso você ainda não tenha entendido isso: o que você está procurando é o excelente pacote virtualenvwrapper . É um invólucro do virtualenv do python (vá em figura) e, embora seja comumente referido ao abordar ambientes python, na verdade é uma ferramenta muito genérica que satisfaz o seu caso de uso.

Instalação

pip install virtualenvwrapper

ou

easy_install virtualenvwrapper

e adicione coisas de inicialização em seu shell config ( ~/.zshrc, ~/.bashrc)

export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$WORKON_HOME/projects
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true
source /usr/local/bin/virtualenvwrapper.sh

Uso

# create your env
mkvirtualenv my_project

# edit per project hooks
vim ~/.virtualenvs/my_project/bin/{postactivate,preactivate,predeactivate,etc}

# work in this env
workon my_project

Você também tem ganchos genéricos ~/.virtualenvs/{postactivate,postdeactivate,etc}que são chamados toda vez que você workon any_project.

Assim, por exemplo, ter a linha export HISTFILE="$VIRTUAL_ENV/bash_history"no ~/virtualenvs/postactivategancho significa que a $HISTFILEvariável será expandida todas as vezes para um projeto diferente.


3

Também preciso disso e criei uma versão que usa a variável PROMPT_COMMAND do Bash :

O valor da variável PROMPT_COMMAND é examinado antes de o Bash imprimir cada prompt principal. Se PROMPT_COMMAND estiver definido e tiver um valor não nulo, o valor será executado como se tivesse sido digitado na linha de comando.

Então eu digo PROMPT_COMMAND = "check_for_local_history" em ~ / .bashrc.my, onde check_for_local_historyé uma função minha que verifica se o último comando executado foi uma alteração de diretório e, quando isso é verdade, verifica o novo diretório atual do arquivo .bash_history . Se estiver lá, use-o como o arquivo de histórico.

Aqui está a lista completa: https://gist.github.com/gurdiga/dac8d2e7eb3056d6b839


2

Um truque que eu uso na estrutura de construção de subpacotes para um produto é usar um subcasco.

Para o bash, você pode criar um script de shell como este:

#!/bin/bash

export PROJECT_DIRECTORY=$(pwd)

exec bash --rcfile $HOME/.project-bashrc

Então $HOME/.project-bashrcvocê coloca algo assim:

source $HOME/.bashrc
export HISTFILE="${PROJECT_DIRECTORY}/.bash_history"
cd "${PROJECT_DIRECTORY}"

Isso também permite que você personalize o prompt no .project-bashrcarquivo, o que pode ser útil.

Não sei ao certo como fazer o mesmo zsh. Você teria que substituir a ZDOTDIRvariável, eu acho. Mas seria parecido.

Tchau!


1

Dê uma olhada nos meus scripts de log aqui . Usando um deles, você pode acompanhar o diretório em que está quando emite cada comando. Você pode grepo arquivo de log para o comando ou outras informações. Eu uso a versão longa em casa e no trabalho.


Obrigado - vou dar uma olhada nisso. Pode fazer algo próximo ao que eu preciso!
Simon

1

Você pode estar interessado em um plugin que escrevi chamado directory-history for zsh.
Veja aqui: https://github.com/tymm/directory-history

Embora não se ajuste realmente ao seu fluxo de trabalho no meu projeto , ele deve se encaixar perfeitamente às suas necessidades.

Ele cria um histórico que inclui diretórios.
Ao pesquisar seu histórico, você primeiro obtém comandos do diretório em que se encontra.
Se não houver comandos para esse diretório, ele retornará a um histórico global e sugerirá comandos usados ​​em outros diretórios.


1

Se você quiser algo simples, poderá ter seu .history.logarquivo como tal:

#!/bin/cat
some
relevant
commands

Em seguida, a execução do arquivo incluiria catos comandos listados nele.
Você também pode agrupar esses comandos em arquivos separados por funcionalidade como convenção:

.howto.datadump
.howto.restart

Isso tem a vantagem de trabalhar fora da caixa e não poluir seu ambiente.


Como alternativa, você pode usar README.mdou criar outros .mdarquivos por tópico e apontá-los a partir do leia-me. Isso se você tiver uma interface de controle de fonte amigável à redução de preço.
Reno

1

Para obter um arquivo de histórico local para um diretório, adicionei a seguinte linha ao meu comando bash prompt.

if [ -f .local_history ] ; then tail -1 $HISTFILE >> .local_history ; fi

O comando touch .local_historyem um diretório fornece um arquivo de histórico local para todos os comandos executados nesse diretório, sem perder o arquivo de histórico principal. Algo semelhante funcionaria no zsh, eu acho.


0

No bash, pelo menos, o HISTFILE é consultado apenas no início da instância do shell. A ideia por dir não funcionará aqui, a menos que o exemplo 'workon' acima crie uma instância de shell.

Talvez você possa olhar para algo como

alias workon='script ./.history.log'

Mas o script também cria um subshell.

Em resumo, você provavelmente precisará de níveis sujos de subcascas para fazer com que isso funcione.


Porra, eu esperava que fosse algo simples. Obrigado mesmo assim!
Simon

0

Eu trabalhei em casas de software de produção onde apenas criamos novos usuários e grupos para várias funções. Novas contas de usuário especificamente para gerenciamento de configuração ou criação de software com diferentes níveis de visibilidade em outras áreas funcionais relacionadas por meio de associação ao grupo e ACL, e o histórico de comandos executado por, por exemplo, cmmgrseria salvo em ~cmmgr/.bash_history, a bldmgrpalavra relacionada seria salva em ~bldmgr/.bash_historyetc. Infelizmente, para fazer login, um usuário deve possuir seu diretório de login. Portanto, uma área do projeto foi configurada em um disco separado completamente. A propriedade do criador do arquivo mostrou qual área funcional criou os arquivos na área do projeto, para a qual o apropriado .bash_historypode ser examinado.

A abordagem acima, no entanto, não fornece a granularidade desejada, no entanto, fornece um esqueleto de que, quando combinado com a associação ao grupo, um usuário pode alternar grupos com os newgrpquais efetivamente cria um novo shell e ambiente e, em seguida, usar um das abordagens fornecidas nas outras respostas para alterar o ~/.bash_historyarquivo efetivo ao trocar de chapéu , cmmgrpara que um newgrppossa gerenciar o que ~/.bash_historyé usado e salvo por pasta à medida que alguém entra e sai do novo grupo por meio do newgrpcomando Confira man newgrp. Existem alguns pontos de partida nesse sentido em outras respostas a esta pergunta. Eles devem funcionar com o paradigma do grupo UNIX - a maioria das porcas e parafusos são manipulados pelas rotinas de inicialização e saída do shell, conforme controlado pelonewgrpinvocação. Confira newgrp -l:

NAME
     newgrp -- change to a new group

SYNOPSIS
     newgrp [-l] [group]

DESCRIPTION
     The newgrp utility creates a new shell execution environment with modified real and effective group
     IDs.

     The options are as follows:

     -l      Simulate a full login.  The environment and umask are set to what would be expected if the user
             actually logged in again.

0

Apresento aqui duas variantes, mas aplicáveis ​​apenas ao Z Shell .

Variante 1

Foi nisso que pensei pela primeira vez ao ler o título da sua pergunta. Com esta variante, você pode alternar entre dois modos de histórico com ALT+ h: Global ou local , onde o último alterna para um histórico por diretório automaticamente no chdir . O histórico global acumula todos os comandos emitidos.

  • Demonstração

    ~ fonte src / cd_history
    ~ eco da história global                                                
    história global
    ~ mkdir foo bar                                                      
    ~ [ALT-h] 
    ~                          observe o indicador para o histórico local ->    +
    ~ cd foo +
    ~ / foo echo a história local em foo +
    história local em foo
    ~ / foo fc -l +
        1 eco história local em foo
    ~ / foo cd ../bar +
    ~ / bar ecoa a história local no bar +
    história local em bar
    ~ / bar fc -l +
        1 eco da história local no bar
    ~ / bar cd ../foo +
    ~ / foo fc -l +
        1 eco história local em foo
        3 cd ../bar
    ~ / foo [ALT-h]                                           
    ~ / foo fc -l                                                          
       55 origem src / cd_history
       64 eco história global
       65 mkdir foo bar
       66 cd foo
       70 eco da história local no bar
       72 cd .. / fu
       73 eco da história local em foo
       74 cd ../bar
    ~ / foo  
  • O script (a ser incluído ~/.zshrcou a fonte)

    # set options for shared history
    setopt prompt_subst
    setopt share_history
    setopt hist_ignorealldups
    
    # define right prompt as an indicator if local (i.e. per directory) history is enabled
    RPS1=' ${HISTLOC}'
    export HISTLOC=''
    
    # configure global history file and global/local history size
    export HISTGLOBAL=$HOME/.zsh_history
    touch $HISTGLOBAL
    export HISTSIZE=2000
    export SAVEHIST=2000
    
    # define wrapper function and key binding to switch between globel and per-dir history
    function my-local-history()
    {
      if [[ -z $HISTLOC ]]; then
        HISTLOC='+'
        chpwd
      else
        HISTLOC=''
        export HISTFILE=$HISTGLOBAL
        fc -A $HISTFILE
        fc -p $HISTFILE $HISTSIZE $SAVEHIST
      fi
      zle reset-prompt
    }
    zle -N my-local-history
    bindkey "^[h"    my-local-history
    
    # install hook function which is called upon every directory change
    chpwd () {
      if [[ ! -z $HISTLOC ]]; then
        fc -A $HISTGLOBAL $HISTSIZE $SAVEHIST
        export HISTFILE=$PWD/.zsh_history
        fc -p $HISTFILE $HISTSIZE $SAVEHIST
        touch $HISTFILE
      fi 
    }
    

Variante 2

Pensando nisso novamente, parece que o histórico por dir é muito refinado e você também descreve mais um histórico por projeto no corpo da pergunta. Então, criei outra variante com uma função workon para alternar entre projetos. Todo projeto tem seu próprio arquivo de histórico ~/.zsh_projhistory_[name].

  • Demonstração

    ~ fonte src / proj_history 
    ~ eco da história global                                                                    
    história global
    ~ [ALT-h]                                                               [usar trabalho]
    ~ workon foo [use workon]
    comando ~ echo no projeto foo [no proj foo]
    comando no projeto foo
    ~ fc -l [no projeto foo]
        1 comando echo no projeto foo
    ~ barra de trabalho [on proj foo]
    ~ ecoa outro proj, chamado bar [na barra de proj]
    outro proj, chamado bar
    ~ fc -l [na barra de projeção]
        1 eco outro projeto, chamado bar
    ~ workon foo [na barra de projeção]
    ~ fc -l [no projeto foo]
        1 comando echo no projeto foo
        Barra de 3 workon
    ~ [ALT-h]                                                              [no projeto foo]
    ~
    ~ fc -l                                                                                   
       31 eco história global
       36 ecoam outro proj, chamado bar
       38 workon foo
       39 comando echo no projeto foo
       Barra de 40 workon
    ~ ls -1 .zsh_ *
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • O script (a ser incluído ~/.zshrcou a fonte)

    # set options for shared history
    setopt prompt_subst
    setopt share_history
    setopt hist_ignorealldups
    
    # define right prompt as an indicator if local (i.e. per directory) history is enabled
    RPS1=' ${HISTLOC}'
    export HISTLOC=''
    
    # configure global history file and global/local history size
    export HISTGLOBAL=$HOME/.zsh_history
    touch $HISTGLOBAL
    export HISTFILE=$HISTGLOBAL
    export HISTSIZE=2000
    export SAVEHIST=2000
    
    # define wrapper function and key binding to switch between globel and per-dir history
    function my-local-history()
    {
      if [[ -z $HISTLOC ]]; then
        if [[ -z $HISTLOC ]]; then
          HISTLOC='+'
          [[ -z "$HISTPROJ" ]] && HISTLOC='[use workon]' || workon "$HISTPROJ"
        fi
      else
        HISTLOC=''
        export HISTFILE=$HISTGLOBAL
        fc -A $HISTFILE
        fc -p $HISTFILE $HISTSIZE $SAVEHIST
      fi
      zle reset-prompt
    }
    zle -N my-local-history
    bindkey "^[h"    my-local-history
    
    # function to change project
    workon () {
      if [[ -z "$1" ]]; then
        echo Usage: workon [project name]
        return 1
      fi
      export HISTPROJ="$1"
      if [[ ! -z $HISTLOC ]]; then
        fc -A $HISTGLOBAL $HISTSIZE $SAVEHIST
        export HISTFILE=$HOME/.zsh_projhistory_"$HISTPROJ"
        fc -p "$HISTFILE" $HISTSIZE $SAVEHIST
        touch "$HISTFILE"
        HISTLOC="[on proj $HISTPROJ]"
      fi 
    }
    

0

Depois de trabalhar em uma área por algum tempo.

history> hist1.txt e depois history> hist2.txt

Às vezes eu uso a data para o nome do arquivo. história> hist20180727.txt

Dessa forma, há um histórico recente de comandos para cada diretório.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.