Jak uzyskać wspólną historię podstawową między różnymi kartami

19

Użyłem odpowiedzi w /unix//a/1292/41729, aby umożliwić wspólną historię w czasie rzeczywistym pomiędzy oddzielnymi terminalami bash. Jak wyjaśniono w powyższej odpowiedzi, osiąga się to poprzez dodanie:

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

# After each command, save and reload history
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Działa to dobrze, jeśli powłoki bash są oddzielne (np. Otwieranie różnych terminali bash za pomocą CTRL+ALT+T. Jednak nie działa, jeśli używam tabs(z otwartego terminala `CTRL + SHIFT + T) zamiast nowych okien. Dlaczego ta różnica w zachowaniu? Jak czy mogę udostępniać historię bash również w różnych zakładkach?

AKTUALIZACJA: Zauważyłem nietypowe zachowanie: jeśli piszę, CTRL+Cto ostatnie polecenie wpisane w dowolnym innym terminalu (zarówno z kartą, jak i bez) jest poprawnie wyświetlane. To tak, jakby CTRL + C wymusił opróżnienie historii, aby następnie została poprawnie udostępniona.

Jako przykład wyjścia (T1 oznacza zacisk 1 i zacisk 2 T2):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<up> (i.e. I press the up arrow)
ls -lah #i.e the last command in terminal 1 is shown rather than the last of terminal 2
^C (i.e. I press CTRL+C)
<up>
cd Documents #the last command issued in terminal 2 is correctly displayed

Mam nadzieję, że może to dać jakąkolwiek wskazówkę!

lucacerone
źródło
Dodałeś to do swojego ~.bashrcpliku? Na marginesie, eksport tych zmiennych jest bezcelowy; po prostu marnuje przestrzeń środowiska.
geirha
@geirha tak, dodałem do mojego pliku .bashrc. Dzięki za komentarz na temat eksportu.
lucacerone

Odpowiedzi:

2

Wygląda na to, że próbujesz uzyskać dostęp do historii drugiego terminala przed synchronizacją. PROMPT_COMMANDjest wykonywany tuż przed wydrukowaniem nowego monitu, tj. po uruchomieniu polecenia i przed wpisaniem następnego polecenia. Tak się nie stanie od razu w T1; musisz spowodować wyświetlenie nowego monitu.

Aby to przetestować, wypróbuj ten wariant na swoich krokach (dodałem dodatkowy <enter>w T1):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<enter>
<up> (i.e. I press the up arrow)

Po dodatkowym naciśnięciu klawisza Enter pojawi się nowy monit, który uruchomi PROMPT_COMMANDi zsynchronizuje Twoją historię, więc spodziewam się, że ta strzałka w górę wyświetli cdzamiast tego ls, jak chcesz. Niestety nie sądzę, że istnieje sposób, aby synchronizacja odbyła się natychmiast we wszystkich terminalach bez uruchamiania żadnych poleceń, jak się wydaje; w efekcie wymagałoby to ciągłej synchronizacji wszystkich historii logowania przez wszystkie sesje logowania, co byłoby ogromnym marnotrawstwem wydajności procesora i dysku.

Paweł
źródło
masz rację, naciśnięcie Enter jest synchronizowane po. Nawet jeśli nie jest to strata pamięci lub procesora jak można wymusić synchronizację (jeśli jest zbyt wiele Ja to zawsze można wyłączyć, ale chciałbym spróbować)?
lucacerone
1

Zadałem to samo pytanie i oto odpowiedź, na którą wpadłem ...

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

history() {
  _bash_history_sync
  builtin history "$@"
}

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

PROMPT_COMMAND=_bash_history_sync
Scott Goodgame
źródło
Źródło: unix.stackexchange.com/a/48116/37944
Radu Rădeanu
dwa wyjaśnienia, zanim spróbuję: czy powinienem usunąć drugą historię - opcje? to idzie w .bashrc, prawda?
lucacerone
niestety to nie działa ...
lucacerone
Każdorazowa HISTFILESIZEzmiana powoduje automatyczną próbę obcięcia istniejącego pliku historii. Zmiana HISTSIZEma podobny wpływ na bieżącą historię. Dla odniesienia zobacz komentarz w variables.cbash src tuż przed sv_histsize.
Brian Vandenberg,
1

dodaj te linie do swojego .bashrcpliku

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

trap 'history -r' USR1 
export PROMPT_COMMAND="history -a ; history -c; ps a | awk '/ bash$/ {system (\"kill -USR1 \" \$1)}'; $PROMPT_COMMAND"

Uwaga:

Początkowo przeprowadzałem testowanie, wysyłając sygnał USR1 do bashowania za pomocą killall, później pomyślałem o użyciu unikalnej nazwy powłoki, kopii bash o nazwie testhell, aby uniknąć zabijania własnych powłok, które mogłyby działać (na przykład procesy cron), ale dziwnie, że nie było pracujący.

Killall nie był wystarczająco selektywny, zastąpiłem go skryptem, który zabija tylko procesy bashowe ściśle do tty ( ps azgłasza tylko procesy powiązane z tty)

Nie zapomnij zrestartować sesji, aby mieć nowy PROMPT_COMMAND, kiedy testowałem, zobaczyłem wiele moich poprzednich testów ułożonych w PROMPT_COMMAND.

Emmanuel
źródło
Nie potrzebujesz nowego użytkownika i drugiej powłoki, możesz po prostu powiedzieć, killallże wysyła sygnał tylko do procesów tego samego użytkownika z dodatkowym -uargumentem , e.g. -u $ (whoami) `.
Philipp Wendler
Myślę, że składnia csh jest niepoprawna ... @PhilippWendler, czy mógłbyś trochę rozwinąć?
lucacerone
Pytanie dotyczy bash, więc użyłem składni bash. Nie wiem csh. W przypadku bash killall -q -USR1 -u $(whoami) bashwysyła sygnał USR1 do wszystkich procesów bash bieżącego użytkownika.
Philipp Wendler
@ Philipp ty btw Nie testowałem dedykowanego rozwiązania powłoki, było to naprawienie przypadku, w którym działałby skrypt brona cron.
Emmanuel
@LucaCerone I przepisane wydaje się działać
Emmanuel
0

Miałem to samo dziwne zachowanie w Yakuake, gdy próbowałem stworzyć skomplikowane polecenie bash, które pokazywałoby liczbę kolejnych logowań. Liczba nie wzrosła dla kart. Moim obejściem było powiedzenie, że Yakuake uruchamia się bashponownie w każdej nowej karcie, zasadniczo rozpoczynając bash w bash. Zaczęło działać bezbłędnie. Może ci też pomoże. Domyślam się, że GUI dla konsoli ładuje konfiguracje bash, a następnie przekazuje je do instancji bash. Może być w stanie się nimi bawić.

Barafu Albino
źródło
Próbowałem załadować bash w bash, ale bezskutecznie :(
lucacerone