Fichiers journaux d'historique bash / zsh par répertoire

14

Je trouve que je fais beaucoup de travail sur un projet dans un répertoire défini. Parfois - quelques mois plus tard - j'ai besoin de refaire quelque chose sur ce projet mais je ne me souviens pas de ce que j'ai fait. J'utilise mercurial ou git pour suivre les modifications apportées aux fichiers, mais je veux pouvoir me souvenir des commandes que j'ai émises dans ce répertoire.

La recherche dans mon historique de shell n'est pas très informative. J'ai déjà tout enregistré dans mes fichiers d'historique. * _, Mais je veux une liste des choses que j'ai faites dans ~ / foo / bar, et pas toutes les autres (millions) choses que j'ai faites cette semaine. Je ne me souviens probablement pas du mois où j'ai travaillé pour la dernière fois sur ce projet particulier.

Quelqu'un at-il des idées sur la façon dont un fichier journal de répertoire de projet de toutes les commandes shell que j'ai utilisées? J'imagine une commande comme:

workon myproject

... qui définirait le fichier journal du shell sur ~ / monprojet / .history.log, chargerait l'historique précédent à partir de ce fichier journal, et peut-être mettrait à jour mon invite pour me dire sur quel répertoire je travaille (comme par exemple vcprompt pour fournir la version informations de contrôle).

Y a-t-il quelque chose comme ça?

Simon
la source

Réponses:

4

Au cas où vous ne l'auriez pas encore compris: ce que vous recherchez est l'excellent package virtualenvwrapper . C'est un wrapper autour de virtualenv de python (allez comprendre) et, bien qu'il soit communément appelé lors de la prise en compte des environnements python, c'est en fait un outil très générique qui satisfait votre cas d'utilisation.

Installation

pip install virtualenvwrapper

ou

easy_install virtualenvwrapper

et ajouter des trucs d'initialisation dans votre 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

Usage

# 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

Vous avez également des crochets génériques ~/.virtualenvs/{postactivate,postdeactivate,etc}qui sont appelés à chaque fois que vous workon any_project.

Ainsi, par exemple, avoir la ligne export HISTFILE="$VIRTUAL_ENV/bash_history"dans le ~/virtualenvs/postactivatecrochet signifie que la $HISTFILEvariable sera développée à chaque fois dans un projet différent.

catalin.costache
la source
3

J'en ai aussi besoin et j'ai trouvé une version qui utilise la variable PROMPT_COMMAND de Bash :

La valeur de la variable PROMPT_COMMAND est examinée juste avant que Bash imprime chaque invite principale. Si PROMPT_COMMAND est défini et a une valeur non nulle, alors la valeur est exécutée comme si elle avait été tapée sur la ligne de commande.

Je dis donc PROMPT_COMMAND = "check_for_local_history" dans ~ / .bashrc.my, où check_for_local_historyest une de mes fonctions qui vérifie si la dernière commande exécutée était un changement de répertoire, et quand c'est vrai, il vérifie le nouveau répertoire actuel pour le fichier .bash_history . S'il est là, utilisez-le comme fichier d'historique.

Voici l'essentiel: https://gist.github.com/gurdiga/dac8d2e7eb3056d6b839

Vlad GURDIGA
la source
2

Une astuce que j'utilise pour le cadre de construction de sous-packages pour un produit est d'utiliser un sous-shell.

Pour bash, vous pouvez créer un script shell comme celui-ci:

#!/bin/bash

export PROJECT_DIRECTORY=$(pwd)

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

Ensuite, $HOME/.project-bashrcvous mettez quelque chose comme ceci:

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

Cela vous permet également de personnaliser l'invite dans le .project-bashrcfichier, ce qui peut être pratique.

Je ne sais pas comment faire de même zsh. Il faudrait remplacer la ZDOTDIRvariable, je pense. Mais ça ressemblerait.

Ciao!

docwhat
la source
1

Jetez un œil à mes scripts de journalisation ici . À l'aide de l'un d'eux, vous pouvez garder une trace du répertoire dans lequel vous vous trouvez lorsque vous exécutez chaque commande. Vous pouvez greple fichier journal pour la commande ou d'autres informations. J'utilise la version longue à la maison et au travail.

En pause jusqu'à nouvel ordre.
la source
Merci - je vais voir ça. Pourrait faire quelque chose proche de ce dont j'ai besoin!
Simon
1

Vous pourriez être intéressé par un plugin que j'ai écrit appelé directory-history for zsh.
Regardez ici: https://github.com/tymm/directory-history

Bien qu'il ne corresponde pas vraiment à votre travail sur le flux de travail myproject , il devrait parfaitement correspondre à vos besoins.

Il crée un historique qui comprend des répertoires.
Lorsque vous recherchez dans votre historique, vous obtiendrez d'abord les commandes du répertoire dans
lequel vous vous trouvez. S'il n'y a plus de commandes pour ce répertoire, il reviendra à un historique global et suggérera des commandes utilisées dans d'autres répertoires.

tymm
la source
1

Si vous voulez quelque chose de simple, vous pouvez avoir votre .history.logfichier en tant que tel:

#!/bin/cat
some
relevant
commands

Ensuite, l'exécution du fichier correspondrait cataux commandes que vous y avez répertoriées.
Vous pouvez également regrouper ces commandes dans des fichiers séparés par fonctionnalité comme convention:

.howto.datadump
.howto.restart

Cela a l'avantage supplémentaire de travailler hors de la boîte et de ne pas polluer votre environnement.

Reno
la source
Vous pouvez également utiliser README.mdou créer d'autres .mdfichiers par sujet et les pointer vers le fichier Lisez-moi. C'est si vous avez une interface de contrôle de source conviviale pour le démarquage.
Reno
1

Pour obtenir un fichier d'historique local pour un répertoire, j'ai ajouté la ligne suivante à ma commande d'invite bash.

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

La commande touch .local_historydans un répertoire me donne alors un fichier d'historique local pour toutes les commandes exécutées dans ce répertoire, sans perdre le fichier d'historique principal. Quelque chose de similaire fonctionnerait dans zsh, je suppose.

Aad Schippers
la source
0

En bash au moins, HISTFILE n'est consulté qu'au début de l'instance de shell. L'idée par répertoire ne fonctionnera pas ici, à moins que votre exemple 'workon' ci-dessus ne crée une instance de shell.

Peut-être que vous pouvez regarder quelque chose comme

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

Mais le script crée également un sous-shell.

En bref, vous aurez probablement besoin de niveaux désordonnés de sous-coquilles pour que cela fonctionne.

Rich Homolka
la source
Merde, j'espérais que ce serait quelque chose de simple. Merci quand même!
Simon
0

J'ai travaillé dans des éditeurs de logiciels de production où nous venions de créer de nouveaux utilisateurs et groupes pour diverses fonctions. De nouveaux comptes d'utilisateurs spécifiquement pour la gestion de la configuration ou les versions de logiciels avec différents niveaux de visibilité dans d'autres domaines fonctionnels connexes via l'appartenance à un groupe et l'ACL, et l'historique des commandes effectué par exemple, cmmgrseraient enregistrés ~cmmgr/.bash_history, le bldmgrmot associé serait enregistré ~bldmgr/.bash_history, etc. Malheureusement, pour se connecter, un utilisateur doit posséder son répertoire de connexion. Par conséquent, une zone de projet a été entièrement configurée sur un disque séparé. La propriété du créateur du fichier a montré quel domaine fonctionnel a créé les fichiers dans la zone du projet, pour lequel les éléments appropriés .bash_historypeuvent être examinés.

L'approche ci-dessus, cependant, ne vous donne pas la granularité que vous désirez, cependant, elle vous donne un squelette qui, lorsqu'il est combiné avec l'appartenance à un groupe, un utilisateur peut changer de groupe avec newgrplequel crée efficacement un nouveau shell et un nouvel environnement, puis en utiliser un des approches données dans les autres réponses pour modifier le ~/.bash_historyfichier effectif lors du changement de chapeau pour dire, de cmmgrmanière à newgrppouvoir gérer ce qui ~/.bash_historyest utilisé et enregistré par dossier à mesure que l'on entre et sort du nouveau groupe via la newgrpcommande. Découvrez man newgrp. Il y a des points de départ dans ce sens dans d'autres réponses à cette question. Ceux-ci devraient fonctionner avec le paradigme du groupe UNIX - la plupart des écrous et boulons sont gérés par les routines de démarrage et de sortie du shell, contrôlées par lenewgrpinvocation. Découvrez 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
la source
0

Je présente ici deux variantes, mais applicables uniquement au Z Shell .

Variante 1

C'est ce à quoi j'ai pensé en lisant le titre de votre question. Avec cette variante, vous pouvez basculer entre deux modes d'historique avec ALT+ h: Global ou local , où ce dernier bascule automatiquement vers un historique par répertoire sur chdir . L'historique global accumule toutes les commandes émises.

  • Manifestation

    ~ source src / cd_history
    ~ faire écho à l'histoire mondiale                                                
    histoire mondiale
    ~ mkdir foo bar                                                      
    ~ [ALT-h] 
    ~                          noter l'indicateur de l'histoire locale ->    +
    ~ cd foo +
    ~ / foo fait écho à l'histoire locale dans foo +
    histoire locale à foo
    ~ / foo fc -l +
        1 écho de l'histoire locale à foo
    ~ / foo cd ../bar +
    ~ / bar fait écho à l'histoire locale dans bar +
    histoire locale au bar
    ~ / bar fc -l +
        1 écho de l'histoire locale au bar
    ~ / bar cd ../foo +
    ~ / foo fc -l +
        1 écho de l'histoire locale à foo
        3 cd ../bar
    ~ / foo [ALT-h]                                           
    ~ / foo fc -l                                                          
       55 source src / cd_history
       64 écho à l'histoire mondiale
       65 mkdir foo bar
       66 cd foo
       70 échos de l'histoire locale au bar
       72 cd ../foo
       73 faire écho à l'histoire locale de foo
       74 cd ../bar
    ~ / foo  
  • Le script (à inclure ~/.zshrcou à rechercher)

    # 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

En y repensant, il semble que l'historique par répertoire soit trop fin et vous décrivez également davantage un historique par projet dans votre corps de question. J'ai donc trouvé une autre variante avec une fonction workon pour basculer entre les projets. Chaque projet a son propre fichier historique ~/.zsh_projhistory_[name].

  • Manifestation

    ~ source src / proj_history 
    ~ faire écho à l'histoire mondiale                                                                    
    histoire mondiale
    ~ [ALT-h]                                                               [utiliser workon]
    ~ workon foo [utilisez workon]
    ~ commande echo dans le projet foo [sur proj foo]
    commande dans le projet foo
    ~ fc -l [sur proj foo]
        1 commande echo dans le projet foo
    ~ workon bar [sur proj foo]
    ~ faire écho à un autre projet, nommé bar [sur la barre de projet]
    un autre projet, nommé bar
    ~ fc -l [sur la barre de projet]
        1 écho à un autre projet, nommé bar
    ~ workon foo [sur la barre de projet]
    ~ fc -l [sur proj foo]
        1 commande echo dans le projet foo
        3 workon bar
    ~ [ALT-h]                                                              [sur proj foo]
    ~
    ~ fc -l                                                                                   
       31 Écho de l'histoire mondiale
       36 faire écho à un autre projet, nommé bar
       38 workon foo
       39 Commande echo dans le projet foo
       40 workon bar
    ~ ls -1 .zsh_ *
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • Le script (à inclure ~/.zshrcou à rechercher)

    # 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
la source
0

Après avoir travaillé dans un domaine pendant un certain temps.

histoire> hist1.txt puis histoire plus tard> hist2.txt

Parfois, j'utilise la date pour le nom de fichier. histoire> hist20180727.txt

De cette façon, il existe un historique de commandes récent pour chaque répertoire.

John
la source