bash history: переписуємо історію

bash history: переписуємо історію

January 6, 2024
technical
bash, shell, history, awk, sponge

Проблема із баш історією #

Колись давно я вважав, що мати таймстемп для кожної виконаної команди у консолі то гарна ідея.

Розробники башу вважали так само, тому за бажання це можна легко налаштувати:

Ось оця команда у профілі

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

Вуаля.

comments powered by Disqus