Bash / zsh-Verlaufsprotokolldateien pro Verzeichnis


14

Ich finde, ich arbeite viel an einem Projekt in einem festgelegten Verzeichnis. Manchmal - ein paar Monate später - muss ich etwas an diesem Projekt wiederholen, aber ich kann mich nicht erinnern, was ich getan habe. Ich verwende mercurial oder git, um Änderungen an Dateien zu verfolgen, möchte mich aber daran erinnern können, welche Befehle ich in diesem Verzeichnis ausgegeben habe.

Das Durchsuchen meines Shell-Verlaufs ist nicht sehr informativ. Ich protokolliere bereits alles in meinen. * _-Verlaufsdateien, aber ich möchte eine Liste der Dinge, die ich in ~ / foo / bar getan habe, und nicht alle anderen (Millionen) Dinge, die ich in dieser Woche getan habe. Ich kann mich wahrscheinlich nicht einmal daran erinnern, in welchem ​​Monat ich zuletzt an diesem bestimmten Projekt gearbeitet habe.

Hat jemand irgendwelche Ideen, wie eine Projektverzeichnis-Protokolldatei aller Shell-Befehle, die ich verwendet habe? Ich stelle mir einen Befehl vor wie:

Arbeit an meinem Projekt

... wodurch die Shell-Protokolldatei auf ~ / myproject / .history.log gesetzt, der vorherige Verlauf aus dieser Protokolldatei geladen und möglicherweise meine Eingabeaufforderung aktualisiert wird, um mir mitzuteilen, an welchem ​​Verzeichnis ich arbeite (z. B. vcprompt, um die Version bereitzustellen) Kontrollinfo).

Gibt es da draußen so etwas?

Antworten:


4

Falls Sie dies noch nicht herausgefunden haben: Was Sie suchen, ist das hervorragende virtualenvwrapper- Paket. Es ist ein Wrapper um die virtuelle Umgebung von Python ( siehe Abbildung), und obwohl es häufig in Bezug auf Python-Umgebungen verwendet wird, ist es tatsächlich ein sehr allgemeines Tool, das Ihren Anwendungsfall erfüllt.

Installation

pip install virtualenvwrapper

oder

easy_install virtualenvwrapper

und füge Initialisierungsmaterial in deine Shell-Konfiguration ein ( ~/.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

Verwendung

# 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

Sie haben auch generische Hooks ~/.virtualenvs/{postactivate,postdeactivate,etc}, die jedes Mal aufgerufen werden, wenn Sie workon any_project.

Wenn Sie beispielsweise die Zeile export HISTFILE="$VIRTUAL_ENV/bash_history"im ~/virtualenvs/postactivateHook haben, wird die $HISTFILEVariable jedes Mal auf ein anderes Projekt erweitert.


3

Ich brauche das auch und habe eine Version entwickelt, die die PROMPT_COMMAND-Variable von Bash verwendet :

Der Wert der Variablen PROMPT_COMMAND wird unmittelbar vor dem Drucken jeder primären Eingabeaufforderung durch Bash überprüft. Wenn PROMPT_COMMAND festgelegt ist und einen Wert ungleich Null hat, wird der Wert so ausgeführt, als wäre er in die Befehlszeile eingegeben worden.

Ich sage also PROMPT_COMMAND = "check_for_local_history" in ~ / .bashrc.my, wobei check_for_local_historyeine meiner Funktionen prüft, ob der zuletzt ausgeführte Befehl eine Verzeichnisänderung war, und wenn dies zutrifft, das neue aktuelle Verzeichnis auf die Datei .bash_history überprüft . Wenn es dort ist, verwenden Sie es als Verlaufsdatei.

Hier ist das komplette Wesentliche: https://gist.github.com/gurdiga/dac8d2e7eb3056d6b839


2

Ein Trick, den ich für das Framework zum Erstellen von Unterpaketen für ein Produkt verwende, ist die Verwendung einer Unterschale.

Für Bash können Sie ein Shell-Skript wie folgt erstellen:

#!/bin/bash

export PROJECT_DIRECTORY=$(pwd)

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

Dann $HOME/.project-bashrcsetzen Sie so etwas ein:

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

Auf diese Weise können Sie auch die Eingabeaufforderung in der .project-bashrcDatei anpassen , was nützlich sein kann.

Ich bin mir nicht sicher, wie ich das auch machen soll zsh. Sie müssten die ZDOTDIRVariable überschreiben , denke ich. Aber es würde ähnlich aussehen.

Ciao!


1

Schauen Sie sich hier meine Protokollierungsskripte an . Mit einem von ihnen können Sie verfolgen, in welchem ​​Verzeichnis Sie sich befinden, wenn Sie jeden Befehl ausgeben. Sie können grepdie Protokolldatei für den Befehl oder andere Informationen. Ich benutze die lange Version zu Hause und bei der Arbeit.


Danke - ich werde das untersuchen. Könnte etwas in der Nähe von dem tun, was ich brauche!
Simon

1

Vielleicht interessiert Sie ein Plugin namens Verzeichnisverlauf für zsh, das ich geschrieben habe .
Schauen Sie hier: https://github.com/tymm/directory-history

Obwohl es nicht wirklich zu Ihrer Arbeit im myproject- Workflow passt, sollte es perfekt zu Ihren Anforderungen passen.

Es wird ein Verlauf erstellt, der Verzeichnisse enthält.
Wenn Sie Ihren Verlauf durchsuchen, erhalten Sie zuerst Befehle aus dem Verzeichnis, in dem Sie sich befinden.
Wenn für dieses Verzeichnis keine Befehle mehr vorhanden sind, wird auf einen globalen Verlauf zurückgegriffen und Befehle vorgeschlagen, die in anderen Verzeichnissen verwendet werden.


1

Wenn Sie etwas Einfaches wollen, können Sie Ihre .history.logDatei als solche haben:

#!/bin/cat
some
relevant
commands

catWenn Sie dann die Datei ausführen, werden die darin aufgeführten Befehle angezeigt.
Sie können diese Befehle auch nach Konvention in Funktionen in separaten Dateien gruppieren:

.howto.datadump
.howto.restart

Dies hat den zusätzlichen Vorteil, dass Sie sofort arbeiten und Ihre Umgebung nicht verschmutzen.


Alternativ können Sie README.mdandere .mdDateien pro Thema verwenden oder erstellen und in der Readme-Datei darauf verweisen. Das ist, wenn Sie eine markdown-freundliche Quellcodeverwaltungsoberfläche haben.
Reno

1

Um eine lokale Verlaufsdatei für ein Verzeichnis abzurufen, habe ich meinem Befehl bash prompt die folgende Zeile hinzugefügt.

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

Der Befehl touch .local_historyin einem Verzeichnis gibt mir dann eine lokale Verlaufsdatei für alle in diesem Verzeichnis ausgeführten Befehle, ohne die Hauptverlaufsdatei zu verlieren. Ähnliches würde in zsh funktionieren, denke ich.


0

Zumindest in Bash wird HISTFILE nur zu Beginn der Shell-Instanz konsultiert. Die Per-Dir-Idee funktioniert hier nicht, es sei denn, Ihr 'Workon'-Beispiel oben erstellt eine Shell-Instanz.

Vielleicht kannst du dir so etwas ansehen

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

Das Skript erstellt jedoch auch eine Unterschale.

Kurz gesagt, Sie benötigen wahrscheinlich unordentliche Ebenen von Unterschalen, damit dies funktioniert.


Verdammt, ich hatte gehofft, dass es etwas Einfaches sein würde. Danke trotzdem!
Simon

0

Ich habe in Produktionssoftwarehäusern gearbeitet, in denen wir nur neue Benutzer und Gruppen für verschiedene Funktionen erstellt haben. Neue Benutzerkonten speziell für das Konfigurationsmanagement oder Software-Builds mit unterschiedlichem Grad an Sichtbarkeit in andere verwandte Funktionsbereiche über Gruppenmitgliedschaft und ACL, und der von beispielsweise ausgeführte Befehlsverlauf cmmgrwürde in gespeichert ~cmmgr/.bash_history, bldmgrverwandte Wörter würden in ~bldmgr/.bash_historyusw. gespeichert . Um sich anzumelden, muss ein Benutzer sein Anmeldeverzeichnis besitzen. Daher wurde ein Projektbereich insgesamt auf einer separaten Festplatte eingerichtet. Der Besitz des Dateierstellers hat gezeigt, welcher Funktionsbereich die Dateien im Projektbereich erstellt hat, für die der entsprechende .bash_historygeprüft werden kann.

Der obige Ansatz bietet Ihnen jedoch nicht die gewünschte Granularität, sondern ein Skelett, mit dem ein Benutzer in Kombination mit der Gruppenmitgliedschaft Gruppen wechseln kann, mit newgrpdenen effektiv eine neue Shell und Umgebung erstellt und dann eine verwendet wird von den Ansätzen in den anderen Antworten angegeben, um die effektive ~/.bash_historyDatei zu ändern, wenn Hüte zu sagen wechseln , cmmgrso dass ein newgrpverwalten kann, welche ~/.bash_historypro Ordner verwendet und gespeichert wird, wenn man die neue Gruppe über den newgrpBefehl betritt und verlässt . Auschecken man newgrp. In anderen Antworten auf diese Frage gibt es einige Ansatzpunkte in dieser Richtung. Diese sollten mit dem UNIX-Gruppenparadigma funktionieren - die meisten Schrauben und Muttern werden von den Shell-Start- und Exit-Routinen behandelt, die von der gesteuert werdennewgrpAufruf. Check out 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

Hier stelle ich zwei Varianten vor, die jedoch nur für die Z-Shell gelten .

Variante 1

Daran habe ich beim Lesen Ihres Fragentitels zuerst gedacht. Mit dieser Variante können Sie mit ALT+ zwischen zwei Verlaufsmodi wechseln h: Global oder lokal , wobei letzterer bei chdir automatisch zu einem Verlauf pro Verzeichnis wechselt . Der globale Verlauf sammelt alle ausgegebenen Befehle.

  • Demonstration

    ~ source src / cd_history
    ~ Echo der globalen Geschichte                                                
    Weltgeschichte
    ~ mkdir foo bar                                                      
    ~ [ALT-h] 
    ~                          Beachten Sie den Indikator für die lokale Geschichte ->    +
    ~ cd foo +
    ~ / foo gibt die lokale Geschichte in foo + wieder
    lokale Geschichte in foo
    ~ / foo fc -l +
        1 Echo lokale Geschichte in foo
    ~ / foo cd ../bar +
    ~ / bar gibt die lokale Geschichte in bar + wieder
    lokale Geschichte in Bar
    ~ / bar fc -l +
        1 Echo lokale Geschichte in Bar
    ~ / bar cd ../foo +
    ~ / foo fc -l +
        1 Echo lokale Geschichte in foo
        3 cd ../bar
    ~ / foo [ALT-h]                                           
    ~ / foo fc -l                                                          
       55 source src / cd_history
       64 Echo globale Geschichte
       65 mkdir foo bar
       66 cd foo
       70 Echo lokale Geschichte in Bar
       72 cd ../foo
       73 Echo lokale Geschichte in foo
       74 cd ../bar
    ~ / foo  
  • Das Skript (um aufgenommen zu werden ~/.zshrcoder bezogen zu werden)

    # 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

Wenn Sie noch einmal darüber nachdenken, scheint die Per-Dir-Historie zu feinkörnig zu sein, und Sie beschreiben in Ihrem Fragetext auch eher eine Pro-Projekt-Historie. Also habe ich mir eine andere Variante mit einer Workon- Funktion ausgedacht , um zwischen Projekten zu wechseln. Jedes Projekt hat eine eigene Verlaufsdatei ~/.zsh_projhistory_[name].

  • Demonstration

    ~ source src / proj_history 
    ~ Echo der globalen Geschichte                                                                    
    Weltgeschichte
    ~ [ALT-h]                                                               [Arbeit verwenden]
    ~ workon foo [benutze workon]
    ~ echo Befehl im Projekt foo [auf proj foo]
    Befehl im Projekt foo
    ~ fc -l [auf proj foo]
        1 Echo-Befehl im Projekt foo
    ~ workon bar [auf proj foo]
    ~ Echo eines anderen Projekts mit dem Namen bar [auf proj bar]
    Ein weiteres Projekt namens Bar
    ~ fc -l [auf proj bar]
        Ich gebe ein anderes Projekt mit dem Namen bar wieder
    ~ workon foo [auf proj bar]
    ~ fc -l [auf proj foo]
        1 Echo-Befehl im Projekt foo
        3 Workon Bar
    ~ [ALT-h]                                                              [auf proj foo]
    ~
    ~ fc -l                                                                                   
       31 Echo globale Geschichte
       36 Echo ein anderes Projekt namens Bar
       38 workon foo
       39 echo befehl im projekt foo
       40 Workon Bar
    ~ ls -1 .zsh_ *
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • Das Skript (um aufgenommen zu werden ~/.zshrcoder bezogen zu werden)

    # 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

Nachdem ich eine Weile in einem Bereich gearbeitet habe.

history> hist1.txt dann später history> hist2.txt

Manchmal verwende ich das Datum für den Dateinamen. history> hist20180727.txt

Auf diese Weise gibt es für jedes Verzeichnis einen aktuellen Befehlsverlauf.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.