Czy możliwe jest natychmiastowe zapisanie do .bash_history?

124

I często otwierają wiele, wiele zacisków [Teraz mam 7 otwarte na tej przestrzeni roboczej] i szukać często historyze grepznalezienie polecenia Właśnie napisany niedawno, ale nie chcę, aby dopaść terminal, a następnie przewiń w górę i szukam tego więcej, itp. Czasami moje terminale zamykają się bez „wyjścia”, a wszystko, co napisałem, ginie [Czasem potrzebuję czegoś, co napisałem w terminalu, który został zabity].

Czy istnieje sposób, aby to zrobić, aby każdy terminal natychmiast zapisywał .hash_history? lub przynajmniej raz na minutę, czy coś takiego?

Matt
źródło
2
Zwykle używam control-rdo wyszukiwania wstecz w historii poleceń jednego basha. Bardziej wygodne niż history | grepchyba, że ​​potrzebujesz wyrażenia regularnego.
Peter Cordes,

Odpowiedzi:

92

Proste rozwiązanie wyszczególnione w Aktualizuj historię Bash w czasie rzeczywistym .

Mówi się, aby umieścić te polecenia w konfiguracji .bashrc:

shopt -s histappend
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"

Pierwsze polecenie zmienia .historytryb pliku na dołączanie. A drugi konfiguruje history -apolecenie, które będzie uruchamiane przy każdym znaku zachęty powłoki. -aNatychmiast zapisuje prąd / nowe linie do pliku historii.

Powiązane z Zsh:

Mario
źródło
1
cóż, tego rodzaju prace. Próbowałem więcej testów i wydaje się, że działa tylko na pierwsze polecenie. czy to działa poprawnie dla ciebie?
Matt
54

Spróbuj umieścić to w .bashrc:

shopt -s histappend                      # append to history, don't overwrite it
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Kredyt tutaj: https://stackoverflow.com/questions/103944/real-time-history-export-amongst-bash-terminal-windows/3055135

history -cusuwa historię uruchomionej sesji. Spowoduje to zmniejszenie licznika historii o kwotę $HISTSIZE. history -rprzeczytaj zawartość $HISTFILEi włóż je do bieżącej historii uruchomionych sesji. Spowoduje to podniesienie licznika historii o liczbę linii w $HISTFILE.

Myślę, że oznacza to, że polecenia są dostępne niemal natychmiast (masz jeden terminal, pisz echo 1, drugi terminal echo 2, pierwszy echo 3i po dwukrotnym naciśnięciu strzałki w dół powinieneś mieć echo 2dostęp. Musisz wydać polecenie w danym terminalu, aby mieć dostęp do tego, co ma zostało napisane.

łyk
źródło
Znakomity! Dzięki. Zastanawiam się, dlaczego te opcje nie są udokumentowane w man history...
artfulrobot
10
@artfulrobot: To polecenie jest bashwbudowane, więc zostało opisane w man bash. Możesz także użyć help history.
pabouk
2
Mam skonfigurowane zsh, aby działało w ten sposób: każda powłoka śledzi swoją WŁASNĄ historię (a wcześniej połączoną historię), a każde polecenie jest dołączane do połączonej historii. Jest to inna i lepsza niż zawsze historia przeładowywania dla każdego polecenia dla każdej powłoki, ponieważ zwykle mam inny „wątek pracy” lub „zadanie” dla każdego terminalu powłoki. Myślę, że to jest różnica między tym -ra -cposiadaniem -a.
Steven Lu,
Więc czego dokładnie używasz? history -c; history -r? Wydaje mi się, że to jest lepsze dla ciebie, byłoby lepsze dla mnie tylko czasami, często używam kilku powłok do wykonania jednej pracy, więc wolę mieć jak najwięcej historii. Właściwie mam na myśli, że polecenie zostaje zapisane w historii dopiero po jego zakończeniu. zazwyczaj, kiedy rozpoczynam sesję ssh do jednego hosta i chcę otworzyć kolejną, gdy pierwsza jest jeszcze uruchomiona, muszę ją ponownie wpisać, ponieważ nie została jeszcze zapisana w historii.
sup
Wydaje mi się, że nigdy nie trzymałem się wystarczająco długo, aby wymyślić, jak bash jednocześnie śledził równoległe wątki historii (na podstawie instancji powłoki), jednocześnie zapisując historię do głównego pliku historii. Zsh sprawia, że ​​jest to o wiele łatwiejsze, a ponadto zdefiniowałem funkcję zsh, aby wypisać wiele fantazyjnych metadanych do mojego pliku z rozszerzoną historią . Stało się to raczej niezbędne. W każdym razie mechanizm precmd () i preexec () dla zsh get args opisujący wprowadzone polecenie. Wtedy staje się banalne, aby przekierować to do plików. history -amoże wystarczyć
Steven Lu
38

Mam duży plik historii z około 100 000 pozycji, a warianty, które usuwają listę historii i czytają cały plik historii (używając history -ci history -r) wprowadzają zauważalne (może 0,2 sekundy) opóźnienie przed wyświetleniem monitu. Używanie history -ntak, aby tylko nowe linie były odczytywane z pliku historii, jest szybsze:

shopt -s histappend
PROMPT_COMMAND='history -a;history -n'

PROMPT_COMMAND nie musi być eksportowany, ponieważ jest to zmienna powłoki.

nisetama
źródło
Znakomity! Nigdy więcej utraconej historii po zerwaniu połączenia!
Tobia,
To jest cudowne. Dołączając do pliku i czytając z pliku, udostępni historię na wielu terminalach.
wisbucky
3

Uwaga do wszystkich innych odpowiedzi (które są w zasadzie to samo):

Ustawienie PROMPT_COMMAND="history -a;$PROMPT_COMMAND"w .bashrc(lub znajomych) wystarczy.

Ponadto możesz ręcznie uruchomić, history -agdy chcesz „wykonać migawkę” historii w bieżącej sesji.

Polecenie shopt -s histappendnie jest potrzebne, ponieważ history -azawsze dodaje nowe wiersze do pliku i nigdy go nie zastępuje. Ponadto, przynajmniej od wersji Bash 4, histappendzachowanie jest domyślne.

Guss
źródło
Na moim komputerze Mac 10.13.6 wydawało się, że nie działałoby bez shopt -s histappend. Zauważ też, że dodałem go do mojego~/.bash_profile
ubershmekel
Prawdopodobnie w Twoim systemie jest inne ustawienie, które zostało wyłączone histappend, ponieważ jest to zachowanie domyślne. Szukałem tego, ale nie mam dostępu do komputera Mac.
Guss