BASH history and GNU screen

Bildschirmfoto-2024-02-27-um-17.21.20

I can’t remember exactly when or where I learned this. I would guess sometime between 5 and 10 years ago, while I was working at Nuance Communications. I likely learned it from stackoverflow.com, though it is possible I learned it from a colleague. I have been using GNU screen on a nearly daily basis at work for nearly that long. It is very helpful when connecting to a remote server with a terminal. I remember trying screen once or twice and not really understanding it and giving up. I did the same thing the first time I tried vim. Months later, I decided to give it a try again, and finally started to understand the beauty of it. For screen, I think that I fully realized how useful it was when I learned more how to customize it. I spent some hours reading about how to configure it using .screenrc, and I have been using the same .screenrc configuration file for about 10 years now. I have it set so that the bottom line lists my various screen “windows”, (which are more like browser tabs nowadays). By default, screen will just number these, but you can also use Ctrl-a Shift-A to set a custom title for the window. This is very handy. Frequently I have one tab open where I am editing some code, and another tab open where I am testing out running the code. I can simply switch back and forth between the tabs using Ctrl-A <number>, where the number is the number of the tab. I find this very helpful. Another great feature of GNU screen is that when you disconnect from the server, your screen session stays open. This means when you reconnect to the server, you are instantly back just where you left off. I do that with the following command (from my laptop)

robfelty$ ssh -t sandbox screen -Udr rob
  • The -it option makes ssh behave like a terminal, which is necessary for screen.
  • sandbox is the alias I have for my WordPress.com sandbox server that I use at work.
  • screen is the name of the command I want to run on the remote server.
  • -U means use utf-8 encoding (otherwise non-ASCII characters can get messed up).
  • -d means detach the screen session (if it is attached)
  • -r means to reattach to the screen session
  • rob is the creative name of the screen session. When I started the screen session I gave it a name using the -S option.

Okay, so that is a little bit of info about how I use GNU screen. For reference, here is my .screenrc file (which lives on the remote server)

# set a big scrolling buffer
defscrollback 50000
termcapinfo xterm* ti@:te@
caption always # activates window caption
caption string '%{= wk}[ %{k}%H %{k} %h%=][%= %{= wk}%?%-Lw%?%{r}(%{r}%n*%f%t%?(%u)%?%{r})%{k}%?%+Lw%?%?%= %{k}][%{b} %d/%m %{k}%c %{k}]' # good looking window bar
#
vbell_msg "beep"
altscreen on
#
encoding utf8 utf8
defencoding utf8
#
deflogin on
defshell -$SHELL

# needed for agent forwarding (for git keys)
setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

So, what does BASH history have to do with GNU screen? Well, at some point I noticed that if I had four screen “windows” open, that while I was working with one window, and trying to search through my history to find that really long command that I ran a couple minutes ago, I couldn’t find it. Where did it go? I looked in my .bash_history file and it simply wasn’t there. I then learned that by default, BASH history is stored in memory as part of the terminal session, and only written to the .bash_history file when you close the terminal. I don’t remember the details now, but I also seem to recall that I had issues where the history from one screen window would end up getting written but not the others. Some people might see the per-window history as a feature, but I saw it as a bug. However, after some interweb sleuthing I found a solution which allows me to share the same history across all my screen windows. I now have the following options in my ~/.bashrc file.

export HISTCONTROL=ignoredups:erasedups
export HISTIGNORE="&:ls:exit:cd:clear: *"
export HISTSIZE=100000
export HISTFILESIZE=100000
export HISTTIMEFORMAT="%h %d %H:%M:%S "
PROMPT_COMMAND='history -a; history -c; history -r'

The first option simply says to not store duplicates. The second option list a few commonly used commands which are not saved into history, like ls and cd. The third and fourth options specify how many commands to keep in memory and save to the history file – I have 100,000, which currently goes back over 2 years on the WordPress.com sandbox I use daily at work. The time format is handy when using the actual history command to tell you when you issued a specific command. And the last line is the magic for screen – in order to get each screen window to share the same history, I modify the prompt command. That is, every time I press Enter to execute a command, I get a prompt back. As this prompt is being created, it appends to the history file (-a), then it clears the current in-memory history (-c), and then it re-reads the history into memory from the .bash_history file (-r). It might sound like this would be slow, and maybe it would have been 30 years ago, but I have been using it for over 10 years, and I never noticed any lag when getting a prompt.

I was prompted to write this post when I heard about an improved shell history tool called https://atuin.sh/ – for me personally, my .bash_history solution is good enough for now. I don’t think I would be likely to remember part of a command from more than two years ago that I would search for. (Oh, speaking of search, I use vi key bindings on the command line, which also allows me to search my history very easily by simply typing Esc + /, and then searching for whatever I want. Searching with vim key bindings allows me to also specify that I want to search for things anchored to the beginning of the line by using ^

Join 165 other subscribers

archives

  • 2024 (10)
  • 2023 (8)
  • 2022 (15)
  • 2021 (19)
  • 2020 (1)
  • 2019 (1)
  • 2018 (2)
  • 2017 (1)
  • 2016 (2)
  • 2015 (5)
  • 2014 (5)
  • 2013 (2)
  • 2011 (7)
  • 2010 (10)
  • 2009 (50)
  • 2008 (28)
  • 2007 (31)
  • 2006 (8)

Category