linux命令fuser详解
2019-06-27 22:35:12 阿炯

fuser命令用于报告进程使用的文件和网络套接字的使用情况,为psmisc的子工具。该命令列出了本地进程的进程号及其所使用的本地或远程文件。特别对于被阻塞的设备,此命令列出了使用该设备上任何文件的进程,每个进程号后面都跟随一个字母,该字母指示进程如何使用文件。

fuser command shows the PIDs of processes using the specified files or file systems in Linux.

kill process by port
kill a process according to which port number it is using.

用法:fuser [-fIMuvw] [-a|-s] [-4|-6] [-c|-m|-n 命名空间] [-k [-i] [-信号]] 名字...
fuser -l
fuser -V
显示哪些进程使用指定的文件、端口或文件系统。
-a,--all              也显示未使用的文件
-i,--interactive      杀死程序前询问 (未指定 -k 选项时被忽略)
-I,--inode            总是使用 inode 来比较文件
-k,--kill             杀死访问指定文件的进程
-l,--list-signals     列出可用的信号名
-m,--mount            显示所有使用指定文件系统或块设备的进程
-M,--ismountpoint     只在 <名字> 为挂载点时完成要求
-n,--namespace 空间   在指定命名空间中查找 (file、udp 或 tcp)
-s,--silent           不输出信息
-[SIGNAL|信号]                 发送指定的 "信号" 而不是 SIGKILL
-u,--user             显示用户 ID
-v,--verbose          输出更多信息
-w,--writeonly        只杀死有权写入的进程
-V,--version          显示版本信息
-4,--ipv4             仅查找 IPv4 套接字
-6,--ipv6             仅查找 IPv6 套接字
-                     重置选项

udp/tcp 名字格式: [本地端口][,[远程主机][,[远程端口]]]

在对sockets的信息查看上,默认会将ipv4与ipv6的信息同时打印出来,可通过传入参数'-4'或'-6'来分别输出其相关信息。

说明:这些进程号后面的字母要表达什么意思(访问修饰符(access symbol))
c:指示进程的工作目录,将此文件作为当前目录使用(presents the current directory)。
e:指示该文件为进程的可执行文件(即进程由该文件拉起),将此文件作为程序的可执行对象使用(Executable being run)。
f:指示该文件被进程打开,默认情况下f字符不显示(Open file)。
F:指示该文件被进程打开进行写入,默认情况下F字符不显示(File open for writing)。
r:指示该目录为进程的根目录,将此文件作为根目录使用(Root directory)。
m:指示进程使用该文件进行内存映射,抑或该文件为共享库文件,被进程映射进内存(mmap'ed file or shared library)。
s:将此文件作为共享库(或其他可装载对象)使用

当指定的文件没有被访问,或者出现错误的时候,fuser会返回非零。为了查看使用tcp和udp套接字的进程,需要-n选项并指定名称空间。默认Ipv4和Ipv6都会显示。套接字可以是本地的或者是远程的端口,和远程的地址。所有的域是可选的,但是其前面的','必须存在。如下:[lcl_port][,[rmt_host][,[rmt_port]]]  
对于ip地址和port,名称和数字表示都可以使用。

fuser只把PID输出到标准输出,其他的都输出到标准错误输出。 使用fuser指令可以显示出当前哪个程序在使用磁盘上的
某个文件
挂载点
甚至网络端口

语法
fuser(选项)(参数)

常用选项
列出进程的详细信息,而不仅仅是进程id,用-v参数即可,含义是:verbose output,详细的输出信息。
-a 显示所有命令行中指定的文件,默认情况下被访问的文件才会被显示。
-c 和-m一样,用于POSIX兼容。
-k 杀掉访问文件的进程,如果没有指定-signal就会发送SIGKILL信号。与–signal相结合。
-signal 使用指定的信号,而不是用SIGKILL来杀掉进程。可以通过名称或者号码来表示信号(例如-HUP,-1),这个选项要和-k一起使用,否则会被忽略。
-l 列出所有已知的信号名称。
-i 杀掉进程之前询问用户,如果没有-k这个选项会被忽略。
-m name 指定一个挂载文件系统上的文件或者被挂载的块设备(名称name)。这样所有访问这个文件或者文件系统的进程都会被列出来。如果指定的是一个目录会自动转换成"name/",并使用所有挂载在那个目录下面的文件系统。
-n space 指定一个不同的命名空间(space).这里支持不同的空间文件(文件名,此处默认)、tcp(本地tcp端口)、udp(本地udp端口)。对于端口,可以指定端口号或者名称,如果不会引起歧义那么可以使用简单表示的形式,例如:name/space (即形如:80/tcp之类的表示)。
-s 静默模式,这时候-u,-v会被忽略。-a不能和-s一起使用。
-u 在每个PID后面添加进程拥有者的用户名称。
-v 详细模式。输出似ps命令的输出,包含PID,USER,COMMAND等许多域,如果是内核访问的那么PID为kernel.

详细选项
-a 显示所有命令行中指定的文件,默认情况下被访问的文件才会被显示。
-c 和-m一样,用于POSIX兼容。
-k 杀掉访问文件的进程。如果没有指定-signal就会发送SIGKILL信号。
-i 杀掉进程之前询问用户,如果没有-k这个选项会被忽略。
-l 列出所有已知的信号名称。
-m name 指定一个挂载文件系统上的文件或者被挂载的块设备(名称name)。这样所有访问这个文件或者文件系统的进程都会被列出来。如果指定的是一个目录会自动转换成"name/",并使用所有挂载在那个目录下面的文件系统。
-n space 指定一个不同的命名空间(space).这里支持不同的空间文件(文件名,此处默认)、tcp(本地tcp端口)、udp(本地udp端口)。对于端口, 可以指定端口号或者名称,如果不会引起歧义那么可以使用简单表示的形式,例如:name/space (即形如:80/tcp之类的表示)。
-s 静默模式,这时候-u,-v会被忽略。-a不能和-s一起使用。
-signal 使用指定的信号,而不是用SIGKILL来杀掉进程。可以通过名称或者号码来表示信号(例如-HUP,-1),这个选项要和-k一起使用,否则会被忽略。
-u 在每个PID后面添加进程拥有者的用户名称。
-v 详细模式。输出似ps命令的输出,包含PID,USER,COMMAND等许多域,如果是内核访问的那么PID为kernel.  -V 输出版本号。
-4 使用IPV4套接字,不能和-6一起应用,只在-n的tcp和udp的命名存在时不被忽略。
-6 使用IPV6套接字,不能和-4一起应用,只在-n的tcp和udp的命名存在时不被忽略。
- 重置所有的选项,把信号设置为SIGKILL。

signal列表
# fuser -l
# kill -l


用法示例1

列出使用/etc/filesystems文件的进程的进程号和用户登录名,请输入:
fuser -u /etc/files

列出进程所属的用户用 -u参数即可
说明: -u: 含义:display user IDs,显示用户id

要终止使用给定文件系统的所有进程,请输入:
fuser -k -x -u -c /dev/sda1  或者  fuser -kxuc /home

任一命令都列出了进程号和用户名,然后终止每个正在使用/dev/hda1 (/home)文件系统的进程。仅有root用户能终止属于另一用户的进程。如果正在试图卸下/dev/hda1文件系统,而一个正在访问/dev/hda1文件系统的进程不允许这样的操作,就可以使用此命令。

显示使用某个文件的进程信息
$ fuser -um /dev/sda2  

这个命令在umount的时候很有用,可以找到还有哪些进程用到这个设备了。

杀掉打开readme文件的程序
fuser -m -k -i readme  

在此会在kill之前询问是否确定,最好加上-v以便知道将要杀那个进程。

查看那些程序使用tcp的80端口
fuser -v -n tcp 80

# fuser -v 80/tcp
                     USER        PID ACCESS COMMAND
80/tcp:              root        347 F.... nginx
                     nginx       348 F.... nginx
                     nginx       349 F.... nginx


fuser -n 80/tcp
fuser -v 80/tcp
fuser 3306/tcp    #最简单的输出
fuser -k 3306/tcp    #kill该侦听该端口的应用程序


fuser不同信号的应用
用'-l'参数可以列出fuser所知的信号
fuser -l

fuser可以发送它已知的信号给访问的指定文件进程而代替-k参数默认发送的SIGKILL,例如:只是挂起进程,那么发送HUP信号就可以了。
fuser -v /home/freeoa.txt
用户     进程号 权限   命令
/home/freeoa.txt:   root       3357 f.... tail

fuser -k -SIGHUP /home/freeoa.txt
/root/install.log:    3357

fuser -v /home/freeoa.txt

杀死所有正在访问指定文件的进程用-k参数即可。
说明:-k: kill processes accessing the named file;
说明:-k参数能够杀死所有的正在访问指定文件的进程,所以用来杀进程时非常方便;
说明:fuser通过发送SIGKILL信号来杀死的进程。


用法示例2

use ss and lsof to see processes using a port number, kill process by port number with fuser, use socat to create a dummy process for testing.

lsof -i :873
lsof -i TCP:80
lsof -t -i tcp:80
lsof -t -i:873 -sTCP:LISTEN
lsof -i tcp:8080 | awk '/8080/{print $2}'

lsof 中的两个选项:
-t - show only process ID
-i - show only internet connections related process

Testing with socat

Bind a process to TCP port 8080:
$ socat tcp-listen:8080,bind=127.0.0.1 stdout &

Bind a process to UDP port 8080:
$ socat udp-listen:8080,bind=127.0.0.1 stdout &

Bind a process to SCTP port 8080:
$ socat sctp-listen:8080,bind=127.0.0.1 stdout &

Terminate processes utilizing TCP port 80
$ fuser -k 8080/tcp

Or to kill a process on UDP port 8080 with fuser:
$ fuser -k 8080/udp


fuser [directory]
fuser -v .
查看哪些进程在当前目录下被使用,有如下的信息列输出:
用户(USER)、进程号(PID)、权限(ACCESS)、命令(COMMAND)。

查看指定文件的使用情况
fuser -v [filename]
$ fuser -v MozillaUpdateLock-4F8A...
 用户     进程号 权限   命令
/tmp/MozillaUpdateLock-4F8A...:
 hto        1911 f.... firefox-bin

sockets使用情况

fuser -v -n [socket_type] [port]
Or:
fuser -v [port]/[socket_type]

$ nc -l -p 8002
使用netcat创建一个tcp侦听于8002端口上,在使用fuser来查看其信息:
$ fuser -v -n tcp 8002

查看对指定文件系统目录的信息情况:列出指定文件所在挂载点文件系统上所有进程的访问情况。
fuser -v -m freeoa_new_text

'-k'选项,最为常用的是Kill相关的进程,可指定文件类型,结合'-k'选项来终止使用该文件的进程(非文件所在挂载点的所有进程)。
fuser -v -k /home/sara/freeoa_new_text

如果不需要自动或立即执行,即以交互的方式运行,带上'-i'参数即可。

中止/home目录下的所有访问进程
fuser -ki -m /home/

中止当前目录的使用进程
fuser -ki .

fuser -k -[SIGNAL] [file_or_directory_or_socket]
SIGNAL信息列表可以使用fuser带'-l'的参数查看,可使用其简写或数字编号。如-TERM or -5 as -[SIGNAL];即发送非KILL类的信号只需要在'-k'后加上该信号的名称或编号。

fuser -ki -5 996/tcp
fuser -ki -TERM -n tcp 996

查看标准的信号名与编号等信息可从该手册页中查找:
man 7 signal

在此提供一个Perl测试用例,可向脚本发送hup,usr1,usr2信号来看执行结果,int信号就会让其退出。这里特意拉起了一个tcp的socket。

use v5.20;
use IO::Socket::INET;

sub hdsig_hup{state $n;say 'Got Hup:',++$n}
sub hdsig_usr1{state $n;say 'Got Usr1:',++$n}
sub hdsig_usr2{state $n;say 'Got Usr2:',++$n}
sub hdsig_int{say 'Caught Int. Exiting...:';exit}

say "Pid is:$$";

foreach my $sig(qw(int hup usr1 usr2)){
    $SIG{uc $sig}="hdsig_${sig}";
}

while(1){
    # Creating a listening socket
    my $socket = new IO::Socket::INET (
        LocalHost => '0.0.0.0',
        LocalPort => '6789',
        Proto => 'tcp',
        Listen => 5,
           Reuse => 1
    );
    die "Cannot create socket $!\n" unless $socket;
    sleep 1;
}