Black Bytes
Share this post!

Building Your Own Linux Tools with Ruby: A Practical Guide

Tools like ps, top & netstat are great, they give you a lot of information about what’s going with your system.

But how do they work? Where do they get all their information from?

In this post we will recreate three popular Linux tools together. You are going to get a 2×1 meal, learn Ruby & Linux at the same time! πŸ™‚

Finding Status Information

So let’s try answering the question of where all these tools find their info. The answer is in the /proc filesystem.

If you look inside the /proc directory it will look like a bunch of directories & files, just like any other directory on your computer. But the thing is that these aren’t real files, it’s just a way for the Linux kernel to expose data to users.

It’s very convenient because they can be treated like normal files, which means that you can read them without any special tools. In the Linux world a lot of things work like this, if you want to see another example take a look at the /dev directory.

Now that we understand what we are dealing with, let’s take a look at the contents of the /proc directory…

This is just a small sample, but you can quickly notice a pattern. What are all those numbers? Well, it turns out these are PIDs (Process IDs). Every entry contains info about a specific process.

If you run ps you can see how every process has a PID associated with it:

From this we can deduce that what ps does is just iterate over the /proc directory & print the info it finds.

Let’s see what is inside one of those numbered directories:

That’s just a sample to save space, but I encourage you to take a look at the full list.

Here are some important / interesting entries:

Entry Description
comm Name of the program
cmdline Command used to launch this process
environ Environment variables that this process was started with
status Process status (running, sleeping…) & memory usage
fd Directory that contains file descriptors (open files, sockets…)

Now that we know this we should be able to start writing some tools!

Process Listing

Let’s start by just getting a list of all the directories under /proc. We can do this using the Dir class.

Example:

Notice how I used a number range, the reason is that there are other files under /proc that we don’t care about right now, we only want the numbered directories.

Now we can iterate over this list and print two columns, one with the PID & another with the program name.

Example:

And this is the output:

Hey, it looks like we just made ps! Yeah, it doesn’t support all the fancy options from the original, but we made something work.

Who Is Listening?

Let’s try to replicate netstat now, this is what the output looks like (with -ant as flags).

Where can we find this information? If you said “inside /proc” you’re right! To be more specific you can find it in /proc/net/tcp.

But there is a little problem, this doesn’t look anything like the netstat output!

What this means is that we need to do some parsing with regular expressions. For now let’s just worry about the local address & the status.

Here is the regex I came up with:

This will give us some hexadecimal values that we need to convert into decimal. Let’s create a class that will do this for us.

The only thing left is to print the results in a pretty table format.

Example output:

Yes, this gem is awesome!

I just found about it & looks like I won’t have to fumble around with ljust / rjust again πŸ™‚

Stop Using My Port!

Have you ever seen this message?

Umm… I wonder what is using that port…

Ah, so there is our culprit! Now we can stop this program if we don’t want it to be running & that will free our port. How did the fuser program find out who was using this port?

You guessed it! The /proc filesystem again.

In fact, it combines two things we have covered already: walking through the process list & reading active connections from /proc/net/tcp.

We just need one extra step:
Find a way to match the open port info with the PID.

If we look at the TCP data that we can get from /proc/net/tcp, the PID is not there. But we can use the inode number.

“An inode is a data structure used to represent a filesystem object.” – Wikipedia

How can we use the inode to find the matching process? If we look under the fd directory of a process that we know has an open port, we will find a line like this:

The number between brackets is the inode number. So now all we have to do is iterate over all the files & we will find the matching process.

Here is one way to do that:

Example output:

Please note that you will need to run this code as root or as the process owner. Otherwise you won’t be able to read the process details inside /proc.

Conclusion

In this post you learned that Linux exposes a lot of data via the virtual /proc filesystem. You also learned how to recreate popular Linux tools like ps, netstat & fuser by using the data under /proc.

Don’t forget to subscribe to the newsletter below so you don’t miss the next post (and get some free gifts I prepared for you) πŸ™‚

11 comments
jasonjoeldata says 7 months ago

Interesting post. I’ll see if I can apply it to Mac OS

    Jesus Castello says 7 months ago

    Thanks for reading πŸ™‚

june says 7 months ago

Very instructive!

    Jesus Castello says 7 months ago

    Thank you!

thisisole says 7 months ago

Very nice article. Thank you

    Jesus Castello says 7 months ago

    Thanks for reading! πŸ™‚

Kelvin says 7 months ago

added to my favortites πŸ˜‰

    Jesus Castello says 7 months ago

    I’m glad you liked it πŸ™‚

Andy says 7 months ago

WOW – how did I not know this?

Antony says 6 months ago

Hi! Good article! Can I translate this to russian and post in my blog – doam.ru, with link to original article of course?

    Jesus Castello says 6 months ago

    Yes, you can do that πŸ™‚

Comments are closed