Дивна поведінка історії баш при запуску декількох сеансів


15

Як зберігається історія командного рядка, коли я використовую кілька вікон терміналів? Я знаю, що він зберігається, .bash_historyале я не бачу логіки того, що використовується історія, якщо я відкрию нове вікно. Це майже не відчуває себе недетермінованим в тому сенсі, що я ніколи не знаю, яку команду я побачу, якщо спробую використовувати стрілку вгору в новому вікні.

Хтось може це пояснити?

Чи є спосіб керувати історією таким чином, щоб я міг повторно використовувати історію з певного вікна?

Відповіді:


14

Щоб зрозуміти поведінку історії баш-спочатку, ви повинні знати наступне:

  1. У файлі історії є історія.
  2. Існує історія в пам'яті баш-процесу.
  3. Історія в пам'яті одного bash-процесу не синхронізується з історією в пам'яті будь-якого іншого bash-процесу.
  4. Історія в пам'яті процесу bash не синхронізується з історією у файлі, якщо явно не запитується до або під час якоїсь конкретної події (див. Нижче).

Використовуючи налаштування за замовчуванням, життєвий цикл баш-сеансу щодо історії є таким:

  1. Під час запуску bash прочитає файл історії. Вміст файлу історії тепер знаходиться в пам'яті процесу bash.
  2. Під час звичайного використання обробляється лише історія пам'яті.
  3. Під час відключення історія в пам'яті записується у файл історії, перезаписуючи будь-який попередній вміст файла історії.

Здається, неспостережна поведінка, яку ви спостерігали, здебільшого пояснюється тим, що вміст файлу історії завжди є історією останнього закритого bash-сеансу, а bash читає файл історії лише під час запуску.

Прочитайте інструкцію bash для більш детального пояснення процесу запуску та відключення.

Зауважте, що під налаштуваннями за замовчуванням я маю на увазі параметри за замовчуванням від bash. Ваш дистрибутив, можливо, забезпечив .bashrc(або /etc/bash.bashrc), що змінить цю поведінку.

Увімкнувши опцію оболонки, histappendви можете сказати bash, щоб додати, а не перезаписувати файл історії. Можна ввімкнути histappendвикористання команди shopt -s histappend. Щоб ця опція завжди була включена, вам слід ввести команду у свій .bashrc(або інший файл ініціалізації). Детальніше про shoptкоманду читайте в посібнику з bash

Зауважте, що включення histappendне значно зменшить, здавалося б, недетерміновану поведінку. Це тому, що кожен баш-сеанс все ще має власну історію в пам'яті. Можна мати в основному синхронізовану історію баш. Існує посібник, як отримати кожен процес bash, щоб мати історію синхронізованої історії в потоці під час переповнення стека .

за допомогою вбудованої команди historyви можете явно сказати bash, щоб прочитати історію з файлу в пам'ять або записувати з пам'яті в файл. Наприклад: history -rпрочитає вміст файла і додасть його до історії в пам'яті. history -wзапише поточну історію з пам'яті у файл, перезаписуючи попередній вміст. Це в основному те, що відбувається під час відключення. Детальніше про historyкоманду читайте в посібнику з bash

Для повноти тут перелік внутрішніх змінних, які змінюють поведінку історії:

  • HISTFILE: файл, з якого слід читати та записувати історію.
  • HISTFILESIZE: максимальна кількість рядків для файлу історії.
  • HISTSIZE: максимальна кількість рядків для історії в пам'яті.
  • HISTCONTROL, HISTIGNORE, HISTTIMEFORMAT: Чи не має відношення до цієї дискусії. Детально прочитайте посібник з bash .

Гарне пояснення. Ви згадали про відключення, а як щодо вбивства сеансу терміналу? Сеанс можна вбити через вихід, або через інтерфейс користувача або за допомогою інших засобів, таких як перепад мережевого з'єднання. Якщо весь файл історії замінено і у вас є кілька сеансів, ви хочете сказати, що історія з останнього закритого буде використовуватися у файлі історії? Це може пояснити недетерміновану поведінку.
Алекс Гітельман

точка життєвого циклу (3) невірна. Схоже, що лише перший баш-сеанс коли-небудь запише в файл історії. Тест: відкрийте 2 сеанси в порядку, b. Зробіть «ехо привіт» у б . Потім вийдіть в b . Потім відкрийте нову сесію c . Цей сеанс не буде лунати в його історії.
user606723

@AlexGitelman: якщо забито процес bash, він не матиме можливості перезаписати файл історії. і так, історія останнього закритого сеансу - це та, яка буде у файлі історії.
lesmana

@ user606723: пункт 3 правильний. прочитайте посібник з баш. експериментуйте знову, використовуючи мінімальний .bashrcфайл. зауважте, що ваш розподіл може змінити деякі налаштування в /etc/bash.bashrc. спеціально перевірте варіант оболонки histappend.
lesmana

2

http://www.gnu.org/software/bash/manual/bashref.html#Using-History-Interactively

Можливо, ви зможете маніпулювати тим, як записується файл історії за допомогою одного з терміналів, тобто виконувати "history -a" або "history -w" в терміналі, в який потрібно зберегти історію, а потім "history -r" в інші термінали. Залежить від того, що ви хочете зробити.


0

AFAIK, команди bash зберігаються після припинення сеансу SSH. Отже, команди не зберігаються, коли сеанс закінчується аномально (наприклад, через збій у мережі). Я говорю тут про сеанси SSH. Місцеві термінали можуть використовувати подібний підхід.

Під час відкриття декількох сеансів одночасно команди, введені на одному сеансі, не відображаються на іншому, поки вони обидва активні. Однак ви побачите ці команди, коли ви закінчите сеанс, і знову відкрийте їх.


Це не поведінка, яку я зазнав. Я можу підтвердити це, зробивши швидкий тест, коли я відкриваю сеанс ssh, виконую команду та витончений вихід. У цьому випадку у мене був ще один раніше активний сеанс ssh. У цьому попередньому сеансі bash я перевіряю .bash_history і не знаходжу нічого записаного. Мені здається, що перший запущений сеанс bash є єдиним, який закінчує запис у .bash_history.
user606723

Припинення сеансу не вплине на поточно запущені сесії, але це вплине на нові сесії!
Халед

Що робити, якщо через інтерфейс користувача я закриваю не вікно SSH, а вікно терміналу Gnome?
Алекс Гітельман

Це потрібно перевірити. Наразі у мене немає доступу до терміналу Gnome!
Халед

@Khaled, протестований, не впливає на нові сеанси. (Я перевірив .bash_history раніше, але де bash отримує історію команд для нових сесій, я так знав, що це не буде; я не працюю, але я все одно humour'ed вас.)
user606723
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.