Archivos de registro de historial bash / zsh por directorio

14

Me parece que hago mucho trabajo en un proyecto en un directorio establecido. A veces, unos meses después, necesito rehacer algo en ese proyecto, pero no puedo recordar lo que hice. Uso mercurial o git para rastrear los cambios en los archivos, pero quiero poder recordar qué comandos emití en ese directorio.

Buscar en mi historial de shell no es muy informativo. Ya registro todo en mis archivos de historial. * _, Pero quiero una lista de las cosas que hice en ~ / foo / bar, y no todas las otras (millones) cosas que hice esa semana. Probablemente ni siquiera puedo recordar en qué mes trabajé por última vez en ese proyecto en particular.

¿Alguien tiene alguna idea de cómo un archivo de registro de directorio de proyecto de todos los comandos de shell que he usado? Estoy imaginando un comando algo como:

workon myproject

... que establecería el archivo de registro de shell en ~ / myproject / .history.log, cargaría el historial anterior de ese archivo de registro y quizás actualizaría mi mensaje para decirme en qué directorio estoy trabajando (como, por ejemplo, vcprompt para proporcionar la versión información de control).

¿Hay algo por ahí como este?

Simón
fuente

Respuestas:

4

En caso de que aún no lo haya resuelto: lo que está buscando es el excelente paquete virtualenvwrapper . Es una envoltura alrededor del virtualenv de Python (vaya a la figura) y, si bien se hace referencia a menudo cuando se trata de entornos de Python, en realidad es una herramienta muy genérica que satisface su caso de uso.

Instalación

pip install virtualenvwrapper

o

easy_install virtualenvwrapper

y agregue cosas de inicialización en su configuración 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

También tiene ganchos genéricos ~/.virtualenvs/{postactivate,postdeactivate,etc}que se llaman cada vez que usted workon any_project.

Entonces, por ejemplo, tener la línea export HISTFILE="$VIRTUAL_ENV/bash_history"en el ~/virtualenvs/postactivategancho significa que la $HISTFILEvariable se expandirá cada vez a un proyecto diferente.

catalin.costache
fuente
3

También necesito esto y se me ocurrió una versión que utiliza la variable PROMPT_COMMAND de Bash :

El valor de la variable PROMPT_COMMAND se examina justo antes de que Bash imprima cada solicitud principal. Si PROMPT_COMMAND está configurado y tiene un valor no nulo, entonces el valor se ejecuta como si se hubiera escrito en la línea de comando.

Entonces digo PROMPT_COMMAND = "check_for_local_history" en ~ / .bashrc.my, donde check_for_local_historyes una función mía que comprueba si el último comando ejecutado fue un cambio de directorio, y cuando eso es cierto, comprueba el nuevo directorio actual para el archivo .bash_history . Si está allí, úselo como archivo de historial.

Aquí está la esencia completa: https://gist.github.com/gurdiga/dac8d2e7eb3056d6b839

Vlad GURDIGA
fuente
2

Un truco que uso para el marco de creación de subpaquetes para un producto es usar un subconjunto.

Para bash, podría crear un script de shell como este:

#!/bin/bash

export PROJECT_DIRECTORY=$(pwd)

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

Luego en $HOME/.project-bashrcponer algo como esto:

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

Esto también le permite personalizar la solicitud en el .project-bashrcarchivo, que puede ser útil.

No estoy seguro de cómo hacer lo mismo zsh. Tendría que anular la ZDOTDIRvariable, creo. Pero se vería similar.

Ciao!

docwhat
fuente
1

Echa un vistazo a mis scripts de registro aquí . Con uno de ellos, puede realizar un seguimiento del directorio en el que se encuentra cuando emite cada comando. Puede grepel archivo de registro para el comando u otra información. Utilizo la versión larga en casa y en el trabajo.

Pausado hasta nuevo aviso.
fuente
Gracias, echaré un vistazo a esto. ¡Podría hacer algo parecido a lo que necesito!
Simon
1

Puede que le interese un complemento que escribí llamado directorio-historial para zsh.
Mira aquí: https://github.com/tymm/directory-history

Aunque en realidad no se ajusta a su trabajo en el flujo de trabajo de myproject , debería adaptarse perfectamente a sus necesidades.

Crea una historia que incluye directorios.
Cuando busque en su historial, primero obtendrá los comandos del directorio en el que se encuentra.
Si no quedan comandos para ese directorio, recurrirá a un historial global y sugerirá los comandos utilizados en otros directorios.

tymm
fuente
1

Si desea algo simple, puede tener su .history.logarchivo como tal:

#!/bin/cat
some
relevant
commands

A continuación, ejecute el archivo con catlos comandos que enumeró en él.
También puede agrupar esos comandos en archivos separados por funcionalidad como convención:

.howto.datadump
.howto.restart

Esto tiene la ventaja adicional de trabajar fuera de la caja y no contaminar su entorno.

Reno
fuente
Alternativamente, puede utilizar README.mdo crear otros .mdarchivos por tema y señalarlos desde el archivo Léame. Eso si tiene una interfaz de control de fuente amigable de reducción.
Reno
1

Para obtener un archivo de historial local para un directorio, agregué la siguiente línea a mi comando bash prompt.

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

El comando touch .local_historyen un directorio me da un archivo de historial local para todos los comandos ejecutados en ese directorio, sin perder el archivo de historial principal. Algo similar funcionaría en zsh, supongo.

Aad Schippers
fuente
0

Al menos en bash, HISTFILE solo se consulta al inicio de la instancia de shell. La idea por directorio no funcionará aquí, a menos que su ejemplo 'workon' anterior cree una instancia de shell.

Tal vez puedas mirar algo como

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

Pero el script también crea una subshell.

En resumen, probablemente necesitará niveles desordenados de subcapas para que esto funcione.

Rich Homolka
fuente
Maldición, esperaba que fuera algo simple. ¡Gracias de cualquier manera!
Simon
0

He trabajado en casas de software de producción donde simplemente creamos nuevos usuarios y grupos para diversas funciones. Las nuevas cuentas de usuario específicamente para la gestión de la configuración o las compilaciones de software con niveles variables de visibilidad en otras áreas funcionales relacionadas a través de la pertenencia a grupos y ACL, y el historial de comandos realizado por say, se cmmgrguardaría ~cmmgr/.bash_history, bldmgrlas palabras relacionadas se guardarían ~bldmgr/.bash_history, etc. Desafortunadamente, para iniciar sesión, un usuario debe ser propietario de su directorio de inicio de sesión. Por lo tanto, se configuró un área de proyecto en un disco separado por completo. La propiedad del creador del archivo mostró qué área funcional creó los archivos en el área del proyecto, para lo cual .bash_historyse puede examinar el apropiado .

Sin embargo, el enfoque anterior no le brinda la granularidad que desea, sin embargo, le brinda un esqueleto que, cuando se combina con la pertenencia a un grupo, un usuario podría cambiar de grupo con lo newgrpque efectivamente crea un nuevo shell y entorno, y luego usar uno de los enfoques dados en las otras respuestas para alterar el ~/.bash_historyarchivo efectivo al cambiar sombreros para decir, de cmmgrmodo que se newgrppueda administrar cuál ~/.bash_historyse usa y guarda por carpeta a medida que uno ingresa y sale del nuevo grupo a través del newgrpcomando. Echa un vistazo man newgrp. Hay algunos puntos de partida a lo largo de estas líneas en otras respuestas a esta pregunta. Estos deberían funcionar con el paradigma de grupo UNIX: la mayoría de las tuercas y tornillos son manejados por las rutinas de inicio y salida de shell controladas pornewgrpinvocación. Echa un vistazo a 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.
Billy McCloskey
fuente
0

Aquí presento dos variantes, pero aplicables solo a Z Shell .

Variante 1

Esto es lo que pensé por primera vez al leer el título de su pregunta. Con esta variante, puede cambiar entre dos modos de historial con ALT+ h: Global o local , donde este último cambia automáticamente a un historial por directorio en chdir . La historia global acumula todos los comandos emitidos.

  • Demostración

    ~ fuente src / cd_history
    ~ echo historia global                                                
    historia global
    ~ mkdir foo bar                                                      
    ~ [ALT-h] 
    ~                          tenga en cuenta el indicador de historial local ->    +
    ~ cd foo +
    ~ / foo echo historia local en foo +
    historia local en foo
    ~ / foo fc -l +
        1 eco de la historia local en foo
    ~ / foo cd ../bar +
    ~ / bar echo historia local en bar +
    historia local en bar
    ~ / bar fc -l +
        1 eco de la historia local en el bar
    ~ / bar cd ../foo +
    ~ / foo fc -l +
        1 eco de la historia local en foo
        3 cd ../bar
    ~ / foo [ALT-h]                                           
    ~ / foo fc -l                                                          
       55 fuente src / cd_history
       64 echo historia global
       65 mkdir foo bar
       66 cd foo
       70 echo historia local en bar
       72 cd ../foo
       73 echo historia local en foo
       74 cd ../bar
    ~ / foo  
  • El guión (para incluir ~/.zshrco para obtener)

    # 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

Pensándolo de nuevo, parece que el historial por directorio es demasiado detallado y también describe más un historial por proyecto en su cuerpo de preguntas. Así me ocurrió con otra variante con un workon función para cambiar entre proyectos. Cada proyecto tiene su propio archivo de historial ~/.zsh_projhistory_[name].

  • Demostración

    ~ fuente src / proj_history 
    ~ echo historia global                                                                    
    historia global
    ~ [ALT-h]                                                               [use workon]
    ~ workon foo [use workon]
    ~ comando echo en proyecto foo [en proj foo]
    comando en proyecto foo
    ~ fc -l [en proj foo]
        1 comando echo en proyecto foo
    ~ workon bar [en proj foo]
    ~ echo otro proyecto, llamado barra [en la barra de proyecto]
    otro proyecto, llamado bar
    ~ fc -l [en la barra de proyectos]
        1 echo otro proyecto, llamado barra
    ~ workon foo [en la barra de proyectos]
    ~ fc -l [en proj foo]
        1 comando echo en proyecto foo
        3 barra de trabajo
    ~ [ALT-h]                                                              [en proj foo]
    ~
    ~ fc -l                                                                                   
       31 echo historia global
       36 echo otro proyecto, llamado bar
       38 workon foo
       39 comando echo en proyecto foo
       40 barra de trabajo
    ~ ls -1 .zsh_ *
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • El guión (para incluir ~/.zshrco para obtener)

    # 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 
    }
mpy
fuente
0

Después de trabajar en un área por un tiempo.

history> hist1.txt luego historia> hist2.txt

A veces uso la fecha para el nombre del archivo. historia> hist20180727.txt

De esta manera hay un historial de comandos reciente para cada directorio.

John
fuente