Sunday, October 11, 2009

Linux find command

sometimes finding out the way a Linux or UNIX command is working can be fun. For example I have been looking into the way how the find command is working and I have had a lot of fun with it. find can give you a great option to locate exactly the files you want and with the pipe options in Linux you can get exact that output you want and need.

The reason for me to look into the find command was a interface at a server at a customer. The interface consist basically out of remote servers who place files with FTP in certain locations. On the server side we have a couple of processes scheduled looking for files in certain directories who will process and delete the files. The processes run every 10 minutes, as we have some files that can be large the processing can take some time so files can be at the location for some time. However, never longer than 1 hour. So what we want the administrators would like to have is a system that looks for files older than 1 hour because this can indicate a interface that is stuck for some reason.

As we maintain a large number of servers and interfaces this can not be done by hand and has to be automated. The solution is to schedule a scrip that will look for the files and send the output every hour via mail. Even in the cases no files older than 1 hour are find a mail should be send because this is a trigger to see if the check has run.

First is to find out how you can locate files older than 1 hour. We will be using the find command for this. We will use the following command:

find . -type f -mmin +60

find is the command to find files. the “.” indicates that you want to look in the current directory. than we have the “-type f” option. “-type” allows you to set what kind of files you are looking for. f states that you are looking for regular files. If you for example are looking for directories you can state d and if you are looking for a link you can state l. for the complete list you can refer to the man page of find.

We also states -mmin +60. This indicates that you are looking for files older than 60 minutes. You can play with +60, if you are looking for files for example that are NOT older than 60 minutes you can state -60 instead.

Now we do not want the standard output because we do want to have more information, somewhat like the output we get from the ls command. For this we can do a “internal” pipe to the ls command with the -exec option. for the -exec we set ls -la so we get all the ls output. The command will look like this:

find . -type f -mmin +60 -exec ls -la {} \;

However this is still not what we want because we only want the filename and the time it is created. currently we get something like:

-rw-r–r– 1 jlouwers staff 0 Oct 11 11:14 ./x
-rw-r–r– 1 jlouwers staff 0 Oct 11 11:23 ./z/x

So we have to change the output and we can do this by using awk. We have to pipe the output from the above command to awk and than make sure we only get what we want. And what we want is filename and time. nothing more. So we can do this by using awk. According to the UNIX manual pages AWK is a pattern scanning and processing language… simple told.. it is a damn handy tool to make stuff look like the way you want it.

We pipe the data into the following command:
awk ‘{print $8,$9,$10}’

which makes the complete command look like:
find . -type f -mmin +60 -exec ls -la {} \; | awk ‘{print $9,$10}’

and the output will look like:
11:14 ./inbound_225/225int_inb.txt_65466
11:15 ./inbound_225/225int_inb.txt_65467
11:25 ./inbound_225/225int_inb.txt_65468
11:23 ./inbound_256/256int_inb.txt_43221
11:24 ./inbound_256/256int_inb.txt_43222

One last thing you might want to add, if you are running the command on a directory and you do not have access to all sub-directories you might end up in a situation where you get access denied errors in your output which can disturb your checks so you can pipe all the error messages to /dev/null . You can do this by editing the command that it will look like the command below:

find . -type f -mmin +60 -exec ls -la 2>>/dev/null {} \; | awk ‘{print $8,$9,$10}’

A lot more options are in the find command, you have however to check out the manual and have some fun with it while trying.



Post a Comment