Pliki dziennika historii bash / zsh dla katalogu

14

Uważam, że dużo pracuję nad projektem w ustalonym katalogu. Czasami - kilka miesięcy później - muszę coś powtórzyć w tym projekcie, ale nie pamiętam, co zrobiłem. Używam mercurial lub git do śledzenia zmian w plikach, ale chcę mieć możliwość zapamiętania poleceń wydanych w tym katalogu.

Przeszukiwanie mojej historii powłoki nie jest zbyt pouczające. Wszystko już loguję do moich plików historii. * _, Ale chcę listę rzeczy, które zrobiłem w ~ / foo / bar, a nie wszystkich innych (milionów) rzeczy, które zrobiłem w tym tygodniu. Prawdopodobnie nie pamiętam nawet, w którym miesiącu ostatnio pracowałem nad tym konkretnym projektem.

Czy ktoś ma jakieś pomysły, jak plik dziennika katalogu projektu wszystkich poleceń powłoki, których użyłem? Przewiduję polecenie takie jak:

mój projekt

... który ustawiłby plik dziennika powłoki na ~ / myproject / .history.log, załadował poprzednią historię z tego pliku dziennika i może zaktualizował mój monit, aby powiedzieć mi, w którym katalogu pracuję (np. vcprompt, aby zapewnić wersję informacje kontrolne).

Czy jest coś takiego?

Szymon
źródło

Odpowiedzi:

4

W przypadku, gdy jeszcze tego nie rozgryzłeś: szukasz doskonałego pakietu virtualenvwrapper . Jest to wrapper wokół virtualenv Pythona (przejdź do rysunku) i chociaż jest to często określane w przypadku środowisk Pythona, w rzeczywistości jest to bardzo ogólne narzędzie, które spełnia twój przypadek użycia.

Instalacja

pip install virtualenvwrapper

lub

easy_install virtualenvwrapper

i dodaj elementy inicjujące do config powłoki ( ~/.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

Stosowanie

# 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

Masz również ogólne zaczepy, ~/.virtualenvs/{postactivate,postdeactivate,etc}które są wywoływane za każdym razem workon any_project.

Tak więc, na przykład, posiadanie linii export HISTFILE="$VIRTUAL_ENV/bash_history"w ~/virtualenvs/postactivatezaczepie oznacza, że $HISTFILEzmienna będzie za każdym razem rozszerzana do innego projektu.

catalin.costache
źródło
3

Potrzebuję tego również i wymyśliłem wersję, która wykorzystuje zmienną PROMPT_COMMAND firmy Bash :

Wartość zmiennej PROMPT_COMMAND jest sprawdzana tuż przed wydrukowaniem przez Bash każdego głównego monitu. Jeśli ustawiony jest PROMPT_COMMAND i ma on wartość inną niż null, wówczas wartość jest wykonywana tak, jakby została wpisana w wierszu polecenia.

Mówię więc PROMPT_COMMAND = "check_for_local_history" w ~ / .bashrc.my, gdzie check_for_local_historyjest moja funkcja, która sprawdza, czy ostatnio wykonane polecenie było zmianą katalogu, a gdy to prawda, sprawdza nowy bieżący katalog w poszukiwaniu pliku .bash_history . Jeśli tak, użyj go jako pliku historii.

Oto pełna treść: https://gist.github.com/gurdiga/dac8d2e7eb3056d6b839

Vlad GURDIGA
źródło
2

Jedną sztuczką, której używam do budowania podpakietów dla produktu, jest użycie podpowłoki.

W przypadku bash możesz utworzyć skrypt powłoki w następujący sposób:

#!/bin/bash

export PROJECT_DIRECTORY=$(pwd)

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

Następnie $HOME/.project-bashrcwłóż coś takiego:

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

Pozwala to również dostosować monit w .project-bashrcpliku, co może być przydatne.

Nie jestem pewien jak to zrobić zsh. ZDOTDIRMyślę, że musiałbyś zastąpić zmienną. Ale wyglądałoby podobnie.

Cześć!

docwhat
źródło
1

Spójrz na moje skrypty logowania tutaj . Korzystając z jednego z nich, możesz śledzić katalog, w którym się znajdujesz po wydaniu każdego polecenia. Możesz grepzalogować plik polecenia lub inne informacje. Używam długiej wersji w domu i pracy.

Wstrzymano do odwołania.
źródło
Dzięki - przyjrzę się temu. Może zrobić coś blisko tego, czego potrzebuję!
Simon
1

Być może zainteresuje Cię napisana przeze mnie wtyczka o nazwie katalog-historia dla zsh.
Zajrzyj tutaj: https://github.com/tymm/directory-history

Chociaż tak naprawdę nie pasuje do twojego przepływu pracy w moim projekcie , powinien idealnie pasować do twoich potrzeb.

Tworzy historię zawierającą katalogi.
Podczas przeszukiwania historii najpierw otrzymujesz polecenia z katalogu, w którym się znajdujesz.
Jeśli dla tego katalogu nie ma żadnych poleceń, wróci do historii globalnej i zasugeruje polecenia używane w innych katalogach.

tymianek
źródło
1

Jeśli chcesz czegoś prostego, możesz mieć swój .history.logplik jako taki:

#!/bin/cat
some
relevant
commands

Następnie uruchomienie pliku sprawi, catże zostaną w nim wymienione polecenia.
Możesz również pogrupować te polecenia w osobne pliki według funkcji jako konwencji:

.howto.datadump
.howto.restart

Ma to tę dodatkową zaletę, że działa od razu i nie zanieczyszcza środowiska.

Reno
źródło
Alternatywnie możesz użyć README.mdlub utworzyć inne .mdpliki na temat i wskazać je z pliku readme. Dzieje się tak, jeśli masz przyjazny dla źródła interfejs kontroli źródła.
Reno,
1

Aby uzyskać lokalny plik historii dla katalogu, dodałem następujący wiersz do polecenia bash.

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

Polecenie touch .local_historyw katalogu daje mi lokalny plik historii dla wszystkich poleceń wykonanych w tym katalogu, bez utraty głównego pliku historii. Coś podobnego działałoby w Zsh.

Aad Schippers
źródło
0

Przynajmniej w bash HISTFILE jest sprawdzany tylko na początku instancji powłoki. Idea per-dir tutaj nie zadziała, chyba że powyższy przykład „workon” tworzy instancję powłoki.

Może możesz spojrzeć na coś takiego

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

Ale skrypt tworzy również podpowłokę.

Krótko mówiąc, prawdopodobnie potrzebujesz bałaganu na poziomie podpowłoki, aby to zadziałało.

Rich Homolka
źródło
Cholera, miałem nadzieję, że to będzie coś prostego. W każdym razie dzięki!
Simon
0

Pracowałem w domach oprogramowania produkcyjnego, w których tworzyliśmy nowych użytkowników i grupy dla różnych funkcji. Nowe konta użytkowników specjalnie do zarządzania konfiguracją lub kompilacji oprogramowania o różnym poziomie widoczności do innych powiązanych obszarów funkcjonalnych poprzez członkostwo w grupie i ACL, a historia poleceń wykonywana przez powiedzmy, cmmgrzostanie zapisana ~cmmgr/.bash_history, bldmgrpowiązane słowo zostanie zapisane ~bldmgr/.bash_historyitp. Niestety, aby się zalogować, użytkownik musi posiadać własny katalog logowania. Dlatego obszar projektu został utworzony na osobnym dysku. Własność twórcy plików pokazała, który obszar funkcjonalny utworzył pliki w obszarze projektu, dla którego .bash_historymożna sprawdzić odpowiedni.

Powyższe podejście nie zapewnia jednak pożądanej szczegółowości, ale daje szkielet, który w połączeniu z członkostwem w grupie, użytkownik może przełączać grupy, w newgrpktórych skutecznie tworzy nową powłokę i środowisko, a następnie użyć jednego podejść podanych w innych odpowiedziach, aby zmienić ~/.bash_historyplik efektywny przy zmianie kapeluszy, aby powiedzieć, cmmgraby newgrpmógł zarządzać, który ~/.bash_historyjest używany i zapisywany w folderze, gdy ktoś wchodzi i wychodzi z nowej grupy za pomocą newgrppolecenia. Sprawdź man newgrp. Istnieje kilka punktów początkowych wzdłuż tych linii w innych odpowiedziach na to pytanie. Powinny one współpracować z paradygmatem grupy UNIX - większość nakrętek i śrub jest obsługiwana przez procedury uruchamiania i wychodzenia powłoki, kontrolowane przeznewgrpwezwanie. Sprawdź 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
źródło
0

Tutaj przedstawiam dwa warianty, ale dotyczą tylko Z Shell .

Wariant 1

Właśnie o tym pomyślałem, czytając tytuł pytania. W tym wariancie możesz przełączać się między dwoma trybami historii za pomocą ALT+ h: Globalny lub lokalny , przy czym ten drugi automatycznie przełącza się na historię poszczególnych katalogów po chdir . Historia globalna gromadzi wszystkie wydane polecenia.

  • Demonstracja

    ~ source src / cd_history
    ~ echo globalnej historii                                                
    historia globalna
    ~ bar mkdir foo                                                      
    ~ [ALT-h] 
    ~                          zwróć uwagę na wskaźnik historii lokalnej ->    +
    ~ cd foo +
    ~ / foo echo lokalnej historii w foo +
    lokalna historia w foo
    ~ / foo fc -l +
        1 echo lokalnej historii w foo
    ~ / foo cd ../bar +
    ~ / bar echo lokalnej historii w pasku +
    lokalna historia w barze
    ~ / bar fc -l +
        1 echo lokalnej historii w barze
    ~ / bar cd ../foo +
    ~ / foo fc -l +
        1 echo lokalnej historii w foo
        3 cd ../bar
    ~ / foo [ALT-h]                                           
    ~ / foo fc -l                                                          
       55 źródło src / cd_history
       64 echa globalnej historii
       65 mkdir bar foo
       66 cd foo
       70 ech lokalnej historii w barze
       72 cd ../foo
       73 echa lokalnej historii w foo
       74 cd ../bar
    ~ / foo  
  • Skrypt (do włączenia ~/.zshrclub uzyskania)

    # 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 
    }

Wariant 2

Zastanawiając się nad tym ponownie, wydaje się, że historia poszczególnych projektów jest zbyt drobnoziarnista, a w tekście pytań bardziej szczegółowo opisujesz historię poszczególnych projektów. Więc wymyśliłem inny wariant z funkcją workon do przełączania między projektami. Każdy projekt ma swój własny plik historii ~/.zsh_projhistory_[name].

  • Demonstracja

    ~ source src / proj_history 
    ~ echo globalnej historii                                                                    
    historia globalna
    ~ [ALT-h]                                                               [użyj workon]
    ~ workon foo [użyj workon]
    ~ polecenie echo w projekcie foo [on proj foo]
    polecenie w projekcie foo
    ~ fc -l [on proj foo]
        1 polecenie echa w projekcie foo
    ~ workon bar [on proj foo]
    ~ echo innego proj, o nazwie bar [na pasku proj]
    kolejny proj o nazwie bar
    ~ fc -l [na pasku proj]
        1 echo innego proj o nazwie bar
    ~ workon foo [na pasku proj]
    ~ fc -l [on proj foo]
        1 polecenie echa w projekcie foo
        3 pasek roboczy
    ~ [ALT-h]                                                              [on proj foo]
    ~
    ~ fc -l                                                                                   
       31 echa globalnej historii
       36 echo innego proj o nazwie bar
       38 workon foo
       39 polecenie echo w projekcie foo
       40 pasek roboczy
    ~ ls -1 .zsh_ *
    .zsh_history
    .zsh_projhistory_bar
    .zsh_projhistory_foo
  • Skrypt (do włączenia ~/.zshrclub uzyskania)

    # 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
źródło
0

Po pewnym czasie pracy w jednym obszarze.

historia> hist1.txt, a następnie historia> hist2.txt

Czasami używam daty dla nazwy pliku. historia> hist20180727.txt

W ten sposób dla każdego katalogu dostępna jest najnowsza historia poleceń.

Jan
źródło