Module: Unicorn::Util

Defined in:
lib/unicorn/util.rb

Class Method Summary collapse

Class Method Details

.chown_logs(uid, gid) ⇒ Object



17
18
19
20
21
# File 'lib/unicorn/util.rb', line 17

def self.chown_logs(uid, gid)
  ObjectSpace.each_object(File) do |fp|
    fp.chown(uid, gid) if is_log?(fp)
  end
end

.is_log?(fp) ⇒ Boolean

:stopdoc:

Returns:

  • (Boolean)


6
7
8
9
10
11
12
13
14
15
# File 'lib/unicorn/util.rb', line 6

def self.is_log?(fp)
  append_flags = File::WRONLY | File::APPEND

  ! fp.closed? &&
    fp.sync &&
    fp.path[0] == ?/ &&
    (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
  rescue IOError, Errno::EBADF
    false
end

.reopen_logsObject

This reopens ALL logfiles in the process that have been rotated using logrotate(8) (without copytruncate) or similar tools. A File object is considered for reopening if it is:

1) opened with the O_APPEND and O_WRONLY flags
2) opened with an absolute path (starts with "/")
3) the current open file handle does not match its original open path
4) unbuffered (as far as userspace buffering goes, not O_SYNC)

Returns the number of files reopened



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
# File 'lib/unicorn/util.rb', line 32

def self.reopen_logs
  to_reopen = []
  nr = 0
  ObjectSpace.each_object(File) { |fp| is_log?(fp) and to_reopen << fp }

  to_reopen.each do |fp|
    orig_st = begin
      fp.stat
    rescue IOError, Errno::EBADF
      next
    end

    begin
      b = File.stat(fp.path)
      next if orig_st.ino == b.ino && orig_st.dev == b.dev
    rescue Errno::ENOENT
    end

    begin
      File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) }
      fp.sync = true
      new_st = fp.stat

      # this should only happen in the master:
      if orig_st.uid != new_st.uid || orig_st.gid != new_st.gid
        fp.chown(orig_st.uid, orig_st.gid)
      end

      nr += 1
    rescue IOError, Errno::EBADF
      # not much we can do...
    end
  end
  nr
end