3

I just realised that a workflow I've been using for years, doesn't do what it is supposed to do. Since I haven't realised that for such a long time, you might think it's not worth putting much effort into it, but it turns out that right now, it has become somewhat important.

What am I talking about? Okay, I have tmux running with several sessions and each session has different windows and so on. Working like that is wonderful. There's one downside to it, though. When the server gets restarted, for whatever resason, it closes all my sessions. Fair enough, cannot be avoided and doesn't happen often. However, the annoying part is, that all my zsh or bash history is gone as well. This is a problem. I rely on my history, maybe far too much.

I was circumventing this problem by hitting fc -W (in zsh) every now and then. I thought this would append history that is in the memory and I would then only lose the part between my last invocation of fc -W and the restart of the server. But that's not what it does. If I use fc -W in one window, then fc -W in another one, the history from the first window would be overwritten by the history from the second window. I would need to use fc -R first, but this would duplicate the whole history... basically I was misusing the fc command the whole time.

Here's the question: How can I make sure to not lose any of my history when I'm in tmux and there is a sudden power cut? Note:

  • I use infinite history, in case that matters.
  • Losing some of the history is ok, i.e. if I have to invoke a command by hand (or in a cronjob) and I lose the part of the history since the command has last been run, that's fine.
  • Exiting the terminal and open up new one is not the solution.
  • I don't want to store my commands directly to the history, since this mixes up different histories.
  • Solutions for both bash and zsh are welcome. zsh is preferred.

Edit: Highlight the part that everyone seems to misunderstand.

7
  • 1
    You need to set HISTFILE independently for each shell process, but using an algorithm that means you get the same filename when you restart a session, or a window. See what values are in the env that might work for you, eg name your sessions. A simpler solution, depending on your workflow, might be this history per directory plugin.
    – meuh
    Commented Jan 7, 2018 at 18:02
  • Why the downvote?
    – pfnuesel
    Commented Jan 7, 2018 at 19:23
  • @meuh Why do I need to set HISTFILE separately for each process? That seems to complicate things only, but I'm missing what the benefit might be.
    – pfnuesel
    Commented Jan 7, 2018 at 19:25
  • @meuh I think you misunderstood my question.
    – pfnuesel
    Commented Jan 7, 2018 at 19:27
  • The key trick is to use PROMPT_COMMAND to store values. This is a possible duplicate and a nice link to a solution
    – user232326
    Commented Jan 7, 2018 at 21:11

2 Answers 2

2

In zsh, use fc -AI to save your history, not fc -W. Use -A, not -W, otherwise the history from other shell instances is overwritten. And -I saves only the new history entries since the last save.

Given your workflow, rather than saving manually, you should probably save the history automatically. Turn on the inc_append_history option to save each command to the history file immediately before it gets executed.

While it's possible to achieve the same effect in bash, properly sharing history between bash instances is harder. See Preserve bash history in multiple terminal windows

2
  • Thank you! I haven't tested yet, but this looks like a lifesaver! I don't want to use inc_append_history, since it mixes different histories together.
    – pfnuesel
    Commented Jan 7, 2018 at 20:29
  • Sorry, but who is downvoting this answer? It is the perfect answer, the only one actually answering my question...
    – pfnuesel
    Commented Jan 7, 2018 at 21:41
2

You can save your bash history with this command (I am not familiar with zsh):

history -a

This seems to work with zsh:

fc -ln 1 -1 > ~/.zsh_history
8
  • That seems to do the trick. Probably I will just call bash within zsh and then invoke history -a.
    – pfnuesel
    Commented Jan 7, 2018 at 19:24
  • @pfnuesel I don't think that will work but maybe I misunderstand what you have in mind. Why call bash from zsh? Would you execute the command manually or do you want it automated? Commented Jan 7, 2018 at 19:27
  • You are right, that won't work, obviously bash and zsh have different histories. Automatising the process would be nice to have, but is not absolutely necessary.
    – pfnuesel
    Commented Jan 7, 2018 at 19:30
  • @pfnuesel Maybe it helps to set an EXIT trap with this command. In addition you could set a trap for SIGUSR1 and create a cron job which sends this signal to the shell. Commented Jan 7, 2018 at 19:37
  • 1
    The zsh command you propose doesn't do what it should do: it replaces the history file with the history from that shell instance, which wipes out what other instances have written. The bash command kind of works, but it's substandard because it appends the complete history from that shell instance, which duplicates lines that were already present the last time you ran it. Commented Jan 7, 2018 at 20:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .