Оновіть історію bash на інших терміналах при виході з одного терміналу


15

Я знаю, що це питання є неясним, тому що тут його просять постійно оновлюватидублювати тут).

Те, що я намагаюся досягти, трохи інше. Мені не подобається ідея про своє швидке перезапис файлу кожного lsтипу, який я набираю ( history -a; history -c; history -r).

Я хотів би оновити файл при виході. Це легко (насправді за замовчуванням), але додавати його потрібно замість переписування:

shopt -s histappend

Тепер, коли термінал закритий, я хотів би зробити так, щоб усі інші, які залишаються відкритими, були в курсі оновлення.

Я вважаю за краще це робити, не перевіряючи $PS1на кожному, commandщо я набираю. Я думаю, було б краще взяти якийсь сигнал. Як би ти це зробив? Якщо це неможливо, можливо, просте cronjob?

Як ми можемо розгадати цю головоломку?


1
Зауважте, що zsh робить це нестандартно (і має багато варіантів для точного налаштування спільного використання історії).
Жил 'ТАК - перестань бути злим'

Дякую @Gilles; Смішно, роки за допомогою Linux і я ніколи нічого не пробував, окрім bash. Можливо, прийшов час перевірити щось нове, просто заради розваги.
Д-р Беко

Відповіді:


15

Творчі та залучаючі сигнали, скажете ви? ДОБРЕ:

trap on_exit EXIT
trap on_usr1 USR1

on_exit() {
    history -a
    trap '' USR1
    killall -u "$USER" -USR1 bash
}

on_usr1() {
    history -n
}

Чак, що тут, .bashrcі йди. При цьому використовуються сигнали, щоб повідомити кожному bashпроцесу, щоб перевірити наявність нових записів історії, коли виходить інший. Це досить жахливо, але воно справді працює.


Як це працює?

trapвстановлює обробник сигналу або для системного сигналу, або для одного з внутрішніх подій Баша. EXITПодія будь контрольоване припинення оболонки, в той час як USR1це SIGUSR1, безглуздий сигнал ми привласнюючи.

Щоразу, коли оболонка виходить, ми:

  • Додайте всю історію до файлу явно.
  • Вимкніть SIGUSR1обробник і змусьте цю оболонку ігнорувати сигнал.
  • Відправте сигнал усім запущеним bashпроцесам від одного і того ж користувача.

Коли SIGUSR1прибуває, ми:

  • Завантажте всі нові записи з файлу історії до списку історії оболонки оболонки.

Через способом Баша ручки сигналів, що не буде на самому ділі отримати нові дані історії , поки ви не потрапили Enterв наступний раз, так що це не робить краще на цьому фронті , ніж покласти history -nв PROMPT_COMMAND. Він зберігає читання файлу постійно, коли нічого не сталося, і взагалі немає запису, поки оболонка не вийде.


Однак тут є ще пара питань. Перший полягає в тому, що відповідь за замовчуванням на SIGUSR1- це припинення оболонки. Будь-які інші bashпроцеси (наприклад, запущені сценарії оболонки) будуть знищені. .bashrcне завантажується неінтерактивними оболонками. Натомість завантажується файл, названий користувачемBASH_ENV : ви можете встановити цю змінну у вашому оточенні глобально, щоб вказувати на файл за допомогою:

trap '' USR1

в ньому ігнорувати сигнал в них (що вирішує проблему).

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


Цікаво, якщо ви включили тимчасове штампування у .bashrcфайлі, а потім змусили щось подібне до cronjob і періодично вдаватися до файлу, надсилаючи SIGUSR1відповідний фрагмент, чи зможете ви відновити хронологічну історію стрілки вгору?
forquare

Це акуратне рішення, але за фактом USR1 закінчуються інші процеси. Чи трапляється така поведінка і з USR2?
Д-р Беко

Додам другий коментар, тому що я здивований. Яким чином процес пов'язує термін з USR1? Хіба USR1 не використовується лише користувачем ?? Це якийсь linux bug?? Чому інший процес ловить USR1? (Я знаю, що це не призначено для обговорення тут, але, можливо, я з’ясую це в потрібному місці)
Д-р Беко,

Типова поведінка майже всіх сигналів - це припинення; це вказано в POSIX . Це не помилка. Bash дозволить вам вказати, що сигнал буде ігнорований для всіх його процесів, хоча це добре для наших цілей.
Майкл Гомер

Дякую @MichaelHomer Чи є ця специфікація, яку ви мали на увазі, BASH_ENVяк зазначено у цій відповіді? Або ви знаєте більш стандартний спосіб вимкнути це зло?
Д-р Беко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.