bash history: переписуємо історію
January 6, 2024
Проблема із баш історією #
Колись давно я вважав, що мати таймстемп для кожної виконаної команди у консолі то гарна ідея.
Розробники башу вважали так само, тому за бажання це можна легко налаштувати:
Ось оця команда у профілі
export HISTTIMEFORMAT="[%F %T] "
змушує історію башу виглядати отак:
12715 [2024-01-06 22:24:48] gs
12716 [2024-01-06 22:24:50] git diff
12717 [2024-01-06 22:24:54] git add -u
12718 [2024-01-06 22:24:54] gs
12720 [2024-01-06 22:25:41] gs
12721 [2024-01-06 22:27:56] history
12722 [2024-01-06 22:28:16] history | wc -l
12723 [2024-01-06 22:28:24] history | head -10
12724 [2024-01-06 22:28:24] history | head -10
12725 [2024-01-06 22:28:38] history | head -10 | awk '{print $5}'
Однак виявилася невеличка проблема - всього записів у історії - 12к, тоді як унікальних лише ~5к, тобто оверхед ледве не втричі..
$ history | awk -F] '{print $2}' | wc -l
12741
$ history | awk -F] '{print $2}' | sort -u | wc -l
4741
Виходить, включення таймстемпу приводить до того, що баш ігнорує (чи не може обробити нормально) налаштування
export HISTCONTROL=ignoreboth:erasedups
яке мало призвести до відсутності дублікатів в історії.
Робимо бекап і фіксимо.
Робимо бекап #
Позаяк дотфайли в мене лежать в гіт-репозиторії, то забекапитися досить просто:
j dotfiles && git add .bash_history && git cm 'SAVE: before changing bash history'
Фіксаємо #
У мене профіль, як і багато іншого, менеджиться через власноруч написану ансіблову плейбуку, тому конфіги я не редагую напряму, а редагую шаблони і вже потім оновлюю все ансіблом.
Коментуємо строчку із export HISTTIMEFORMAT="[%F %T] "
у шаблоні баш-профайлу
Ще нам знадобиться sponge
, тому треба додати його до списку brew-пакетів
Закриваємо всі сесії башу, запускаємо zsh
і оновлюємо баш-профіль та пакети brew:
./playbook-init.yml --tags bash,brew
Переписуємо стару історію #
Після зроблених змін все рівно у поточному файлі історії залишаться таймстемпи. Щоб їх позбутися, нам і знадобиться sponge
- без нього складно писати в той самий файл, із якого ти читаєш.
cat ~/.bash_history | grep -v '#' | sort -u | sponge ~/.bash_history
Пропадуть також команди, в яких був символ #
, це я вже зрозумів після - але заглянув у забекаплену версію, такі команди в мене були, але небагато і не являють “історичної” цінності, так що і нехай, ліньки переробляти.
Перевіряємо #
$ history | awk '{$1="";print $0}' | wc -l # надрукуй все крім першого поля
4802
$ history | wc -l
4802
Вуаля.