Sunday, May 7, 2023

Never Lose a Command Again: How to Centralize Your Bash Command History


Have you ever found yourself in a situation where you needed to recall a command that you had used in the past, only to find out that it was no longer available in your command history?

If so, you're not alone. It's a common problem for anyone who uses a command line interface on a regular basis.
To address this issue, one solution is to log all of your commands in a central server. This allows you to access your command history from any machine that you may have used. In this post, we'll explore a simple way to achieve this using bash and netcat.
First, let's start with the client-side implementation. Bash provides an environment variable called PROMPT_COMMAND, which is a command that is run every time the prompt is printed on the screen.
By setting PROMPT_COMMAND to a command that sends the current command to a server using netcat, we can easily log all of our commands. Netcat, also known as "nc", is a versatile networking utility that can be used for a wide range of purposes, including sending and receiving data over TCP or UDP connections.
There are several different implementations of netcat available, each with its own set of features and options. Some of the most popular netcat implementations include:
  • GNU Netcat - The GNU implementation of netcat, also known as "nc", is the most widely used version of netcat. It includes a wide range of features and options, including support for TCP and UDP, port scanning, and remote shell access.
  • OpenBSD Netcat - OpenBSD's version of netcat, also known as "nc", is designed to be secure and portable. It includes support for IPv6 and encryption using SSL/TLS.
  • BusyBox Netcat - BusyBox is a lightweight Linux distribution that includes a variety of common Unix utilities, including a minimalist version of netcat. BusyBox netcat is designed to be small and fast, and includes support for basic TCP and UDP connections.
It's worth noting that different versions of netcat may have different options and behavior, so it's important to check the documentation for your specific implementation to ensure that you're using it correctly. In the context of logging command history, we've used the most basic version of netcat without any options, as it provides the core functionality we need without adding unnecessary complexity.
Here's an example of how to set up PROMPT_COMMAND:

export PROMPT_COMMAND='echo "$(date +%Y%m%d.%H%M%S) - $(hostname -A) > $(history -w /dev/stdout | tail -n1)"|nc server.example.com 12345'

This command sends the most recent command from the command history to the server server.example.com on port 12345 using netcat. Note that we're using the history command to retrieve the most recent command.
Now let's move on to the server-side implementation. Initially, we had planned to use netcat to receive the data from the client, but we found that we needed some uncommon features that netcat does not provide. As a result, we decided to implement the server in a single Golang application.

In conclusion, logging your command history to a central server can be a great way to keep track of your commands and make them easily accessible from any machine. By using bash and netcat, we've provided a simple and efficient way to implement this solution. However, depending on your requirements, you may need to use a more complex solution like the Golang application that we ended up implementing.