Follow this blog

Software engineering, design, and psychology

Later Ctrl + ↑

How to View Past Terminal Commands — from Simple to Robust

Suppose you want to re-run some shell command you used ten days ago. It is a complex one; you do not remember exact flags and argument values, and it would take a long time to recall an exact text. What can you do?

1. The upwards arrow

Majority of devs working with command line knows it. Press “up” to see a previous command, press “down” for a next command, press “Ctrl+C” to drop whatever is in the prompt and start fresh.

This approach works, but gets very tedious when you need to find a command you used last week or last month. Once more than ten or twenty commands have passed, scrolling through them becomes tedious.

2. Terminal history file

All the commands you enter into a terminal get stored in .bash_history file (or .zsh_history if you are on Mac) up to a certain limit. Thus, you can run:

Shell
cat ~/.bash_history # output all into the terminal
less ~/.bash_history # or use any text viewer
tail -n 20 ~/.bash_history # or observe only the most recent n lines
cat ~/.bash_history | grep whatever # to search for specific patterns

This method gives you full access to your history file, and lets you search more flexibly.

3. history command

Almost the same as using the history file directly: you get a list commands, but now it is numbered.

Shell
history -20 # show the last 20 commands
history -500 | grep ssh # search for a specific patter in a command
!780 # execute command with order number 780

But there is one important difference from direct usage of .bash_history:

  • history command uses the last HISTSIZE history entries (default 1000)
  • .bash_history file uses the last HISTFILESIZE entries (default 2000)
    So, if your command was run a really long time ago, history may not find it, but direct inspection of .bash_history can do.

4. fc -l command

This command behaves very similar to history, with an additional ability to display ranges of command numbers::

Shell
fc -l -20 # show the last 20 commands
fc -l 100 150 # show commands 100 to 150

5. Reverse-i-search

This is the most powerful approach. Press “Ctrl+R” to enter reverse incremental search mode. Initially you get no output; start writing any part of a command you remember, e. g. ssh or input.json or -n 10 — and you will see the first full command entry with that match!

From there, you can:

  • Press “Enter” to execute the command immediately
  • Use left/right arrow keys to move within a command to edit it, then press “Enter” to execute
  • Press “Ctrl+R” again to go to the next, older match
  • Press “Ctrl+S” to go to the previous, newer match (see comment below)
  • Press up-down arrows to view to nearby entries in history around the match
  • Press “Ctrl+C” or “Ctrl+G” to exit the search

On many systems “Ctrl+S” shortcut will not work, as it is prioritized to pause terminal output (press “Ctrl+Q” to resume). To make it work for reverse-i-search, add stty -ixon to your shell config. It will disable “Ctrl+S” / “Ctrl+Q” shortcuts for terminal flow control:

Shell
echo "stty -ixon" >> ~/.bashrc
source ~/.bashrc

Happy command line manipulation!

💡 This post has a second part: Shell Configs for Better Command History Search

The Very Roots of Object-Oriented Programming

An image below is the first historical mention of something resembling objects we use today in OOP.

An ancestor of all modern objects — plex. Rectangles represent data in memory. Yellow ones are pointers to other objects, green rectangles hold actual values, red rectangles are pointers to functions, and blue rectangles are flags that control program execution flow.

The author is Douglas T. Ross from MIT, who published this concept in a paper A Generalized Technique for Symbol Manipulation and Numerical Calculation in 1960! He called it a plex, a shorter form of plexus, meaning “an interwoven combination of parts in a structure; a network”.

This solution was intended to solve problems for which commonly used linked list or tree structures were not sufficient enough. Each plex could hold both data and an arbitrary number of pointers, allowing it to represent complex object relationships — essentially, a network of interconnected elements. Pointers do not only point to other plexi, they could also point to functions. And, as these are not actual functions but pointers (which can potentially be changed during runtime), this means an invention of virtual functions as well. A truly fascinating stuff!

I’ve learned this bit from a great talk of Casey Muratori at the Better Software conference in which he digs into the history of OOP in C++. I highly recommend watching it in full.

Useful Commands to Debug DNS Issues and Redirection Loops (Ubuntu, Apache, Letsencrypt)

Recently I decided to add a blog to my personal website. Now I can regularly share thoughts with everyone! The blog resides at https://mishurovsky.com/blog/, while the main page remains at https://mishurovsky.com.

The path to a working solution, however, was not easy. My website is a Next.js application hosted on Vercel, while the blog engine I chose is a PHP application requiring a separate Linux server with Apache and MariaDB. My initial intent was to lead all traffic through a self-hosted reverse proxy, which would direct /blog requests to the blog engine, and all other requests to the Vercel page. I did not manage to make it work, so I ended up hosting both PHP and Next.js apps from my own server.

But that wasn’t the end of the story. After migration, HTTP connection was OK, but whenever I tried to switch to HTTPS, the response was still served by Vercel, even though I deleted both my domain and project from there! It was not just a failing request, but a redirection loop, 308 to mishurovsky.com again and again and again. I spent two days debugging configs and waiting for DNS caches to clear.

Long story short, the problem was in my use of Letsencrypt: I launched it as

Shell
certbot --apache ...# instead of certbot certonly --apache ...

, and Certbot created a separate HTTPS virtual host that reused an old configuration pointing to Vercel’s upstream. Apache prioritized this config over mine, causing a persistent redirect loop.

Helpful Commands to Debug DNS Problems and Redirection Loops

During this weekend journey, I discovered a lot of valuable commands to debug connectivity problems, which I want to share. Hopefully, these will help you, my reader, or me myself in some future.

1. Verbose cURL

Shell
curl -v https://example.com

Connect to a website and get a verbose response. Helps to see HTTP response codes and SSL connectivity status.

2. cURL with redirects

Shell
curl -I -L https://example.com

Connect to a website and get only headers in response + follow redirects. I used this countless times to examine if redirect loops persist.

3. Get site IP

Shell
dig +short example.com

Get an ip for a website. Useful when checking if a website is indeed hosted from a rented server.

4. Show all Letsencrypt certificates

Shell
certbot certificates

List all Letsencrypt certificates on a server with their domains, expiration dates, and paths to private and public keys.

5. Review Apache config

Shell
apache2ctl -S

All the main Apache config details: virtual hosts and structure. The most interesting part is error section in the beginning of the output — this is where I found a reference to an additional config from Letsencrypt.

6. Examine Port Usage

Shell
ss -tuln | grep ':443'
lsof -i :443

List all listening sockets (TCP/UDP), showing if port 443 is open. Then get a list of all process on port 443 (HTTPS).

7. Flush DNS Cache

Finally, Mac OS specific:

Shell
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

These two commands flush DNS cache on modern Macs, so DNS could be tested after updates. Requires to quit and re-start a browser after execution.