/
fuser.py
executable file
·83 lines (65 loc) · 2.15 KB
/
fuser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python2.7
"""\
usage: pgctl-fuser [-d] file [file ...]
Shows the pids (of the current user) that have this file opened.
This is useful for finding which processes hold a file lock (flock).
This has the same behavior as `lsof -t file`, but is *much* faster.
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
from .debug import trace
def stat(path):
from os import stat
try:
return stat(path)
except EnvironmentError as error:
trace('fuser suppressed: %s', error)
return None
def listdir(path):
from os import listdir
try:
return listdir(path)
except EnvironmentError as error:
trace('fuser suppressed: %s', error)
return ()
def fuser(path, allow_deleted=False):
"""Return the list of pids that have 'path' open, for the current user"""
search = stat(path)
if search is None and not allow_deleted:
return
from glob import glob
for fddir in glob('/proc/*/fd/'):
try:
pid = int(fddir.split('/', 3)[2])
except ValueError:
continue
fds = listdir(fddir)
for fd in fds:
from os.path import join
fd = join(fddir, fd)
found = stat(fd)
if found is None:
# fd disappeared since we listed
continue
if found == search:
yield pid
break
if allow_deleted and found.st_nlink == 0:
from os import readlink
if readlink(fd) == path + ' (deleted)':
yield pid
break
def main(args=None):
from argparse import ArgumentParser
from sys import argv
args = args or argv
parser = ArgumentParser(description=__doc__)
parser.add_argument('-d', '--allow-deleted', action='store_true', help='allow deleted files')
parser.add_argument('file', nargs='+')
args = parser.parse_args(args[1:])
for f in args.file:
for pid in fuser(f, allow_deleted=args.allow_deleted):
print(pid)
if __name__ == '__main__':
exit(main())