We have a script that runs and picks up some files to later be used in Oracle. Every now and again we get a ERROR 'filename' file is open We know for a fact the files are not open. The files are created early morning and not used until the next morning by the script. If we manually open the file then close it, the script will pick it up with no errors.
Anyone run into this issue? I am willing to post the script if need be.
You are redirecting errors to stdout. Is there ever the possibility that fuser errors and pass the bytes alone all the way to wc, evaluating to the equivalent of "FILE IS OPEN"? YES.
Allow me to show you the concept:
% ls do_not_exist
ls: cannot access do_not_exist: No such file or directory
% ls do_not_exist | wc -c
ls: cannot access do_not_exist: No such file or directory
0
% ls do_not_exist 2>&1 | wc -c
58
% ls do_not_exist 2>&1 | awk '{printf "%s", $2}' | wc -c
6
else
#log error because file is open
banner "* ERROR *"
echo "`date +'%m-%d-%Y %H:%M:%S'` ERROR $i file is open"
fail_notify;
One issue is that under some circumstances that evaluation is misrepresented, if fuser errors, because, the error stream pollutes the stdout stream with unwanted information.
Let me put it in another words: you have a bug. 2>&1 should not be there in this case
You could use 2> /dev/null
I think aka has a good point, but there is a slight complication to this, since according to the man page:
So when stderr is redirected to stdout ( 2>&1 ) the filename with a colon and a space is prepended to the process numbers and a newline is added at the end
If stderr is redirected to /dev/null ( 2>/dev/null ) then the first PID is no longer in column 2 (also there is no longer a closing newline) , so then the awk part is no longer required (nor will it work properly), so instead one could try:
if [ $(fuser -- "$i" 2>/dev/null | wc -c) -eq 0 ]
or
if [ -z "$(fuser -- "$i" 2>/dev/null)" ]
-- is used here, so that file names that start with a - cannot break the command... ( The pattern used in the for loop for i in *${cdate}* would leave that possibility open, whereas with for i in usb* that would not be strictly necessary, but it wouldn't hurt either)