[MUSIC] Hello again everyone and welcome back to the Linux Crash Queer series here on Learn Linux TV. In this series, I'll teach you a very important topic around Linux one video at a time. In today's episode, we're going to talk about open files, or specifically how to find out which files are open on your system and open by whom or what in particular. To help us achieve this goal, we're going to introduce the LSOF, or List Open File command, which is going to be the subject of today's episode. But why would you want to know which files are open? Well, when it comes to the LSOF command and when you would use it, it's entirely dependent on your situation. There's a number of different situations that might come up where understanding which files are open is going to be useful to you, but a very common example is going to be error messages that let you know that you can't, for example, delete a file because it's in use. If you can't delete a file because it's in use, then what do you do? I mean, do you go around asking everybody at your company if they have the file open? I mean, you could do that, but I wouldn't recommend it. I don't think that's very efficient. The LSOF command comes to the rescue in that case because it does exactly that. It lets you know which files are open and by whom or what. Now, another example where a command like this might be helpful is when you have a security issue. If you have a process, for example, running on your server and you're not really sure what that process is or you want to understand more about it to find out if that process is genuine or something more suspicious, you could also investigate the open files for that process to understand what files it's working with, which might give you a greater understanding of what that pertains to or if it's something that absolutely should not be in your system because it's opening files that should not be open. Well, you probably have a clue that something malicious is going on. Now, regardless of your situation, it's a good idea to have some notes around the LSOF command handy in case you need to understand what files are open and I'll show you some examples in today's video. But before we get into that, I need to mention the sponsor for today's video, Akamai Connected Cloud. If you're looking for a cloud provider that's affordable, flexible and reliable, then look no further than Akamai Connected Cloud. With Akamai's Cloud Platform, you can split up Linux servers quickly and the platform contains all the features you'll need to deploy full featured solutions. And using the marketplace, you could easily deploy applications such as Next Cloud, Rocket Chat, Mastodon, WordPress, Pihole, Plex, Jenkins and many more. In fact, there's over 100 applications available in the marketplace. If you want to set up a custom Linux instance, you could do that too. All the popular Linux distributions are available on the platform, including but not limited to Debian, CentOS, Fedora, Ubuntu and many others. In fact, even Arch Linux is available. So check out Akamai Connected Cloud with the URL that you see on the screen right now, which will do two things. First, it'll help support this channel, which I'll really appreciate. And it'll also get you $100 in starter credit to check out the platform. And thank you yet again to Akamai for sponsoring today's episode. I really appreciate it. So with all of that out of the way, let's dive into the LSOF command. I have some examples to give you that'll help you learn the command. And by the end of the episode, you'll know how to use the LSOF command. So let's dive in. And the first thing that I'll go over is the basic usage of this command. And well, all we have to do is type LSOF just like that. That's the first example that I'll give you is the command itself. And it prints quite a bit of information here, doesn't it? Well, actually, what I'm going to do is pipe the command into head to, you know, have fewer lines of output. As you probably already understand if you've seen my video about the head and tail commands, the head and tail commands allow you to view the first 10 or the last 10 lines of a file respectively. And just like with other Linux commands, we could pipe something into that command. So let's take a look at the first 10 lines of the file that'll help minimize the output here. And what I have is a bunch of permission denied errors. So no matter what I do, I'm facing this issue right here where I just don't have the permission that I need to view everything. Now, I will cover this part later in the video, but what I want to do first is go over the top part. And it looks like the lines have wrapped so much, I'm going to have to make the font size a bit smaller here. I apologize for the smaller text, but I will zoom in as necessary, so that way you guys are able to see everything. But what I want to call your attention to is the very first line after I entered the command. We have a series of headers here, for example, Command, PID, User, and so on. So what I'll do first is go over that line and that'll help you understand what each of these columns refer to. And then after I do that, I'll show you some additional examples of the LSOF command that'll help you understand how to use it. Anyway, the first column that we have here is the Command column. That gives us the command associated with the open file. And every line of the output is going to pertain to an open file. Keep in mind that in Linux, everything is a file. And that's especially important when you are trying to understand the LSOF command. Every line, again, pertains to an open file. And like I mentioned, the first column is the Command column, so that's the command that's associated with that open file. Continuing, right after that, we have the process ID or the PID field. And that ID number pertains to the process that has the file open. Now, if you're not familiar already with what a process ID is, a PID or process ID is a unique number given to each and every process running on your system. When a process starts on a Linux system, it asks the init system for a process ID. Nowadays, the init system is most likely going to be system D. That's the most common one nowadays. And regardless of which init system you're using, the job of the init system is to schedule commands. And that's exactly what happens here. A command is requested by the system or by the user. It's given a process ID. And then that process is scheduled on the CPU. But this video isn't about init systems. So to keep it simple for now, you could think of the PID as the process ID number that the underlying distribution provides a running process to distinguish it from others. I'll probably create a video that's dedicated to init systems in particular. So I'll stop the explanation on PID right here. Next we have the TID field, which stands for thread identifier. A full explanation of this is beyond the scope of our video today. And it doesn't really factor in as much as the other fields do when it comes to our examples. And it's not likely that you'll pay attention to the TID field until you get even deeper into Linux, deeper than we go in this series anyway. So for now, you could write down that the TID stands for the thread identifier, and we'll just leave it at that. Anyway, the next column we're going to go over is the task CMD column, which stands for task command. And often the task command is going to be the same as the command itself. In my case, the lines that were shown after I piped the command into the head command aren't actually showing a task command. There's not always going to be one. But when there is one, it's often going to be the same name as the command. It can vary, but it often doesn't. Now this is another category that doesn't really factor in all that much with what we're doing today. So I'll leave it as simple as that until I come back to it in a future video, which I probably will do at some point in the future. Anyway, moving on, the next column, user, is one of the more important ones. And it's also a field that you'll probably look at fairly often when you run the LSOF command. And what this column is for is to let you know which user created the process that has the file open. For example, I could type LSOF and then pipe it into grep. And then what I'll do is grep for my username. And since I'm currently logged into this workstation, I definitely have a ton of files open, as you can see here. But if you wanted to narrow down by user, you could use grep to do that, as I've done right here. Now, moving on from there, we'll look at the type column. This may be blank or even unknown, but if this field is used, then it will contain what kind of object the item happens to be. For example, a directory, a file, or so on. And we're skipping several columns here because there's additional columns that are beyond our scope and even our use case for the examples that I'll be showing you today. But keep in mind, the basic usage that I will be demonstrating is all you should really need when it comes to using this command on a daily basis. Anyway, node refers to the iNode number of the file. But what exactly is an iNode? Well, every file on a Linux system has an iNode number. And this number differentiates one file from another. Now, these iNodes don't store any actual data, but instead they store information ABOUT the file, you know, metadata, such as permissions, file size, and so on. And this is something that I've covered in other videos, so I've overly simplified the description here. iNodes are something that you'll pay attention to eventually if you haven't done so yet. It's just one of those things you will run into. And if you do, then you can get the iNode number right here from the output of this command. Anyway, at the very end of the file, we have the name, which refers to the name of the object. So what I'll do right now is type lsof without redirecting it into anything at all. And the reason why I'm doing this is because, well, if we look at all of the output of the lsof command right here, we can get even more examples of some of the information that might be in any one of those columns. So based on my description of each column, I recommend you run the lsof command on your system and just make sure that you can understand what each of these columns pertains to. But we're not seeing everything, and the reason why is because the lsof command is only going to display information that the user that executed that command themselves has access to. And to illustrate that, I'll just enlarge the font size right here. I think I could probably keep it fairly large considering that I've gone over the heading so far. And what I'll do is execute lsof again. At this time, I am going to redirect the output of this command. And what I'll do in particular is redirect it into the word count or wc command, and I'll give it the -l option. And what this command will do is give us a line count. Normally, you would use the word count to count the number of words, but with the -l option, we get a count of lines instead. In my case, it's claiming that I have over 45,000 open files. So if I was to scan through all of that output, it would take a very, very long time for me to find exactly what I'm looking for. And that's considering that I just told you we're not seeing everything. So if I was to run sudo lsof and then pipe that into the word count command, the same as we've done before, I have even more lines of output. And here it's showing 50,097 open files. Now to be fair, the line count is not accurate. The word count command with the -l option is going to take into account lines that we may not care about. For example, we have a heading line, the line that shows the names of all the columns. So we know at least one of these is invalid. But the whole point is not to get an exact count of how many lines there are, but instead to show you that the output is different when I use sudo versus when I don't. And again, the user that executes the lsof command will only have access to view the open file listings for the files that the user has access to view. But earlier, I told you that you could use the user column to narrow down the output. And what I showed you as part of that example was running lsof and then using grep to grep for your username. And that is a valid way of limiting the output for a specific user. But there's a built in option that'll help you do this even easier. So what you could do is type lsof -u for user, and then the username, you don't even have to pipe it into another command at all. You could just enter this command right here, and you should get, well, the same output. And of course, it's going to be missing some information because I didn't use sudo, but you get the point. From this point forward, I will be using sudo with the remaining examples, assuming I don't forget. And I'm doing that to make sure that I see everything when it comes to the output. Sorry to interrupt myself, but I just wanted to let you know that I really enjoy making this content for you guys. I have a ton of fun. If you enjoy the content that I produce, then please consider supporting Learn Linux TV. The thing is, producing content like this isn't cheap. So by giving back to the channel, you can help me make even more content for you guys. And to find out more about how you can support Learn Linux TV, what you could do is go to support.learnlinux.tv, and there you'll find some of the ways that you can help support the channel. Anyway, let's get back to the video. Now it's definitely useful to be able to narrow down the output by user, but we can also narrow it down by process as well. Maybe we aren't really concerned about a particular user, and we need to know, well, what a process has open in terms of files. Now I'll give you an example of a web server, but this is a workstation. It's not really a web server, but I'll just install Apache anyway because it's easy to install. So I'll just run sudo apt install, at least in the case of Debian and Ubuntu. And then the package name here on this distro is Apache2. So I'll just press enter on that. And of course I could type systemctl and then status Apache2 to make sure that it's running. And it is. And to be double sure, I'll open a web browser. And since I've installed Apache on this workstation, I could simply type localhost right here to go to the website that's being hosted from this computer. And here we see the default Apache2 start page. So we know that Apache is working. But this isn't an Apache tutorial. We're here to learn about LSOF. So what does this have to do with that? Well, back here in the terminal, what I'll do is show you how to isolate the output based on a process, a particular process. And Apache2 is the example that I'll use. So what I could do is type LSOF and then dash C. That'll help us narrow it down by process. And I want to narrow it down by Apache2. Now when I pipe this into the word count command, I only have 134 lines. And just to show you the comparison one more time, I'd say that's going to be a lot easier to go through than the number of lines that are showing right here. 134 is definitely approachable. Anyway, let's bring up the output one more time. And right here we see a list of open files that's being used by the Apache process. And it's going to be quite a few here. So even though I only have the default web page, I haven't even installed any web apps or anything like that, we have a bunch of open files. And that's not uncommon. With this command, we're seeing every file that's open right here. So if there's something malicious, we would actually see it within the output as being open by this process, assuming this process had anything like that in the first place. Anyway, we see a lot of output here. And each of these open files are going to specifically pertain to the Apache2 process, since that's a process that we called out with a -c option. Now, another thing we can do is narrow down the output by process ID. And if you recall from my earlier explanation, the process ID is this right here. In my case, the process ID for Apache2 is 12274. So to narrow down the output by process ID, I could use option -p and then type the process ID. And that was 12278. So let's see what happens. Well, basically the same thing. And we're going to get the same output here because in either case, we are investigating the Apache2 process, regardless of how we narrow the information down. If we're narrowing down to Apache by the name or the process ID, it's still the same process, same open files. Well, you get the idea. Now what I'll do is show you a fun example. And what you're going to see is a real production system. What you've seen so far is just my local workstation, my footage PC, as I call it, the PC that I use for capturing footage for the videos that I produce on this channel. But considering this is just a demo machine, there's not going to be all that much interesting here. So let's switch over to a production machine and have a little fun with a real Linux server that's actually being used for something important. So what I'll do is type SSH. I want to use SSH to connect to that server. I have several videos in SSH if you want to learn that. But what I'm going to do is connect to the server that serves the Homelab show, which is a podcast that I'm a part of. And that's the URL of the website right there. So I'm going to SSH into that. And this is the actual production site. So I guess you're getting a rare behind the scenes look, aren't you? Okay, I'll just SSH into that server right there. And now I'm logged in. Now what I'm going to do is list open files on this server right here. So again, LSOF, that's our topic for today. And more particularly, what I want to do is view open files in a specific directory, which is yet another thing you could do with the LSOF command. And the directory that I want to investigate the open files for is going to be the WP content directory. And I'll press enter. Let's see what happens. And this is interesting. It looks like somebody right now is actually listening to the latest episode of this podcast. Well, latest as of the time I'm recording this video anyway. And what's interesting about this is that you're seeing a real world example of a situation where the LSOF command can actually help you out. If I wanted to reboot this server, for example, I didn't want to do so if somebody was listening to one of the podcasts, then I could wait until they're done with this episode before rebooting the server. Now in this case, it's not quite the end of the day yet. A lot of people listen to podcasts on their way home from work, for example. And it's going to be rush hour here very soon. And when that happens, the server will be a lot busier. But right now, somebody is enjoying episode 90 of this podcast. And I know that because I could see the output right here that tells me that someone is listening to that episode. Now thankfully, I don't see any personally identifiable information about who in particular is listening to this episode right now. And I don't really want their information anyway. But if you're curious what I see on the server when someone's listening to a podcast, well, using the LSOF command, I could see which episode is being listened to. And you just saw an example of that. Anyway, let's move on to another example. And for this one, what we're going to do is revisit the -u option. That's the option we used previously to narrow the output down by user. Another trick with the -u option is that we can use it as an exception by typing a caret symbol in front of the username. So for example, if I wanted to view the output of open files that are not owned by root, here's what I do. I'll type sudo, and then LSOF -u, and then the user, which is going to be root. But unlike the last time, what I'm going to do this time is type a caret symbol right in front of the username just like that. And that's going to create an exception. With this variation of the LSOF command, we're looking for users that are not root. And we're definitely going to get a lot of information here, probably more than we even needed. But the whole point was to show you that if you wanted to exclude a user from the output, you can do so by typing a caret symbol in front of their name. Now, another thing you can do is view open files pertaining to IPv4 or IPv6 IP addresses. So if I wanted to find out the IP address of the person that's listening to the episode right now, then I could use the LSOF command to find out who that actually is. And you know what? I'm just going to do it right here in the video right now. So I'll type sudo LSOF, and then -i, and then after that I'll type 4, that's short for IPv4. And what I want to do is again use that same directory as an example. And what you're going to see is that individual's actual IP address that's listening to that episode right now. Now, of course, I had to censor the information. I mean, you didn't think I was going to show someone's IP address in clear text on a YouTube video, did you? But if there was a malicious file on the server, I could find out what IP address that connection actually came from if that's something that I wanted to block in the firewall. So that's the actual reason why I might look at something like this if I intended to block somebody. Anyway, that's the command right there that I used to find that information. LSOF -i, and then 4. You could also replace 4 with 6 if you wanted to view IPv6 information. And then in my case, I typed the directory that I wanted to investigate. That directory right there, slash mount slash WP content, that's where all the MP3s are for the podcast. So that's what's going to be, well, used anytime someone listens to an episode. I've given you some examples of the LSOF command in action, even showing you a real production server. I bet that was very interesting to a lot of you because normally I only show you my footage PC, but anytime I can show you a production system going forward, I'll definitely try and do that. Either way, though, I have taught you basic usage of the LSOF command. So that's yet another command to add to your toolset. And if you enjoyed this video, please click that like button, subscribe to the channel, and all of that because some good content is coming that I can't wait for you guys to see. Anyway, thanks for checking out the video. I really appreciate it, and I'll see you in the next video.