Skip to content

Instantly share code, notes, and snippets.

@dvoita
Created February 12, 2018 23:21
Show Gist options
  • Save dvoita/74ea8cba4a133a739eaad921a99b7689 to your computer and use it in GitHub Desktop.
Save dvoita/74ea8cba4a133a739eaad921a99b7689 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# Wraps 'rkt gc' to handle when rkt cannot successfully remove an old pod
# because it is still mounted in some processes' namespace. To use, pass
# options you would normally pass to 'rkt gc':
# Example: sudo ./rkt-gc.rb --grace-period=0s
require 'open3'
def with_error_handling
yield
rescue Errno::ENOENT, Errno::EINVAL => e
[]
end
def run_command(cmd, show_stdout = false)
result = {}
result[:stdout], result[:stderr], result[:status] = Open3.capture3(cmd)
puts result[:stdout] if show_stdout
unless result[:status].success?
puts result[:stderr]
exit(result[:status].exitstatus)
end
result
end
raw_gc = run_command("/usr/bin/rkt gc #{ARGV.join(' ')}", true)
busy_mount_points = []
raw_gc[:stderr].lines.each do |line|
if line =~ /device or resource busy$/
busy_mount_points << line.split.grep(/exited-garbage/).first.chomp(':')
end
end
if busy_mount_points.size > 0
Dir.glob('/proc/*/mountinfo').each do |m|
lines = with_error_handling do
File.open(m, 'r') do |f|
f.readlines
end
end
busy_mount_points.each do |mount_point|
results = lines.grep(/#{mount_point}/)
if results.size > 0
pid = m.strip.split('/')[2]
run_command("/usr/bin/nsenter -m -p -t #{pid} umount --recursive #{mount_point}")
end
end
end
# All mounts are now unmounted, so rerun rkt gc
run_command("/usr/bin/rkt gc #{ARGV.join(' ')}")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment