/proc/プロセス番号/fd/ファイル記述子
は、そのプロセスの開いているファイルをシンボリックリンクで指し示しているのでコレを使う。
fuser.rb
USAGE = <<USAGE
$0 [FILE]...
ファイルを開いている pid を出力
USAGE
file_paths = ARGV.select{|fp| File.exist? fp }.
map{|fp| File.expand_path fp}
if file_paths.empty?
puts USAGE
exit 1
end
fp_pids_map = Hash.new {|h,k| h[k] = [] }
Dir.glob '/proc/*/fd/*' do |fd|
fp = File.readlink(fd) rescue next
if file_paths.include?(fp)
pid = fd.sub(%r!/proc/(\d+)/fd/\d+!, '\1').to_i
fp_pids_map[fp] << pid
end
end
fp_pids_map.each{|v| puts '%s: %s' % v}
使ってみる:
$ touch foo
$ ruby -e 'open "foo"; sleep' &
[1] 9918
$ ruby -e 'open "foo"; sleep' &
[2] 10281
$ ruby tmp/fuser.rb foo
/home/kui/foo: [9918, 10281]
できてるっぽい。