在项目开发过程中,经常会遇到卸载设备文件,一定对“Device or resource busy”打印比较熟悉,说明有进程正在使用准备卸载的设备文件导致卸载失败,这时候我们一般做法是找出正在使用设备文件的进程然后杀掉最后成功卸载,下面介绍一种使用脚本自动杀掉对应进程的脚本方法。
原理
查看/proc下面进程号创建的文件描述符是否指向目标设备文件目录,查看进程号目录下的cwd(指向当前进程运行目录的一个符号链接)是否指向目标设备文件目录。
lrwx------ 1 root root 64 Apr 1 16:38 17 -> /vdr/data/stop
lrwxrwxrwx 1 root root 0 Apr 1 18:11 cwd -> /vdr
脚本
#!/bin/sh
stop_process(){
local flag=0
local i=1
while [ $flag -eq 0 ];do
stop_pid "/vdr" $i
flag=$?
# execute times
let i=i+1
done
}
stop_pid(){
local pid
local ret=1
local run_in_dir="$1"
local time=$2
echo "Try stop process run in $run_in_dir $time times"
for file in $(ls /proc 2>/dev/null);do
pid=$(expr $file + 0 2>/dev/null)
[ -n "$pid" ] && {
# Stop pid which run from $run_in_dir
linkdir=$(ls -l /proc/$pid 2>/dev/null| grep cwd | awk '{print $11}' 2>/dev/null)
[ "$linkdir" == "$run_in_dir" ] && {
pidname=$(cat /proc/${pid}/comm)
kill $pid
kill -9 $pid
ret=0
echo "Stop process $pidname($pid),because it run from $run_in_dir"
}
# Stop pid which use fd from $run_in_dir
$(ls -l /proc/$pid/fd/ 2>/dev/null | grep $run_in_dir 2>/dev/null >/dev/null)
[ $? -eq 0 ] && {
pidname=$(cat /proc/${pid}/comm)
kill $pid
kill -9 $pid
ret=0
echo "Stop process $pidname($pid),because it use some file or dir from $run_in_dir"
}
}
done
# No process found in run_dir, we return 1
return $ret
}
stop_process
sync
打印
Try stop process run in /vdr 1 times
Stop process sleep(1132),because it use some file or dir from /vdr
Stop process minivdr_disable(2084),because it use some file or dir from /vdr
Stop process check_modem_qcm(2092),because it use some file or dir from /vdr
Stop process vdr_check_ssd.s(2209),because it use some file or dir from /vdr
Stop process vdrd(2326),because it use some file or dir from /vdr
Stop process vdrd_dog.sh(2330),because it use some file or dir from /vdr
Stop process wifigps.sh(2341),because it use some file or dir from /vdr
Stop process t.sh(32677),because it run from /vdr
Stop process t.sh(32677),because it use some file or dir from /vdr
Stop process t.sh(32678),because it run from /vdr
Stop process t.sh(400),because it run from /vdr
扩展
fusermount -z -u /vdr