umount-many 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +16 -0
- data/TODO +3 -0
- data/VERSION +1 -0
- data/bin/umount-many +60 -0
- data/lib/umount-many.rb +123 -0
- metadata +65 -0
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "umount-many"
|
5
|
+
gem.executables = "umount-many"
|
6
|
+
gem.summary = "Unmount several devices based on filters"
|
7
|
+
gem.email = "sin3141592@gmail.com"
|
8
|
+
gem.homepage = "http://github.com/hackenporsche/umount-many"
|
9
|
+
gem.description = gem.summary
|
10
|
+
gem.authors = ["Hagbard Celine"]
|
11
|
+
#gem.files = FileList["bin/**/*", "lib/**/*"]
|
12
|
+
end
|
13
|
+
Jeweler::GemcutterTasks.new
|
14
|
+
rescue LoadError
|
15
|
+
puts "Couldn't load jeweler. Please install it with `gem install jeweler`"
|
16
|
+
end
|
data/TODO
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/umount-many
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require File.join(File.dirname(__FILE__), "..", "lib", "umount-many")
|
6
|
+
|
7
|
+
def main
|
8
|
+
opts = Hash.new
|
9
|
+
OptionParser.new do |opt|
|
10
|
+
opt.on("-m", "--mount-point MOUNTPOINT",
|
11
|
+
"Unmount all file systems mounted on MOUNTPOINT") do |mp|
|
12
|
+
opts[:mount_point] = mp
|
13
|
+
end
|
14
|
+
|
15
|
+
opt.on("-d", "--device DEVICE",
|
16
|
+
"Unmount all file system mounted from DEVICE") do |d|
|
17
|
+
opts[:device] = d
|
18
|
+
end
|
19
|
+
|
20
|
+
opt.on("-t", "--type TYPE",
|
21
|
+
"Unmount all file systems having TYPE as file system") do |t|
|
22
|
+
opts[:type] = t
|
23
|
+
end
|
24
|
+
|
25
|
+
opt.on("-o", "--option OPTION",
|
26
|
+
"Unmount all file systems having OPTION set") do |o|
|
27
|
+
opts[:options] ||= []
|
28
|
+
opts[:options] << o
|
29
|
+
end
|
30
|
+
|
31
|
+
opt.on("-a", "--all",
|
32
|
+
"Unmount every file system (CAUTION: Can be dangerous)") do
|
33
|
+
opts[:all] = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opt.on("-s", "--simulate", "List the file systems to unmount "+
|
37
|
+
"but do not unmount anything. See -r as well") do
|
38
|
+
opts[:simulate] = true
|
39
|
+
end
|
40
|
+
|
41
|
+
opt.on("-r", "--report FORMAT", "Instead of unmounting anything " +
|
42
|
+
"report matched devices to stdout. Differs from -s in " +
|
43
|
+
"printing standardized format like Yaml. FORMAT can be " +
|
44
|
+
"Yaml, JSON or XML") do |format|
|
45
|
+
opts[:reporting] = format
|
46
|
+
end
|
47
|
+
|
48
|
+
opt.on("-v", "--verbose", "Print currently unmounted device") do
|
49
|
+
opts[:verbose] = true
|
50
|
+
end
|
51
|
+
|
52
|
+
opt.on("-R", "--reverse", "Reverse the list of devices. Last mounted " +
|
53
|
+
"devices are unmounted first") do
|
54
|
+
opts[:reverse] = true
|
55
|
+
end
|
56
|
+
end.parse!
|
57
|
+
unmount_many_fs(opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
main if $0 == __FILE__
|
data/lib/umount-many.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
# == umount-many
|
5
|
+
# umount-many allows you to unmount several file systems at once
|
6
|
+
# You can specify several filter types to select the desired file systems
|
7
|
+
# For example:
|
8
|
+
# +umount-many -t ext4+
|
9
|
+
# This command unmounts every file system that has ext4 as file system type
|
10
|
+
# For a list of all filters use the +-h+ or +--help+ command line option
|
11
|
+
|
12
|
+
require 'optparse'
|
13
|
+
require 'set'
|
14
|
+
|
15
|
+
class Hash
|
16
|
+
# Works similiar to the +values_at+ method but return
|
17
|
+
# instead of just values an appropriate hash
|
18
|
+
def hash_at(*keys)
|
19
|
+
hash = Hash.new
|
20
|
+
keys.zip(self.values_at(*keys)).each {|k, v| hash[k] = v}
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_file_systems
|
26
|
+
# TODO: Currently calls +mount+ and parses stdout. Not such a good
|
27
|
+
# approach, is it?
|
28
|
+
# TODO: I just can the regex gurantee to work for my box (which is a linux
|
29
|
+
# 2.6.31 with +mount+ from util-linux-ng 2.16)
|
30
|
+
|
31
|
+
filesystems = []
|
32
|
+
IO.popen("mount") do |pipe|
|
33
|
+
pipe.each_line do |line|
|
34
|
+
if line =~ /([^\s]+) on ([^\s]+) type ([^\s]+) \((.*)\)/
|
35
|
+
filesystems.push({:device => $1, :mount_point => $2, :type => $3,
|
36
|
+
:options => $4.split(",")})
|
37
|
+
else
|
38
|
+
STDERR.puts("Couldn't parse output from mount. " +
|
39
|
+
"Skipping current line")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
filesystems
|
44
|
+
end
|
45
|
+
|
46
|
+
def filter_by_device(filesystems, device)
|
47
|
+
filesystems.select {|e| e[:device] == device}
|
48
|
+
end
|
49
|
+
|
50
|
+
def filter_by_mount_point(filesystems, mp)
|
51
|
+
filesystems.select {|e| e[:mount_point] == mp}
|
52
|
+
end
|
53
|
+
|
54
|
+
def filter_by_type(filesystems, type)
|
55
|
+
filesystems.select {|e| e[:type].downcase == type.downcase}
|
56
|
+
end
|
57
|
+
|
58
|
+
def filter_by_options(filesystems, option)
|
59
|
+
filesystems.select {|e| e[:options].include?(option)}
|
60
|
+
end
|
61
|
+
|
62
|
+
def collect_filters(opts)
|
63
|
+
filters = []
|
64
|
+
opts.hash_at(:mount_point, :device, :type, :options).each do |filter, v|
|
65
|
+
filters.push filter if v && !v.empty?
|
66
|
+
end
|
67
|
+
filters.map{|e| [method("filter_by_" + e.to_s), e]}
|
68
|
+
end
|
69
|
+
|
70
|
+
def report_results(to_unmount, format)
|
71
|
+
unless ["yaml", "json", "xml"].include?(format)
|
72
|
+
puts "Not a supported format for reporting: #{format}"
|
73
|
+
puts "See the help (-h) for a list"
|
74
|
+
exit 2
|
75
|
+
end
|
76
|
+
if format.downcase == "xml"
|
77
|
+
# TODO: I am not quite sure if XmlSimple makes proper output
|
78
|
+
STDERR.puts "WARNING: XML format is experimental."
|
79
|
+
require 'xmlsimple'
|
80
|
+
puts XmlSimple.xml_out(to_unmount)
|
81
|
+
else
|
82
|
+
require format
|
83
|
+
meth = to_unmount.method("to_" + format)
|
84
|
+
puts meth.call
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def unmount_devices(devices, verbose)
|
89
|
+
devices.each do |device|
|
90
|
+
if verbose
|
91
|
+
print ("Unmounting #{device[:device]} mounted on " +
|
92
|
+
"#{device[:mount_point]}... ")
|
93
|
+
end
|
94
|
+
system "umount \"#{device[:device]}\""
|
95
|
+
# Needed because umount takes a bit of time
|
96
|
+
sleep 0.2
|
97
|
+
puts "DONE" if verbose
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def matched_devices(opts)
|
102
|
+
filesystems = parse_file_systems
|
103
|
+
filters = collect_filters(opts)
|
104
|
+
to_unmount = Set.new
|
105
|
+
results = filters.map {|meth, name| meth.call(filesystems, opts[name])}
|
106
|
+
results.each {|devices| to_unmount += Set.new(devices)}
|
107
|
+
to_unmount = to_unmount.to_a
|
108
|
+
to_unmount.reverse! if opts[:reverse]
|
109
|
+
to_unmount
|
110
|
+
end
|
111
|
+
|
112
|
+
def unmount_many_fs(opts)
|
113
|
+
to_unmount = matched_devices(opts)
|
114
|
+
if opts[:simulate]
|
115
|
+
# TODO: think of a human readable format for -s
|
116
|
+
require 'pp'
|
117
|
+
pp to_unmount
|
118
|
+
elsif opts[:reporting]
|
119
|
+
report_results(to_unmount, opts[:reporting])
|
120
|
+
else
|
121
|
+
unmount_devices(to_unmount, opts[:verbose])
|
122
|
+
end
|
123
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: umount-many
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Hagbard Celine
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-18 00:00:00 +02:00
|
18
|
+
default_executable: umount-many
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Unmount several devices based on filters
|
22
|
+
email: sin3141592@gmail.com
|
23
|
+
executables:
|
24
|
+
- umount-many
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- TODO
|
29
|
+
files:
|
30
|
+
- Rakefile
|
31
|
+
- TODO
|
32
|
+
- VERSION
|
33
|
+
- lib/umount-many.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/hackenporsche/umount-many
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --charset=UTF-8
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.3.6
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: Unmount several devices based on filters
|
64
|
+
test_files: []
|
65
|
+
|