当前位置: 首页 > 代码生活, 我的研究 > 正文

遇到一个在脚本中读取文件内容占用文件句柄的小问题

一般来说,嵌入式设备的程序是上电自动运行的。设备系统启动后会自动运行某些系统级脚本(/ect/rc3.d/下的脚本),最终会运行我们自定义的脚本,在该脚本中会运行应用程序。——这就是系统自动启动的一般做法。
在测试中,发现如果升级在升级程序过程中断电(测试人员故意的,以模拟某些实际可能也许不会发生的事),则设备无法再启动。我们的设备使用硬盘存储系统文件,所谓“升级”,就是把程序文件写到磁盘分区某个目录上。深入了解后,发生写的文件大小全为0,当然是不正确的,程序无法执行,设备启动就不正常了。——根本原因是,恰好有一个自定义的脚本文件size为0,这个文件挂了,后面的过程就无法顺利执行了。后来想到一招。把核心的脚本单独升级,并且保证这个升级一定成功。其后的程序升级则无须升级该核心脚本。
在这个过程中,引发了另一个题目的小问题。虽然前文所述的值得深究,但不是本文重点。
启动脚本会去读一些文件的配置,使用exec的形式。下面的例子是读取bar文件,并判断其值是否为0,为0执行a.out(q.out为死循环,目的是为了a.out不退出)。如下:
########读文件内容
if [ -f bar ]; then

exec 3< bar read NUM <&3 echo $NUM # 判断是这样 if [ "X$NUM" = "X0" ] then echo "NUM is 0" ./a.out else echo "NUM not 0" fi fi 查询一下a.out进程所占用的文件描述符。结果如下: root@localhost:~# ps -ef | grep a.out root 12409 12405 0 08:55 pts/0 00:00:00 ../a.out root 12412 12386 0 08:55 pts/1 00:00:00 grep --color=auto a.out root@localhost:~# ll /proc/12409/fd total 0 dr-x------ 2 root root 0 Jul 27 08:55 ./ dr-xr-xr-x 7 root root 0 Jul 27 08:55 ../ lrwx------ 1 root root 64 Jul 27 08:55 0 -> /dev/pts/0
lrwx—— 1 root root 64 Jul 27 08:55 1 -> /dev/pts/0
lrwx—— 1 root root 64 Jul 27 08:55 2 -> /dev/pts/0
lr-x—— 1 root root 64 Jul 27 08:55 3 -> /mnt/latelee/test/simple_test/shell/bar

我们看到,脚本使用exec 3< bar将bar的内容读取文件描述符3里,由于a.out是一直循环,所以会一直占用着该描述符。 我们看另一个例子,不使用exec,而是直接用cat。如下: ######## 另一种方式 if [ -f bar ]; then # 只截至第一行的内容 NUM1=`cat bar | head -1` echo $NUM1 # 判断是这样 if [ "X$NUM1" = "X0" ] then echo "NUM1 is 0" ./a.out else echo "NUM1 not 0" fi fi 再次看a.out进行的文件描述符,结果如下: root@localhost:~# ps -ef | grep a.out root 12418 12414 0 08:56 pts/0 00:00:00 ../a.out root 12420 12386 0 08:56 pts/1 00:00:00 grep --color=auto a.out root@localhost:~# ll /proc/12418/fd total 0 dr-x------ 2 root root 0 Jul 27 08:56 ./ dr-xr-xr-x 7 root root 0 Jul 27 08:56 ../ lrwx------ 1 root root 64 Jul 27 08:56 0 -> /dev/pts/0
lrwx—— 1 root root 64 Jul 27 08:56 1 -> /dev/pts/0
lrwx—— 1 root root 64 Jul 27 08:56 2 -> /dev/pts/0
root@localhost:~#
我们看到,脚本已经不占用文件描述符了。
对于这个问题,似乎有点吹毛求疵,但很多时候遇到的问题,往往是小细节引发的,这不得不让我提高敏感度。
文中使用/proc/进程ID/fd目录查看指定进程的文件描述符,这个方法还是比较有用的,下文即将提到。
2015.7.30 李迟



本文固定链接: http://www.latelee.org/code-life/file-handle-occupy.html

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter