Історія BASH обрізана до 500 рядків на кожному вході


22

Чомусь я не можу заставити свою систему зберігати свою історію BASH після перезавантаження. Ось відповідні розділи мого ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND='history -a; updateWindowTitle'
export HISTCONTROL=ignoredups
export HISTSIZE=9999
export HISTFILESIZE=999999
export HISTFILE="$HOME/.bash_history"

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

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

За випадковості, що там можуть бути інші відповідні команди, ви можете переглянути всю мою ~/.bashrc тут .

Отже, чого я пропускаю? Чому мою історію не збережено? Якщо хтось думає, що інший файл може бути релевантним, дайте мені знати, і я опублікую його. Я перевірив, запустивши grep -i hist \.*в моєму , $HOMEякий показав , що релевантно тільки .файл , що містить рядок histабо HISTбув .bashrc.

Я запускаю Linux Mint Debian Edition, GNU bash, версія 4.2.36 (1) -release (x86_64-pc-linux-gnu) і мій улюблений емулятор терміналу (на випадок, якщо це доречно) terminator.


ОНОВЛЕННЯ:

На підставі пропозиції @ mpy в коментарях я змінив ~/.bashrcналаштування HISTFILE=~/bash_historyна відміну від типового, ~/.bash_historyі це, здається, вирішило проблему для інтерактивних оболонок . Оболонки для входу все ще демонструють однакову поведінку, історія врізана в 500рядки. Однак HISTу відповідних файлах не встановлені пов'язані змінні:

$ for f in /etc/profile ~/.profile ~/.bash_profile ~/.bash_login; do \
   echo -ne "$f :"; echo `grep HIST $f`; \
done
/etc/profile :
/home/terdon/.profile :grep: /home/terdon/.profile: No such file or directory
/home/terdon/.bash_profile :grep: /home/terdon/.bash_profile: No such file or directory
/home/terdon/.bash_login :grep: /home/terdon/.bash_login: No such file or directory
$ grep -r HIST /etc/profile.d/  <-- returns nothing

Отже, чому встановлення, HISTSIZEа HISTFILESIZEв ~/.bashrcнедостатній, якщо я чітко не встановив $HISTFILEщось інше, ніж за замовчуванням ~/.bash_history?


Ви власник .bash_history або root? Do ls -l .bash_history
Аднан Бхатті

1
@MSStp так, він належить мені. Дякую за пропозицію, але я не бачу, як це може бути проблема з дозволом у будь-якому випадку, або я читав / записував доступ до нього, або не знаю. Оскільки якась історія збережена, я чітко це роблю. Якщо в bash було налаштування, яке спричинило проблеми, коли цей файл не належить користувачеві, він або скаржиться, або весь функціонал історії не працюватиме.
тердон

коли ви виконуєте historyкоманду, результат, який ви бачите, ідентичний тому, що ви бачите, працює cat .bash_history, крім номерів рядків? Я маю на увазі, чи historyвказано часові позначки часу чи іншу інформацію? Причина, про яку я запитую, - якщо ви бачите ці езотеричні речі, це означає, що є інший модуль / функція / програма, який псується з історією оболонки і неправильна або помилкова версія будь-якої, що може бути, може спричинити вам горе .
Мельбурслан

@Mel_Burslan так, це те саме, різниця лише в номерах рядків.
тердон

2
Гаразд, дещо дивна пропозиція, але це теж натхненна проблема ;): Спробуйте інший файл як HISTFILE, а не за замовчуванням ~/.bash_history. Дуже побудоване пояснення: я припускаю, що bash - це ваша оболонка за замовчуванням, тому при запуску системи неінтерактивна оболонка є батьківщиною вашого X-сеансу (я також припускаю, що ви використовуєте X), який нічого не знатиме про параметр histappend (як .bashrc лише читайте за допомогою інтерактивних оболонок), доки ця батьківська оболонка працює все добре, але після припинення (тобто припинення роботи системи) вона перекриє ~/.bash_history(що за замовчуванням) і заплутує вашу історію ...
mpy

Відповіді:


17

Проблема фактично зводиться до різної поведінки оболонок для входу та не входу в систему. Я встановив змінні, які керують історією в моєму ~/.bahsrc. Цей файл не читається, коли запускається оболонка для входу, він читається лише інтерактивними оболонками без входу (від man bash):

Коли bash викликається як інтерактивна оболонка для входу, або як неінтерактивна оболонка з --loginможливістю, вона спочатку зчитує та виконує команди з файлу /etc/profile, якщо такий файл існує. Прочитавши цей файл, він шукає ~ / .bash_profile, ~/.bash_loginі ~/.profile, у цьому порядку, і зчитує та виконує команди з першого, який існує та читається. --noprofileВаріант може бути використаний , коли оболонка запускається , щоб пригнічувати таку поведінку.

[. . . ]

Коли запускається інтерактивна оболонка, яка не є оболонкою для входу, bash зчитує та виконує команди з ~ / .bashrc, якщо цей файл існує. Це може бути пригнічено за допомогою параметра --norc. Параметр файлу --rcfile змусить bash читати та виконувати команди з файлу замість ~ / .bashrc.

Тому щоразу, коли я входив у систему, або .historyпотрапляв на tty, або використовував ssh, файл ставав усіченим, оскільки я також не встановив його потрібного розміру ~/.profile. Я нарешті зрозумів це і просто встановив змінні, ~/.profile куди вони належать , а не~/.bashrc

Таким чином, причиною моєї ~/.historyобрізання було те, що я встановив лише ІСТОРІЙНІ змінні у файлі, який читають інтерактивні оболонки, що не входять в систему, і тому кожен раз, коли я запускав інший тип оболонки, змінні будуть ігноруватися, і файл буде вирізаний відповідно.


Дуже хороший момент, дякую за обмін! Однак я не згоден з цим файлом: не читається, коли запускається оболонка для входу, він читається лише інтерактивними оболонками. Оскільки оболонка для входу може бути і інтерактивною. Інакше весь механізм історії не мав би сенсу. IMHO .bashrcне зчитується (неінтерактивні оболонки для входу АБО).
mpy

@mpy Дійсно, вибачте, я мав на увазі інтерактивні оболонки без входу. Відповідь відредаговано.
тердон

1
@terdon, загальна ідіома полягає в тому, що параметри інтерактивної оболонки не входять у ~ / .profile або ~ / .bash_profile. Параметри інтерактивної оболонки вводяться в ~ / .bashrc. Щоб уникнути необхідності підтримувати налаштування в двох місцях, наступні команди можуть бути розміщені у верхній частині ~ / .bash_profile: export BASH_ENV=~/.bashrc ; if [ -f ~/.bashrc ]; then . ~/.bashrc; fi..., а вгорі ~ / .bashrc поставити чек, щоб переконатися, що ви дійсно працюєте інтерактивно: [ -z "$PS1" ] && return... Звичайно, це просто ідіома.
Noah Spurrier

1
@NoahSpurrier BASH_ENVне актуальний, він впливає лише на неінтерактивні оболонки. Що стосується "ідіоми", то Дебіан почав щось і з чим я особисто не згоден. У xsetмоєму файлі .bashrc часто є графічні параметри ( тощо), і я не хочу, щоб ті були активними, коли я запускаю оболонки для входу або з tty, або через ssh. Я хочу, щоб мій .profile та .bashrc були окремими. Багато (хоча і не всі) менеджери входу джерело .profile, коли ви входите в систему, так що глобальні змінні найкраще встановлюються там, де вони будуть читатися лише один раз, а не кожен раз, коли ви відкриваєте термінал.
тердон

1
@WilsonF так. Файли читаються послідовно, а особисті файли ( ~/.profileабо ~/.bashrc) читаються останніми. Все, що встановлено в них, матиме перевагу над глобальними налаштуваннями. Ви абсолютно праві, вам не слід встановлювати ці змінні /etc/bash.bashrc. Використовуйте ~/.profile(або ~/.bash_profile) натомість.
тердон

11

Моя пропозиція - використовувати інший файл як HISTFILE, а не за замовчуванням ~/.bash_history.

Хоча я не маю аналітичного пояснення, я спробую окреслити, що призвело мене до цієї пропозиції: Якщо ви використовуєте bashв якості оболонки за замовчуванням (логін), а також використовуєте X(що обоє дуже ймовірно), у вас є запущений bashекземпляр відразу після (графічний ) логін:

systemd
 ...
  |-login
  |   `-bash      <<====
  |       `-slim
  |           |-X -nolisten tcp vt07 -auth /var/run/slim.auth
  |           |  `-{X}
  |           `-fluxbox
  |               `-xterm -bg black -fg white
  |                   `-bash
 ...

Я думаю, що цей екземпляр є оболонкою для входу, тому він не читає ваш ~/.bashrcі, отже, нічого не буде знати про histappendваріант:

man bash (1) : Коли запускається інтерактивна оболонка, яка не є оболонкою для входу , bash читає та виконує команди з /etc/bash.bashrc та ~ / .bashrc, якщо ці файли існують. (...)

Поки ця "батьківська оболонка" працює, все нормально, але після її закінчення (тобто припинення роботи системи) вона буде переосмислена ~/.bash_history(тому що це значення за замовчуванням) і заплутує вашу історію або відключить її в системі, почне (знову за замовчуванням) 500 лінії. (А може, і те й інше ...)

Мене також вражає, що недостатньо включати конфігурацію історії ~/.bashrc, оскільки це не повинно бути таким рідкісним налаштуванням. Я не маю пояснення цьому.


Що стосується вашої проблеми, що "оболонки входу все ще демонструють однакову поведінку", ви можете спробувати включити конфігурацію історії також у ~/.bash_profile:

man bash (1) : Коли bash викликається як інтерактивна оболонка входу, або як неінтерактивна оболонка з опцією --login, вона спочатку зчитує та виконує команди з файлу / etc / profile, якщо цей файл існує. Прочитавши цей файл, він шукає ~ / .bash_profile, (...)

На жаль, я не можу опублікувати більш виправдане пояснення з деталями моєї власної bashконфігурації, оскільки я zshхлопець ...


2
Явно встановивши параметри історії в моєму ~/.bash_profileвирішенні проблеми. Зараз я використовую ~/.bash_historyяк мій файл історії, але просто додав усі рядки, ~/.bashrcпоказані в моєму запитанні, до ~/.bash_profile. Ще не впевнений, хто викручував інтерактивні оболонки, але, здається, зараз це працює, дякую!
тердон

1
Вибачте за неприйняття, але я забув опублікувати відповідь із поясненням того, що відбувається. Я зрозумів це за допомогою допомоги @Gilles деякий час тому і, нарешті, обійшов питання щодо публікації відповіді. Я хотів прийняти своє, тому що він фактично пояснює проблему, а не пропонує (дуже хороший) спосіб вирішення та може допомогти майбутнім відвідувачам.
тердон

2

Оскільки всі ваші налаштування впорядковані відповідно до відповідної сторінки, а оскільки файл історії не обмежений розміром (байтами), я можу придумати єдине можливе пояснення. Це стосується того, як гине оболонка.

Згідно з онлайн-довідкою, витончений вихід (збережена історія) відбувається лише тоді, коли оболонка отримує SIGHUP. Я не можу пояснити, як ваша система поширює сигнали під час перезавантаження, але я підозрюю, що ваша оболонка закривається за допомогою SIGKILL або SIGPWR.

Це може бути тому, що ваш WM працює асинхронно (чекайте), а емулятор термінала породився з WM, де bash отримує сигнал, що примушує вихід, крім SIGHUP. Можливо також, що ОС повинна швидко відправити "остаточне вбивство" всім процесам до того, як початковому витонченому SIGHUP вдасться дістатися до оболонки через X -> WM -> xterm, можливо, тому що для виходу X або WM потрібно більше часу, ніж потрібно, щоб ОС була готова знищитись.

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

Я помітив history -aу вашому запитанні, і я не можу придумати, чому цього не було б достатньо для збереження історії.

Ви можете вирішити проблему, з’ясувавши, що насправді вбиває ваш баш, і перейдіть до з'ясування, звідки походить сигнал, і виправити проблему там, або просто стерти історію, коли ви знаєте, який сигнал останній (якщо припустити, що до цього часу диски ще в мережі ):

trap "echo got 1  >/tmp/sig1;  exit" SIGHUP
trap "echo got 2  >/tmp/sig2;  exit" SIGINT
trap "echo got 15 >/tmp/sig15; exit" SIGTERM
 .. and so on...

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

людина баш

Під час запуску (...) Файл, названий значенням HISTFILE, обрізається, якщо необхідно, щоб він містив не більше кількості рядків, визначених значенням HISTFILESIZE (+ 500 за замовчуванням).

Якщо параметр оболонки histappend включений (+ тут ​​за замовчуванням тут), рядки додаються до файлу історії, інакше файл історії буде перезаписаний.

онлайн-довідник

3.7.6 Сигнали

Коли Bash є інтерактивним, за відсутності пасток він ігнорує SIGTERM (так, що "kill 0" не вбиває інтерактивну оболонку), а SIGINT вловлюється та обробляється (щоб вбудований режим очікування був переривним). Коли Bash отримує SIGINT, він виривається з усіх циклів виконання. У всіх випадках Баш ігнорує SIGQUIT. Якщо діє контроль за роботою (див. Контроль роботи), Bash ігнорує SIGTTIN, SIGTTOU та SIGTSTP.

Не вбудовані команди, запущені Bash, мають обробники сигналів, встановлені на значення, успадковані оболонкою від свого батьківського. Якщо управління роботою не діє, асинхронні команди ігнорують SIGINT та SIGQUIT на додаток до цих успадкованих обробників. Команди, що виконуються в результаті заміни команд, ігнорують сигнали управління роботою клавіатури SIGTTIN, SIGTTOU та SIGTSTP.

Оболонка виходить за замовчуванням після отримання SIGHUP. Перед виходом інтерактивна оболонка надсилає SIGHUP на всі завдання, запущені або зупинені. Зупинені завдання надсилаються SIGCONT, щоб переконатися, що вони отримують SIGHUP. Щоб оболонка не посилала сигнал SIGHUP на певну роботу, його слід видалити з таблиці завдань із відключеним вбудованим (див. Вбудований контроль роботи) або позначити, щоб не отримувати SIGHUP, використовуючи відключення -h.

Якщо параметр оболонки huponexit був встановлений за допомогою shopt (див. Shopt Builtin), Bash надсилає SIGHUP на всі завдання, коли виходить інтерактивна оболонка входу.

Якщо Bash чекає завершення команди і отримує сигнал, для якого встановлено пастку, пастка не буде виконана, поки команда не завершиться. Коли Bash чекає асинхронної команди за допомогою вбудованого очікування, прийом сигналу, для якого встановлена ​​пастка, призведе до негайного повернення вбудованого очікування зі статусом виходу, більшим за 128, одразу після цього пастка виконується.

показовий знімок екрана

сигнали


Я не дуже розумію те, що ти робиш на цьому скріншоті. Що це те, /tmp/psoщо ти вбиваєш? Я бачу вашу думку щодо різних сигналів вбивства (хоча, як ви кажете, я думав, що це з чим history -aборотися). Я тестую це на деякий час і звітую назад.
тердон

$ cat tmp / ps * \ n ps -o pid = | head -n1> ~ / tmp / pso \ n 17201 \ n
Ярослав Рахматуллін

0

Перевірте / etc / profile та /etc/profile.d/*

Можливо, там щось зіпсується з налаштуваннями історії.


Дякую, але grep -r HIST /etc/profile.d/нічого не повертає, і я вже перевірив /etc/profile.
тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.