Total Pageviews

Saturday, 24 October 2020

关于出错提示:'linux device busy'的分析

 本篇主要记录这个命令行工具的使用,主要目的是深入一点理解linux 文件系统的某些机制

  1. lsof命令
  2. fuser命令

本次测试环境,Raspbian只读系统(系统所在的分区及引导分区是只读挂载),只有少量可读写小分区挂载在内存(tmpfs),直接在root用户下进行测试

测试一:普通挂载之上再bind挂载

先准备好挂载

mkdir /mnt/bind
mkdir /testbind
mount -o bind /testbind /mnt/bind

对被bind挂载的目录持续写入,使之保挂device busy:

dd if=/dev/zero of=/testbind/testfile bs=1 oflag=dsync

执行fuser lsof

先测试fuser

//以下打印的头信息
//USER        PID ACCESS COMMAND

fuser -v -m /
//打印出的列表,有如下这条,F表明有打开并有写权限的文件
root       5676 Fr.e. dd

fuser -vm /testbind
//打印出的列表,同样有如下这条
root       5676 Fr.e. dd

fuser -vm /testbind/testfile
//这条等同于上条命令和上上条,自动转成testfile所在的挂载点`/`
root       5676 Fr.e. dd

fuser -v /testbind/testfile
//这条有点不一样了,只有针对此文件的相关信息,不过F同样表明这文件被打开并有权写入,如下
root       5676 F.... dd

fuser -v /mnt/bind
//这条跟前三条一样,并也有如下这条
root       5676 Fr.e. dd

fuser -vm /dev/mmcblk0p2
//这条跟前三条一样,并也有如下这条
root       5676 Fr.e. dd

综上似乎说明一点: 对于bind挂载,fuser命令加m参数的话,等同普通文件

再来测试lsof

// lsof 只能指定挂载点,不指定则用于当前系统中的所有文件系统
// 有别于fuser的是,lsof 不能在device上直接使用
lsof /|grep ^dd
//这条会打印如下信息(其它的不在这里列出来了),注意FD列,有个`1w`的表示此进程所打开的文件正在写入
dd        5676       root  rtd    DIR  179,2     4096      2 /
dd        5676       root  txt    REG  179,2    63424   1011 /bin/dd
dd        5676       root  mem    REG  179,2  1679808   7247 /usr/lib/locale/locale-archive
dd        5676       root  mem    REG  179,2  1234700   6580 /lib/arm-linux-gnueabihf/libc-2.24.so
dd        5676       root  mem    REG  179,2    21868   8231 /usr/lib/arm-linux-gnueabihf/libarmmem.so
dd        5676       root  mem    REG  179,2   138576   6572 /lib/arm-linux-gnueabihf/ld-2.24.so
dd        5676       root    1w   REG  179,2   141655 631956 /testbind/testfile

lsof |grep ^dd
//输出同上

lsof /mnt/bind|grep ^dd
//输出同上

现在来umout remount操作

umount /mnt/bind
//成功
mount -o remount,ro /
//mount: / is busy

现在停掉dd写入,改成写入到/mnt/bind去

dd if=/dev/zero of=/mnt/bind/testfile bs=1 oflag=dsync

执行fuser命令

//现在只用测试两条就行了
fuser -vm /
// 会有下面这条输出
root       8140 Fr.e. dd

fuser -v /testbind/testfile
// 会有下面这条输出
root       8140 F.... dd

fuser -v /mnt/bind/testfile
// 这条同上

执行lsof命令

lsof |grep ^dd
lsof /|grep ^dd
lsof /mnt/bind|grep ^dd
//这三条一样
// 只是第一条多了一条cwd记录,dd运行的当前目录确实不在系统所在的分区,所以只用于系统分区的lsof是不会列出来的

现在来umout remount操作

umount /mnt/bind
umount: /mnt/bind: target is busy
        (In some cases useful info about processes that
         use the device is found by lsof(8) or fuser(1).)
mount -o remount,ro /
mount: / is busy

停掉dd写入,改为写入连接文件,进行测试

(我的/home/git目录是挂载点)

touch /home/git/testfile
ln -s /home/git/testfile /
dd if=/dev/zero of=/testfile bs=1 oflag=dsync

现在来remount操作

mount -o remount,ro /
//成功
mount -o remount,ro /home/git
mount: /home/git is busy

停掉dd写入,改为写入连接的目录文件

dd if=/dev/zero of=/home/git/testfile bs=1 oflag=dsync

现在来remount操作,跟上面测试一样 说明一点连接文件跟预料中一样,bind的话有点出乎意料.

本人目前碰见一个很大迷惑点,我的Raspbian只读系统,自从安装了smbd,nmbd之后.出现了很诡秘的事情,一直找不出哪个进程在阻止remount 系统到只读模式,重启就好了,又不能马上复现,好吧,下回再碰见,我直接用lsof +D递归全文件stat式找一下看看. 先Mark一下,睡觉了…

关于lsof FD列的说明

  1. cwd:表示 current work dirctory,即:应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改
  2. txt:该类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序
  3. lnn: library references (AIX)
  4. er: FD information error (see NAME column)
  5. jld: jail directory(FreeBSD)
  6. ltx: shared library text(code and data)
  7. mxx: hex memory-mapped type number xx.
  8. m86:DOS Merge mapped file
  9. mem: memory-mapped file
  10. mmap: memory-mapped device
  11. pd: parent directory
  12. rtd: root directory
  13. tr: kernel trace file (OpenBSD)
  14. v86 VP/ix mapped file
  15. 0:表示标准输出
  16. 1:表示标准输入
  17. 2:表示标准错误

一般在标准输出、标准错误、标准输入后还跟着文件状态模式:r w u 等

  1. u:表示该文件被打开并处于读取/写入模式
  2. r:表示该文件被打开并处于只读模式
  3. w:表示该文件被打开并处于只写入模式
  4. 空格:表示该文件的状态模式为 unknown ,且没有锁定
  5. - : 表示该文件的状态模式为 unknown ,且被锁定

同时在文件状态模式后面,还跟着相关的锁

  1. N:for a Solaris NFS lock of unknown type
  2. r: for a read lock on part of the file
  3. R:for a read lock on the entire file
  4. w: for a write lock on part of the file (文件的部分写锁)
  5. W: for a write lock on the entire file(整个文件的写锁)
  6. u: for a read and write lock of any length
  7. U: for a lock of unknown type
  8. x: for an SCO OpenServer Xenix lock on part of the file
  9. X:for an SCO OpentServer Xenix lock on the entire file
  10. space : if there is no lock

No comments:

Post a Comment