Today, when I logged into my console, I saw following error message
zsh: corrupt history file /home/rishi/.zsh_history
mv .zsh_history .zsh_history_bad strings .zsh_history_bad > .zsh_history fc -R .zsh_history
I ran them and everything was handy-dandy again. This did made me wonder what these commands do.
mv .zsh_history .zsh_history_bad
mv should be familiar to anyone who's toyed with linux. It moves files from one path to another. Also often used as a cheap was to rename files as we did here. More details on move in the man page.
strings .zsh_history_bad > .zsh_history
Strings is interesting. I had not come upon it before. Based on the man page:
... strings prints the printable character sequences that are at least 4 characters long (or the number given with the options below) and are followed by an unprintable character...
strings is a nice way to actually get the printable characters in a file. In our case, this means if the
.zsh_history was corrupted due to non-printable characters2, this will help parse them out. It also means if you ran any commands with non-printable characters, you've now lost them from your history as well. I'm very unlikely to run printable characters, so this wasn't as big of an issue but this may make past commands for QAs and pen-testers a tad-annoying.
fc -R .zsh_history
fc was interesting. It doesn't show up in the manpage. I ended up in a searching a fair amount to realize that this is a zsh-built in feature. There's some information about it within zsh documentation.
...'fc -R’ reads the history from the given file
fc will interact with your zsh_history. In this case, we are reading from the file and, since no second file was mentioned, putting it back into the same history file. i.e. re-writing history by parsing the same file.
This wasn't part of the original script but you should always clean-up after yourself. This command deletes the tmp "bad" file that you created in the first step.
If I power shutdown my VM / linux box while zsh is still writing content, I can still corrupt the zsh_history. As long as I don't care about any other non-printable characters in the past and open to keep using zsh, I can run the above commands to get back to a happier stage