如何确定文件是否在FreeBSD上的bash脚本中打开

时间:2019-02-18 19:32:19

标签: bash freebsd fuser

我正在尝试将Linux bash脚本移植到FreeBSD。该脚本需要先检查文件是否已打开(用于写入),然后再决定是否采取某些措施。

在Linux上,使用fuser命令很容易:

if [[ ! `/usr/bin/fuser "$FILE"` ]]
     then
     ...
fi

但是,在FreeBSD上,fuser命令似乎完全坏了(由this证实),并且没有向stdout返回任何正确的退出代码或任何有用的输出。例如,在正在被主动写入的文件上:

# fuser file 
file:

编辑:


弗拉基米尔·博特卡(Vladimir Botka)的评论:

  

“在FreeBSD 12.0中显示了简单测试”:

# tail -f /scratch/test-file`
# fuser /scratch/test-file
/scratch/test-file: 45042
# echo $?
0
# ps ax | grep 45042
45042  0  I+       0:00.00 tail -f /scratch/test-file
45232  1  R+       0:00.00 grep 45042

在我的FreeBSD盒子(也是FreeBSD 12)上,相同的测试得出以下结果:

# tail -f /scratch/test-file
# fuser /scratch/test-file
/scratch/test-file:
# echo $?
0

弗拉基米尔·博特卡(Vladimir Botka)的评论:

  

让我们尝试使用一个简单的C程序来测试对文件的写入   打开文件,等待输入,然后将输入写入文件。

这是我对已编译的C代码的测试:

# ./a.out
Enter num:

# fuser /scratch/test-file
/scratch/test-file:
# echo $?
0

因此,fuser确实坏了。但是,这似乎只在我的系统上出现问题,在Vladimir Botka的系统上却没有出现,这很奇怪,因为它们都是FreeBSD 12。


似乎我可以使用lsoffstat来获取此信息,但是如果不对输出进行一些复杂的解析,这会使我的脚本更加复杂。我想知道是否有人可以指向我一个简单的“是/否”命令来确定是否正在使用像fuser这样的文件就可以在FreeBSD上使用?

非常感谢,

4 个答案:

答案 0 :(得分:2)

您的索赔

  

“在FreeBSD上,定影器命令似乎完全坏了”

指的是Port details: fuser POSIX fuser utility for FreeBSD,它已不推荐使用,并于2012年11月26日到期

让我们在FreeBSD 12.0中尝试这个简单的测试。打开终端并运行

# touch /scratch/test-file
# tail -f /scratch/test-file

保留 tail 等待 test-file 的内容。打开第二个终端并运行

# fuser /scratch/test-file
/scratch/test-file: 45042
# echo $?
0
# ps ax | grep 45042
45042  0  I+       0:00.00 tail -f /scratch/test-file
45232  1  R+       0:00.00 grep 45042

让我们尝试使用一个简单的C程序来测试对文件的写入,该程序会打开文件,等待输入,然后将输入写入文件。

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int num;
   FILE *fptr;
   fptr = fopen("/scratch/test-file","w");
   printf("Enter num: ");
   scanf("%d",&num);
   fprintf(fptr,"%d",num);
   fclose(fptr);
   return 0;
}

# ./a.out 
Enter num: 

让程序等待输入。打开第三个终端并运行

# fuser /scratch/test-file
/scratch/test-file: 45448w 45042
# echo $?
0
# ps ax | grep 45448
45448  0  I+       0:00.00 ./a.out
45464  1  S+       0:00.00 grep 45448

如果打开了要写入的文件,则 fuser 会将“ w”附加到PID并进行报告

  

w ...文件已打开可写入。

简单的bash脚本

#!/usr/local/bin/bash
my_file=/scratch/test-file
result=`fuser $my_file 2>&1`
pid=`echo $result | cut -d ':' -f 2-`
if [ -z "$pid" ]; then
    echo "$my_file is not opened by any process"
else
    echo "$my_file is opened by process PID(s): $pid"
fi

显示

# ./test.bash
/scratch/test-file is opened by process PID(s): 45448w 45042

分别

# ./test.bash
/scratch/test-file is not opened by any process

如果这对您不起作用,请参见How to create a Minimal, Complete, and Verifiable example以提供详细信息。

答案 1 :(得分:1)

我得出结论,fuser在FreeBSD中已损坏。最后,我分析了fstat输出以解决该问题。 fstat在正在被主动写入的文件上产生以下输出(还有另一个进程在读取该文件,因此有两行):

# fstat file 
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME
root     smbd       36299   41 /data    1282756 -rwxr--r--  7407140864 rw  file
root     smbd       36295   30 /data    1282756 -rwxr--r--  7407140864  r  file

以下bash代码使用fstat测试文件,删除标题行(sed),然后使用awk来获取第9列,该列与文件是否开放供阅读或写作。然后,grep随即在任一行中寻找w写标志。如果找到一个,它将返回true。整个条件都被否定(!),以确保仅在不使用文件的情况下才执行操作:

 if [[ ! `/usr/bin/fstat "$FILE" | sed 1d | awk '{print $9}' | grep "w"` ]]
 then
    ... do something ...
 fi

答案 2 :(得分:0)

例如,如果fuser在您的系统中不起作用,并且可以进行一些解析,则尝试打开fstat,例如,在打开文件的情况下:

$ cat > /tmp/test

这是fstat /tmp/test的输出:

# fstat /tmp/text
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME
root     cat        39590    1 [restricted]   3812 -rw-r--r--       0  w  /tmp/text

如果该文件未被使用,您将仅获得标题:

# fstat /tmp/text
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME

因此,您可以使用类似以下内容的

[ `fstat /tmp/test | wc -l` -gt 1 ] && echo "in use"

test `fstat /tmp/test | wc -l` -gt 1 && echo "in use"

答案 3 :(得分:0)

您描述为“中断”的行为也可能是正确的行为,具体取决于进程所有者的权限。

除非您具有root或同等特权并且可以查看其他用户的进程,否则您将只能通过fuser查看自己的进程。确保您以同一/ root用户身份运行两个会话。