我正在尝试将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。
似乎我可以使用lsof
或fstat
来获取此信息,但是如果不对输出进行一些复杂的解析,这会使我的脚本更加复杂。我想知道是否有人可以指向我一个简单的“是/否”命令来确定是否正在使用像fuser
这样的文件就可以在FreeBSD上使用?
非常感谢,
答案 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用户身份运行两个会话。