Check if file is locked otherwise gzip it

Dear community,
I've a continuos tcpdump on redhat that close the dumped file every 100000 captured packets.

To avoid disk full I would like to gzip the closed *.cap file. But how can I check if the file is currently opened by tcpdump and skip it from gzip?

Thanks!

EDIT: Just to post an example:
I have currently the following file on the trace directory:

-rwxr-xr-x 1 root root      249 Aug  9  2011 cont_tcpdump.sh
drwx------ 2 root root     4096 Dec 13  2011 lost+found
-rw-r--r-- 1 root root 16558574 Mar 16 18:37 tcpdump_continuous_20130316_183340.cap
-rw-r--r-- 1 root root 17322400 Mar 16 18:40 tcpdump_continuous_20130316_183708.cap
-rw-r--r-- 1 root root 15552512 Mar 16 18:44 tcpdump_continuous_20130316_184049.cap
-rw-r--r-- 1 root root  6029312 Mar 16 18:45 tcpdump_continuous_20130316_184437.cap

The last file (tcpdump_continuous_20130316_184437.cap) is currently opened by tcpdunp, so my other script should run every 5 minutes and gzip only the closed *.cap files!

Try:

fuser -- file
1 Like

If you don't have fuser then lsof is another option:

for cap_file in tcpdump*.cap
do
        if lsof -f -- "$cap_file" > /dev/null
        then
                printf "File: $cap_file currently in use\n"
        else
                printf "File: $cap_file currently not in use\n"
                gzip "$cap_file"
        fi
done
1 Like

Thanks Scrutinizer,
fuser works perfect!
Btw, I realized that it output the file in use, now I've to exclude it from gzip!
Unfortunately gzip cannot exclude file.... Maybe fuser can show the file NOT in use?

---------- Post updated at 01:01 PM ---------- Previous update was at 12:56 PM ----------

OPS! Yoda, your solution works perfect thanks! :wink:

---------- Post updated at 01:37 PM ---------- Previous update was at 01:01 PM ----------

WOPS! Unfortunately lsof seems doesn't work from crontab... :frowning:

If I execute the Yoda's script from shell it works, but at crontab level it just gzip all the *.cap files!!!

But why ?!?!? :confused:

Are you sure that you are using absolute path of capture files in your script?

You can also set DEBUGs and redirect the script output to another file in crontab to check what exactly is going on...

I think so, because the gzip works perfect except for the fact that gzip all the *.cap files even those that are in use.
This is my very simple script:

# pwd
/home/user/trace

# cat gzippa.sh 
#!/bin/bash
find /home/user/trace/*.cap.gz -type f -mmin +600 -exec rm -f {} \;
for cap_file in /home/user/trace/tcpdump*.cap
do
        if lsof -f -- "$cap_file" > /dev/null
        then
                printf "File: $cap_file currently in use"  > /dev/null
        else
                gzip -9 "$cap_file"
        fi
done

Your script looks good & works for me!

I tested it from crontab on few files out of them I kept one file open and it skipped that one from gzipping!

Like I mentioned before, put some print debugs on your script and redirect o/p to another to understand what is going on:

* * * * * /home/user/trace/gzippa.sh > /home/user/trace/debug.out

Ok, this is the situation before the script starts from crontab:

-rw-r--r-- 1 root root  3128771 Mar 16 20:00 tcpdump_continuous_20130316_195558.cap.gz
-rw-r--r-- 1 root root  2802194 Mar 16 20:03 tcpdump_continuous_20130316_200012.cap.gz
-rw-r--r-- 1 root root  3018276 Mar 16 20:06 tcpdump_continuous_20130316_200335.cap.gz
-rw-r--r-- 1 root root 18641426 Mar 16 20:08 tcpdump_continuous_20130316_200606.cap
-rw-r--r-- 1 root root 18049102 Mar 16 20:11 tcpdump_continuous_20130316_200824.cap
-rw-r--r-- 1 root root 13959168 Mar 16 20:14 tcpdump_continuous_20130316_201132.cap

The last bold/red file is in use by tcpdump, but the script just gzip all the file even the one in use:

-rw-r--r-- 1 root root 3018276 Mar 16 20:06 tcpdump_continuous_20130316_200335.cap.gz
-rw-r--r-- 1 root root 3015096 Mar 16 20:08 tcpdump_continuous_20130316_200606.cap.gz
-rw-r--r-- 1 root root 3067111 Mar 16 20:11 tcpdump_continuous_20130316_200824.cap.gz
-rw-r--r-- 1 root root 2566943 Mar 16 20:15 tcpdump_continuous_20130316_201132.cap.gz

And this is the debug file:

# cat log.log 
ZIP the following file: /home/user/trace/tcpdump_continuous_20130316_200606.cap
ZIP the following file: /home/user/trace/tcpdump_continuous_20130316_200824.cap
ZIP the following file: /home/user/trace/tcpdump_continuous_20130316_201132.cap

Maybe tcpdump open a new file, but I've to test it. BTW, I don't understand why the script in root crontab doesn't work! :confused:

The fuser version would become something like:

for file in /home/user/trace/tcpdump*.cap
do
  if [ -z "$(fuser -- "$file" 2>/dev/null)" ]; then
    gzip "$file"
  fi
done

Thanks Scrutinizer,
this works too, but as always works on command line, but gzip all files if it starts from crontab. :frowning: