As I’ve been building out my production mail server, I had the need to monitor some files. Sure, I could have multiple windows/tabs open and click back and forth, or go re-run a command. However, this is Linux, surely there’s a way that I can monitor files in real-time? I just want the screen to update when the file has changed – but how do you do that?
In my case, I had two different scenarios:
- Monitor a file, and update the screen when more content was added to that file (like a log file)
- Monitor a file, and update the screen when any of the content has changed.
Below are some of the things I’ve learned.
The obvious answer for some is to use use “tail”. Tail is a command that will normally just show you the last 10 lines of a file and return. For example:
$ tail /var/log/syslog
You can change how many lines it returns, by using “-n 20” for example, to show the last 20 lines of a file. This is useful, but I don’t want to have to keep re-running that command. Well, there is a “-f” option, for “follow”. Meaning, instead of showing the tail of the file and returning to the prompt, a -f will hold the console open and update immediately if/when more content is written. You use it like this:
$ tail /var/log/syslog -f
and then use CTRL+C to cancel and go back to the command line.
Another way to do this, but which gives you a little more functionality, is to use “less”. Less is typically use to let you scroll up and scroll down a text file in the console, but also lets you search it too. So, you could do this:
$ less /var/log/syslog
which let’s you page-up/page-down and search (at the : prompt, type “/” and then a search pattern). This is great, but the file might be getting bigger, and all I have is this snapshot of how it looked when I first loaded it. What you can do, is while in less, at the “:” prompt, type “F” (upper-case F), which will monitor the file for changes and show them as they are written to the file.
When you are in follow-mode (with “F”), you use CTRL+C to exit that mode, and you can type “q” to quit out of the less program.
What is good about this is that it does the same thing that “tail file -f” does, but also lets you page-up/page-down and search the contents too.
Now, the above are great for monitoring a log file like syslog. However, I had this other need where I wanted to monitor a small file and see the contents, as I changed them with a script I was testing. Although there might be a way to do that, I found this approach totally reasonable (and even ideal) – it’s called “watch”. Watch lets you run a command every n seconds, and shows the output on the screen. For example, if I wanted to see when files changed in a directory, I could run “ls -la” every few seconds. Here’s how you might use that:
$ watch -d -n 2 ls -la
the -d highlights things that are different on each refresh, and -n 2 says to refresh every 2 seconds. After that, is the command to run. That looks something like this:
It’s tough to capture in a screenshot, but when i added “test3.txt”, it highlighted the file name to show that it’d changed. In my case, wanted to monitor the contents of a small file (something that fit on one screen), so as you might imagine, I could now accomplish that with:
$ watch -d -n 2 cat ~/somefile.txt
That outputs the contents of the file every 2 seconds, highlighting the changes. By the way, just in case you are not familiar – how do you know what all the command-line arguments are? Use “man”. For any command you type at the command line there is a “man page” for it. So, to learn more about watch, run:
$ man watch
That goes for any command that you run across on Linux.
Putting it together with “tmux”:
You might recall that I was enamored with this “tmux” tool I ran across. This ended up being a pretty good tool for the job. I ideally wanted to monitor syslog (because I was putting some messages there), and monitor the contents of the file which I was programatically modifying, and then I needed a place to type my commands – so I did something like this:
after running “tmux”, I did a CTRL+B, ” (that’s a CTRL+B, then a double-quote) to split the window horizontally. Then, I do CTRL+B, : to bring up the tmux input line, and I type “resize-pane -D 10” to reduce the size of that lower pane by 10. To navigate between panes, it’s CTRL+B, and then an arrow-key. So, CTRL+B, Up to go the next pane above. From there, I split the pane again horizontally. See that other blog post for more on how to use tmux. Finally, I had the 3 panes I wanted:
- Top: where I could type in my commands
- Middle: where I could monitor the contents of the file using “watch”
- Bottom: where I could monitor syslog by using “tail -f”
In this particular case, I found it very frustrating to move between tabs and windows – particularly because I was working on another system via SSH. So, I would open a new window and start typing… “where did that file go!?” I would say, and then realize I was on the local system. When I’m SSH’ed into another system, I quickly forget – which frustrates me because I tend to open new tabs/windows all the time – never remembering that i need to re-SSH into that remote system in this window too.
Instead, in this particular scenario, just having everything in one screen which only took a few seconds to setup up, was ideal for me. This approach really took the frustration away (for me).