summaryrefslogtreecommitdiff
path: root/lib/byteback/util.rb
blob: 9a993d61db712d7288e7a28716767832534e0e6c (plain)
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
require 'tempfile'

module Byteback
  module Util
    @@lockfile = '/var/lock/byteback/byteback.lock'

    def remove_lockfile!
      File.unlink(@@lockfile)
    rescue Errno::ENOENT
    end

    def claim_lockfile!
      # Check the lockfile first
      if File.directory?(File.dirname(@@lockfile))
        if File.exist? @@lockfile
          # check the lockfile is sane
          exist_pid = File.read(@@lockfile).to_i
          if exist_pid > 1 && exist_pid < (File.read('/proc/sys/kernel/pid_max').to_i)
            begin
              Process.getpgid(exist_pid)
              # if no exception, process is running, abort
              fatal("Process is running (#{exist_pid} from #{@@lockfile})")
            rescue Errno::ESRCH
              # no process running with that pid, pidfile is stale
              remove_lockfile!
            end
          else
            # lockfile isn't sane, remove it and continue
            remove_lockfile!
          end
        end
      else
        Dir.mkdir(File.dirname(@@lockfile))
        # lockfile didn't exist so just carry on
      end

      # Own the pidfile ourselves
      begin
        File.open(@@lockfile, 'w') do |lockfile|
          lockfile.puts Process.pid
        end
      rescue => _ex
        fatal("Failed to open lockfile - are you running as root?")
      end
    end

    def lock_out_other_processes(name)
      @@lockfile = "/var/lock/byteback/#{name}.lock"
      claim_lockfile!
      at_exit { remove_lockfile! }
    end

    def log_system(*args)
      debug('system: ' + args.map { |a| / /.match(a) ? "\"#{a}\"" : a }.join(' '))
      rd, wr = IO.pipe
      pid = fork
      if pid.nil? # child
        rd.close
        STDOUT.reopen(wr)
        STDERR.reopen(wr)
        # any cleanup actually necessary here?
        exec(*args)
      end
      wr.close
      rd.each_line { |line| debug(line.chomp) }
      pid2, status = Process.waitpid2(pid, 0)
      status.exitstatus
    end
  end
end