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

11

Acho que faço muito trabalho 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. Eu uso mercurial ou git para rastrear alterações em arquivos , mas eu quero ser capaz de lembrar quais comandos eu emiti nesse diretório.

A pesquisa no meu histórico de shell não é muito informativa. Eu já ligo tudo para meus arquivos de histórico, mas eu quero uma lista de coisas que fiz em ~ / foo / bar, e não todas as outras (milhões) coisas que eu fiz naquela semana. Eu provavelmente não consigo nem lembrar em que mês trabalhei pela última vez nesse 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? Eu estou imaginando um comando algo como:

workon myproject

... que configuraria o arquivo de log do shell para ~ / myproject / .history.log, carregaria o histórico anterior desse arquivo de log e talvez atualizasse meu prompt para me dizer em qual diretório eu estava trabalhando (por exemplo, vcprompt para fornecer informações de controle de versão).

Existe alguma coisa lá fora assim?

    
por Simon 13.01.2012 / 04:05

10 respostas

2

Um truque que eu uso para a estrutura de criação de subpacotes para um produto é usar um sub-shell.

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, em $HOME/.project-bashrc , você coloca algo assim:

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

Isso também permite personalizar o prompt no arquivo .project-bashrc , o que pode ser útil.

Não sei como fazer o mesmo em zsh . Você teria que substituir a variável ZDOTDIR , eu acho. Mas seria semelhante.

Ciao!

    
por 13.04.2012 / 03:12
2

Caso você não tenha descoberto isso ainda: O que você está procurando é o excelente pacote virtualenvwrapper . É um wrapper em torno do virtualenv do python (go figura) e, embora seja comumente chamado quando se trata de ambientes python, é na verdade uma ferramenta muito genérica que satisfaz seu caso de uso.

Instalação

pip install virtualenvwrapper

ou

easy_install virtualenvwrapper

e adicione material de inicialização na sua configuração de shell ( ~/.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 em ~/.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 gancho ~/virtualenvs/postactivate significa que a variável $HISTFILE será expandida toda vez para um projeto diferente.

    
por 04.01.2014 / 15:32
2

Também preciso disso e desenvolvi uma versão que usa o Bash Variável PROMPT_COMMAND :

The value of the variable PROMPT_COMMAND is examined just before Bash prints each primary prompt. If PROMPT_COMMAND is set and has a non-null value, then the value is executed just as if it had been typed on the command line.

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 mudança de diretório, e quando isso é verdade, ele verifica a nova corrente diretório para o arquivo .bash_history. Se estiver lá, use-o como arquivo de histórico.

Aqui está a essência completa: link

    
por 08.05.2014 / 09:09
1

Veja os meus scripts de registro aqui . Usando um deles, você pode acompanhar em qual diretório você está quando emitir cada comando. Você pode grep do arquivo de log para o comando ou outras informações. Eu uso a versão longa em casa e no trabalho.

    
por 13.01.2012 / 18:18
1

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

#!/bin/cat
some
relevant
commands

Em seguida, executar o arquivo cat dos 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.

    
por 07.04.2016 / 15:46
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 seu exemplo 'workon' acima crie uma instância de shell.

Talvez você possa ver algo como

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

Mas o script também cria uma subchave.

Em suma, você provavelmente precisará de níveis confusos de subshells para que isso funcione.

    
por 13.01.2012 / 05:55
0

Trabalhei em empresas de software de produção, onde criamos novos usuários e grupos para várias funções. Novas contas de usuário especificamente para gerenciamento de configuração ou software constroem com níveis variados de visibilidade em outras áreas funcionais relacionadas através de associação a grupos e ACL, e o histórico de comandos realizado por cmmgr seria salvo em ~cmmgr/.bash_history , bldmgr palavra relacionada seria salva em ~bldmgr/.bash_history , etc. Infelizmente, para efetuar login, um usuário deve possuir seu diretório de login. Portanto, uma área do projeto foi configurada em um disco separado. A propriedade do criador do arquivo mostrou qual área funcional criou os arquivos na área do projeto, para os quais o .bash_history apropriado pode ser examinado.

A abordagem acima, no entanto, não oferece a granularidade desejada, mas fornece um esqueleto que, quando combinado à participação em um grupo, pode alternar grupos com newgrp , o que efetivamente cria um novo shell e e use uma das abordagens dadas nas outras respostas para alterar o arquivo ~/.bash_history efetivo quando mudar de chapéu para dizer, cmmgr para que newgrp possa gerenciar qual ~/.bash_history é usado e salvo por pasta quando se entra e sai do novo grupo através do comando newgrp . Confira man newgrp . Há alguns pontos iniciais nesse sentido em outras respostas a essa pergunta. Eles devem funcionar com o paradigma de grupo do UNIX - a maioria das porcas e parafusos são manipulados pelas rotinas de inicialização e saída do shell, conforme controlado pela invocação newgrp . 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.
    
por 04.01.2014 / 17:56
0

Aqui apresento duas variantes, mas aplicáveis apenas ao Z Shell .

Variante 1

Foi nisso que pensei primeiro 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 muda para um histórico por diretório automaticamente quando chdir . A história global acumula todos comandos emitidos.

  • Demonstração

    ~ source src/cd_history
    ~ echo global history                                                
    global history
    ~ mkdir foo bar                                                      
    ~ [ALT-h]
    ~                         note the indicator for local history ->   +
    ~ cd foo                                                            +
    ~/foo echo local history in foo                                     +
    local history in foo
    ~/foo fc -l                                                         +
        1  echo local history in foo
    ~/foo cd ../bar                                                     +
    ~/bar echo local history in bar                                     +
    local history in bar
    ~/bar fc -l                                                         +
        1  echo local history in bar
    ~/bar cd ../foo                                                     +
    ~/foo fc -l                                                         +
        1  echo local history in foo
        3  cd ../bar
    ~/foo [ALT-h]                                           
    ~/foo fc -l                                                          
       55  source src/cd_history
       64  echo global history
       65  mkdir foo bar
       66  cd foo
       70  echo local history in bar
       72  cd ../foo
       73  echo local history in foo
       74  cd ../bar
    ~/foo  
  • O script (a ser incluído em ~/.zshrc ou a ser originado)

    # 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 sobre isso novamente, parece que o histórico por diretório é muito detalhado e você também descreve mais um histórico por projeto no corpo da pergunta. Então eu criei outra variante com uma função workon para alternar entre os projetos. Todo projeto tem seu próprio arquivo de histórico ~/.zsh_projhistory_[name] .

  • Demonstração

    ~ source src/proj_history 
    ~ echo global history                                                                    
    global history
    ~ [ALT-h]                                                              [use workon]
    ~ workon foo                                                           [use workon]
    ~ echo command in project foo                                         [on proj foo]
    command in project foo
    ~ fc -l                                                               [on proj foo]
        1  echo command in project foo
    ~ workon bar                                                          [on proj foo]
    ~ echo another proj, named bar                                        [on proj bar]
    another proj, named bar
    ~ fc -l                                                               [on proj bar]
        1  echo another proj, named bar
    ~ workon foo                                                          [on proj bar]
    ~ fc -l                                                               [on proj foo]
        1  echo command in project foo
        3  workon bar
    ~ [ALT-h]                                                             [on proj foo]
    ~
    ~ fc -l                                                                                   
       31  echo global history
       36  echo another proj, named bar
       38  workon foo
       39  echo command in project foo
       40  workon bar
    ~ ls -1 .zsh_*
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • O script (a ser incluído em ~/.zshrc ou a ser originado)

    # 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 
    }
    
por 07.01.2014 / 12:09
0

Você pode estar interessado em um plugin que eu escrevi chamado directory-history para zsh.
Veja aqui: link

Embora não caiba muito no seu fluxo de trabalho workon myproject , ele deve se encaixar perfeitamente às suas necessidades.

Cria um histórico que inclui diretórios.
Quando você pesquisa através de seu histórico, você primeiro obtém comandos do diretório em que você está. Se não houver nenhum comando para esse diretório, ele retornará a um histórico global e sugerirá comandos usados em outros diretórios.

    
por 14.03.2014 / 22:05
0

Depois de trabalhar em uma área por algum tempo.

histórico > hist1.txt então depois história > hist2.txt

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

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

    
por 27.07.2018 / 14:02