logrotate 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ === 1.0.0 / 2008-06-19
2
+ Initial release of LogRotate. This package is unit tested fully.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Designing Patterns
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ Manifest.txt
2
+ LICENSE
3
+ History.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/logrotate.rb
7
+ test/test_logrotate.rb
@@ -0,0 +1,162 @@
1
+ = logrotate
2
+ * Project Page: http://rubyforge.org/projects/logrotate/
3
+ * Documentation: http://logrotate.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ This package is a library of methods that perform log rotation. The
8
+ log rotate methods allow the caller to specify options (via
9
+ parameters) such as how many rotated files to keep, what type of
10
+ extension to place on the rotated file (date or a simple count), and
11
+ whether to zip the rotated files. Live log files (currently being
12
+ written to by a live process) can be rotated as well. The post_rotate
13
+ option is useful in that context, as it can be used to send a HUP
14
+ signal to notify the live process to reopen its log file.
15
+
16
+ This package was inspired by the need to have a library version of the
17
+ unix logrotate tool. The unix logrotate tool requires the user to
18
+ specify options in a config file, and is usually invoked through cron.
19
+
20
+ == PROBLEMS:
21
+
22
+ None (known).
23
+
24
+ == SYNOPSIS:
25
+ Here are some sample invocations of the library.
26
+
27
+ Rotate a log file with simple extensions: .1, .2, etc, keep 10 rotated
28
+ files around (.1 .. .10), and gzip the rotated files (.1.gz, .2.gz, .. .10.gz):
29
+ ======+examples/rotate_count.rb+:
30
+ #!/usr/bin/env ruby
31
+
32
+ require 'rubygems'
33
+ require 'logrotate'
34
+
35
+ options = {
36
+ :count => 10,
37
+ :gzip => true
38
+ }
39
+
40
+ LogRotate.rotate_file("/tmp/erwin.dat", options)
41
+
42
+
43
+ Rotate a set of log files with date extensions, and move the rotated
44
+ files to a specified directory:
45
+ ======+examples/rotate_date.rb+:
46
+ #!/usr/bin/env ruby
47
+
48
+ require 'rubygems'
49
+ require 'logrotate'
50
+
51
+ output_directory = "/tmp/archives"
52
+ if (!File.directory?(output_directory)) then Dir.mkdir(output_directory) end
53
+
54
+ files = (1..64).map {|i| "/tmp/erwin_#{i}.dat" }
55
+ files.each do |file|
56
+ File.open(file, "w") do |fs|
57
+ fs.write(file)
58
+ end
59
+ end
60
+
61
+ options = {
62
+ :date_time_ext => true,
63
+ :directory => output_directory
64
+ }
65
+
66
+ LogRotate.rotate_files(files, options)
67
+
68
+
69
+ Rotate a log file with date/time extensions.
70
+ ======+examples/rotate_date_time.rb+:
71
+ #!/usr/bin/env/ruby
72
+
73
+ require 'rubygems'
74
+ require 'logrotate'
75
+
76
+ options = {
77
+ :date_time_ext => true,
78
+ :date_time_format => '%F_%T'
79
+ }
80
+
81
+ LogRotate.rotate_file("/tmp/erwin.dat", options)
82
+
83
+
84
+ Rotate a log file that is currently being written to by a live
85
+ process. After the file is rotated, notify the live process to reopen
86
+ its log file.
87
+ ======+examples/rotate_live.rb+:
88
+ #!/usr/bin/env ruby
89
+
90
+ require 'rubygems'
91
+ require 'logrotate'
92
+
93
+ block = Proc.new() do
94
+ File.open("/tmp/hupper.pid") do |pid_stream|
95
+ pid = pid_stream.read().to_i()
96
+ Process.kill("HUP", pid)
97
+ end
98
+ end
99
+
100
+ options = {
101
+ :gzip => true,
102
+ :count => 3,
103
+ :post_rotate => block
104
+ }
105
+
106
+ LogRotate.rotate_file("/tmp/hupper.dat", options)
107
+
108
+
109
+ == REQUIREMENTS:
110
+
111
+ Hoe is required but only for running the tests.
112
+
113
+ == INSTALL:
114
+
115
+ sudo gem install logrotate
116
+
117
+ == AUTHORS:
118
+ === Designing Patterns
119
+ * Homepage: http://www.designingpatterns.com
120
+ * Blogs: http://blogs.designingpatterns.com
121
+
122
+ == SUPPORT
123
+ Please post questions, concerns, or requests for enhancement to the forums on
124
+ the project page. Alternatively, direct contact information for
125
+ Designing Patterns can be found on the project page for this gem.
126
+
127
+ == ENHANCEMENTS
128
+ Please feel free to contact us with any ideas; we will try our best to
129
+ enhance the software and respond to user requests. Of course, we are more
130
+ likely to work on a particular enhancement if we know that there are users
131
+ who want it. Designing Patterns provides contracting and consulting services,
132
+ so if there is an enhancement that *must* get done (and in a specified time
133
+ frame), please inquire about retaining our services!
134
+
135
+ == LICENSE:
136
+ The license text can be found in the +LICENSE+ file at the root of the
137
+ distribution.
138
+
139
+ This package is licensed with an MIT license:
140
+
141
+ Copyright (c) 2008 Designing Patterns
142
+
143
+ Permission is hereby granted, free of charge, to any person obtaining
144
+ a copy of this software and associated documentation files (the
145
+ 'Software'), to deal in the Software without restriction, including
146
+ without limitation the rights to use, copy, modify, merge, publish,
147
+ distribute, sublicense, and/or sell copies of the Software, and to
148
+ permit persons to whom the Software is furnished to do so, subject to
149
+ the following conditions:
150
+
151
+ The above copyright notice and this permission notice shall be
152
+ included in all copies or substantial portions of the Software.
153
+
154
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
155
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
156
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
157
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
158
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
159
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
160
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
161
+
162
+ == SHARE AND ENJOY!
@@ -0,0 +1,10 @@
1
+ # -*- ruby -*-
2
+ require 'rubygems'
3
+ require 'hoe'
4
+
5
+ Hoe.new('logrotate', "1.0.0") do |p|
6
+ p.remote_rdoc_dir = ''
7
+ p.developer('DesigningPatterns', 'technical.inquiries@designingpatterns.com')
8
+ end
9
+
10
+ # vim: syntax=Ruby
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'English'
4
+ require 'zlib'
5
+ require 'date'
6
+
7
+ #
8
+ # This module provides a few methods for log rotation.
9
+ #
10
+
11
+ module LogRotate
12
+
13
+ DEFAULT_COUNT = 5
14
+ DEFAULT_GZIP = false
15
+ DEFAULT_DATE_TIME_EXTENSION = false
16
+
17
+ DEFAULT_DATE_TIME_FORMAT = '%F'
18
+
19
+ #
20
+ # ====Description: This method rotates the given files.
21
+ #
22
+ # ====Parameters:
23
+ # [file(s)]
24
+ # The files to be rotated.
25
+ # [options = {}]
26
+ # A list of optional arguments.
27
+ #
28
+ # See rotate_file for details.
29
+ #
30
+ def self.rotate_files(files, options)
31
+ files.each do |file|
32
+ rotate_single_file(file, options)
33
+ end
34
+ end
35
+
36
+ #
37
+ # ====Description: This method rotates the given file(s).
38
+ # There are 2 types of extensions that can be used: the default
39
+ # extension which is an integer value (".1", ".2", ..), and a
40
+ # date/time extension (".2008-08-01", ..). If a date/time extension
41
+ # is chosen, the caller can specify a date/time format for this
42
+ # extension.
43
+ #
44
+ # ====Parameters:
45
+ # [file]
46
+ # The file to be rotated.
47
+ # [options = {}]
48
+ # A list of optional arguments.
49
+ #
50
+ # The optional arguments are listed below:
51
+ # +count+:: The number of rotated files to be kept.
52
+ # +directory+:: The directory to store the newly rotated file. If this
53
+ # option is unspecified, the original file's directory
54
+ # will be used.
55
+ # +date_time_ext+:: Whether the extension on the rotated files should be
56
+ # a date. Possible values are: +true+, +false+.
57
+ # +date_time_format+:: For use with +date_time_ext+. This specifies the
58
+ # format of the date / time extension.
59
+ # +date_time+:: For use with +date_time_ext+. The +DateTime+ that will be
60
+ # used to construct the extension of the newly rotated file.
61
+ # If this option is not specified, the current date and time
62
+ # will be used.
63
+ # +pre_rotate+:: A +Proc+ to be executed before the rotation is started.
64
+ # +post_rotate+:: A +Proc+ to be executed after the rotation is finished,
65
+ # and before the newly rotated file is zipped.
66
+ # +gzip+:: Whether the newly rotated file should be gzipped. Possible
67
+ # values are: +true+, +false+.
68
+ #
69
+ def self.rotate_file(file, options)
70
+ rotate_single_file(file, options)
71
+ end
72
+
73
+ def self.rotate_single_file(file, options = {})
74
+ gzip = options[:gzip] ? options[:gzip] : DEFAULT_GZIP
75
+
76
+ # error checking
77
+ if (!File.exist?(file)) then raise "File does not exist: #{file}." end
78
+ if (!File.readable?(file)) then raise "File is not readable: #{file}." end
79
+
80
+ if (options[:pre_rotate]) then options[:pre_rotate].call() end
81
+
82
+ new_backup = ""
83
+ if (options[:date_time_ext])
84
+ new_backup = rotate_file_date_extension(file, options)
85
+ else
86
+ new_backup = rotate_file_integer_extension(file, options)
87
+ end
88
+
89
+ if (options[:post_rotate]) then options[:post_rotate].call() end
90
+
91
+ if (gzip) then gzip_file(new_backup) end
92
+ end
93
+ private_class_method(:rotate_single_file)
94
+
95
+ def self.rotate_file_date_extension(file, options)
96
+ count = options[:count] ? options[:count] : DEFAULT_COUNT
97
+
98
+ now = options[:date_time] ? options[:date_time] : DateTime.now()
99
+
100
+ date_time_format = options[:date_time_format] ? options[:date_time_format] : DEFAULT_DATE_TIME_FORMAT
101
+
102
+ # Get a list of the rotated files.
103
+ (source_directory, base_name) = File.split(file)
104
+ directory = options[:directory] ? options[:directory] : source_directory
105
+
106
+ rotated_files = Dir.entries(directory).map do |entry|
107
+ rslt = nil
108
+
109
+ # Validate the rotated file. Since the caller is allowed to
110
+ # specify the date/time format, here we do not have a regular
111
+ # expression to match the date/time portion of the rotated
112
+ # file's extension. As a result, some foreign files can sneak
113
+ # into our list of rotated files (eg. base_file.GARBAGE.gz). Thus,
114
+ # the rotated file is validated below, and if invalid, it is
115
+ # skipped / left alone / not considered in the rotation.
116
+
117
+ if (entry.match("^#{base_name}\..+(\.gz)?$"))
118
+
119
+ # Validation #1: convert the date/time portion of the
120
+ # extension to a DateTime object and skip the file if an
121
+ # exception is thrown.
122
+ begin
123
+ match_data = entry.match("\.([^.]+)(\.gz)?$")
124
+ date_time = DateTime.strptime(match_data[1], date_time_format)
125
+ gz = match_data[2] ? match_data[2] : ""
126
+
127
+ # Validation #2: convert the date/time portion of the
128
+ # extension to a DateTime object and back to a string again.
129
+ # Then reconstruct the rotated file name with this string,
130
+ # and ensure the reconstructed rotated file matches the
131
+ # original. This will take into account cases where
132
+ # strptime succeeded but had additional garbage characters
133
+ # present.
134
+ # eg: date_time_format = '%F', file = 'mysql_backup.2008-08-04.BACK.gz'
135
+ reconstructed_file = "#{base_name}.#{date_time.strftime(date_time_format)}#{gz}"
136
+ if (entry == reconstructed_file)
137
+ rslt = { :date_time => date_time, :file => entry }
138
+ end
139
+ rescue => e
140
+ end
141
+
142
+ rslt
143
+ end
144
+ end
145
+
146
+ rotated_files = rotated_files.select { |rotated_file| rotated_file }
147
+
148
+ # Sort files by date (newer to older).
149
+ rotated_files.sort! { |left, right| right[:date_time] <=> left[:date_time] }
150
+
151
+ # Remove the oldest files so that there are count rotated files remaining.
152
+
153
+ # Determine how many old files to be removed.
154
+ new_backup_base_name = base_name + "." + now.strftime(date_time_format)
155
+
156
+ # Add 1 to account for the additional rotated file that will be
157
+ # created after the original file passed in is rotated.
158
+ num_old_files = rotated_files.length() - count + 1
159
+
160
+ # There is a chance that the newly rotated file will have the same
161
+ # name as one of the already existing rotated files (eg. if the
162
+ # extension is simply the date, and the job is ran a second time
163
+ # in the same day). In this case, there will be 1 less rotated
164
+ # file (and thus 1 less to delete).
165
+ if (rotated_files.find {|rotated_file| rotated_file[:file] == new_backup_base_name})
166
+ num_old_files -= 1
167
+ end
168
+
169
+ if (num_old_files > 0)
170
+ old_files = rotated_files.slice!(-num_old_files, num_old_files)
171
+ File.unlink(*old_files.map {|old_file| File.join(directory, old_file[:file]) })
172
+ end
173
+
174
+ # Rename the original file.
175
+ new_backup = File.join(directory, new_backup_base_name)
176
+ File.rename(file, new_backup)
177
+
178
+ return new_backup
179
+ end
180
+ private_class_method(:rotate_file_date_extension)
181
+
182
+ def self.rotate_file_integer_extension(file, options)
183
+ count = options[:count] ? options[:count] : DEFAULT_COUNT
184
+
185
+ # Get a list of the backed up files.
186
+ (source_directory, base_name) = File.split(file)
187
+ directory = options[:directory] ? options[:directory] : source_directory
188
+
189
+ rotated_files = Dir.entries(directory).select do |entry|
190
+ entry.match("#{base_name}\.[0-9]+(\.gz)?$")
191
+ end
192
+
193
+ rotated_files.map! do |rotated_file|
194
+ index = rotated_file.match("\.([0-9]+)(\.gz)?$")[1].to_i()
195
+ { :index => index, :file => rotated_file }
196
+ end
197
+
198
+ # Delete old files.
199
+ old_files = rotated_files.select { |rotated_file| rotated_file[:index] >= count }
200
+ File.unlink(*old_files.map {|old_file| File.join(directory, old_file[:file]) })
201
+
202
+ rotated_files = rotated_files - old_files
203
+
204
+ # Sort files such that the back up count is descending (eg. [hello.txt.5, hello.txt.4, ..]).
205
+ rotated_files.sort! { |left, right| right[:index] <=> left[:index] }
206
+
207
+ # Rotate - Increment the back up index on each file.
208
+ rotated_files.each do |rotated_file|
209
+
210
+ new_index = rotated_file[:index] + 1
211
+ new_file = rotated_file[:file].sub(/(^.*\.)(#{rotated_file[:index]})(.gz)?$/,
212
+ "\\1#{new_index}\\3")
213
+ File.rename(File.join(directory, rotated_file[:file]),
214
+ File.join(directory, new_file))
215
+ end
216
+
217
+ # Rename the original file.
218
+ new_backup = File.join(directory, base_name + ".1")
219
+ File.rename(file, new_backup)
220
+
221
+ return new_backup
222
+ end
223
+ private_class_method(:rotate_file_integer_extension)
224
+
225
+ def self.gzip_file(file)
226
+ # Zip the original file if necessary.
227
+ gzip_file = file + ".gz"
228
+
229
+ begin
230
+ File.open(file) do |file_stream|
231
+ Zlib::GzipWriter.open(gzip_file) do |gz|
232
+ while (buffer = file_stream.read(1024))
233
+ gz.write(buffer)
234
+ end
235
+ end
236
+ end
237
+ rescue => error
238
+ raise "Unable to zip file: #{file}. Error: #{error}\n"
239
+ end
240
+
241
+ File.unlink(file)
242
+ end
243
+ private_class_method(:gzip_file)
244
+
245
+ end
246
+
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'logrotate'
4
+
5
+ require 'test/unit'
6
+
7
+ class LogRotateTest < Test::Unit::TestCase
8
+ TEMP_DIR = "./temp"
9
+
10
+ def remove_directory(directory)
11
+ if (!File.directory?(directory)) then return end
12
+
13
+ entries = Dir.entries(directory).select {|entry| (entry != ".") && (entry != "..") }
14
+ entries.map! { |entry| File.join(directory, entry) }
15
+
16
+ entries.each do |entry|
17
+ if File.directory?(entry)
18
+ remove_directory(entry)
19
+ else
20
+ File.delete(entry)
21
+ end
22
+ end
23
+
24
+ Dir.delete(directory)
25
+ end
26
+
27
+ def remove_temp_directory
28
+ remove_directory(TEMP_DIR)
29
+ end
30
+
31
+ def setup
32
+ remove_temp_directory()
33
+ end
34
+
35
+ def teardown
36
+ remove_temp_directory()
37
+ end
38
+
39
+ def test_rotate_integer_extension()
40
+ rotate_integer_extension(3, 10, gzip = false)
41
+ rotate_integer_extension(3, 10, gzip = true)
42
+
43
+ output_dir = "#{TEMP_DIR}/archives"
44
+ rotate_integer_extension(3, 10, gzip = false, output_dir)
45
+ rotate_integer_extension(3, 10, gzip = true, output_dir)
46
+ end
47
+
48
+ def test_rotate_date_extension()
49
+ date_time_format = "%F_%T"
50
+
51
+ output_dir = nil
52
+ rotate_date_extension(3, 10, gzip = false)
53
+ rotate_date_extension(3, 10, gzip = true)
54
+ rotate_date_extension(3, 10, gzip = true, output_dir, date_time_format)
55
+
56
+ output_dir = "#{TEMP_DIR}/archives"
57
+ rotate_date_extension(3, 10, gzip = false, output_dir)
58
+ rotate_date_extension(3, 10, gzip = true, output_dir)
59
+ rotate_date_extension(3, 10, gzip = true, output_dir, date_time_format)
60
+ end
61
+
62
+ def rotate_integer_extension(count, rotations, gzip, output_dir = nil)
63
+ source_dir = "#{TEMP_DIR}"
64
+ base_name = "file.dat"
65
+ file = File.join(source_dir, base_name)
66
+ Dir.mkdir(source_dir)
67
+
68
+ is_output_dir = false
69
+ if (output_dir) then
70
+ Dir.mkdir(output_dir)
71
+ is_output_dir = true
72
+ else
73
+ output_dir = source_dir
74
+ end
75
+
76
+ manipulate_garbage_files(output_dir, base_name, :insert)
77
+
78
+ #rotate the file
79
+ rotations.downto(1) do |i|
80
+ File.open(file, "w") do |file_stream|
81
+ file_stream.write("#{i}")
82
+ end
83
+
84
+ options = {:count => count}
85
+ if (gzip) then options[:gzip] = true end
86
+ if (is_output_dir) then options[:directory] = output_dir end
87
+
88
+ LogRotate.rotate_files(file, options)
89
+ end
90
+
91
+ manipulate_garbage_files(output_dir, base_name, :delete)
92
+
93
+ #verify there are count rotated files.
94
+ entries = Dir.glob("#{output_dir}/*").map {|entry| File.split(entry)[1]}
95
+ assert_equal(entries.length, count)
96
+
97
+ #verify the contents
98
+ expected = (1..count).map { |i| "#{base_name}.#{i}" + (gzip ? ".gz" : "") }
99
+ assert_equal(entries.sort, expected)
100
+
101
+ (1..count).each do |i|
102
+ rotated_file = "#{output_dir}/#{base_name}.#{i}" + (gzip ? ".gz" : "")
103
+ if (gzip)
104
+ Zlib::GzipReader.open("#{rotated_file}") do |gz|
105
+ assert_equal(gz.read().to_i(), i)
106
+ end
107
+ else
108
+ assert_equal(IO.read(rotated_file).to_i(), i)
109
+ end
110
+ end
111
+
112
+ remove_temp_directory()
113
+ end
114
+
115
+ def manipulate_garbage_files(dir, base_name, operation)
116
+ bogus_extensions = [ ".back", ".back123", ".2008-10-04_00:00:00foo", ".123x", "." ]
117
+
118
+ bogus_extensions.each do |bogus_extension|
119
+ bogus_file_1 = File.join(dir, base_name + bogus_extension)
120
+ bogus_file_2 = bogus_file_1 + ".gz"
121
+
122
+ if (operation == :insert)
123
+ File.open(bogus_file_1, "w") { |file_stream| file_stream.print "garbage" }
124
+ File.open(bogus_file_2, "w") { |file_stream| file_stream.print "garbage" }
125
+ elsif (operation == :delete)
126
+ File.delete(bogus_file_1, bogus_file_2)
127
+ end
128
+ end
129
+ end
130
+
131
+ def rotate_date_extension(count, rotations, gzip,
132
+ output_dir = nil,
133
+ date_time_format = LogRotate::DEFAULT_DATE_TIME_FORMAT)
134
+
135
+ source_dir = "#{TEMP_DIR}"
136
+ base_name = "file.dat"
137
+ file = File.join(source_dir, base_name)
138
+ Dir.mkdir(source_dir)
139
+
140
+ is_output_dir = false
141
+ if (output_dir) then
142
+ Dir.mkdir(output_dir)
143
+ is_output_dir = true
144
+ else
145
+ output_dir = source_dir
146
+ end
147
+
148
+ manipulate_garbage_files(output_dir, base_name, :insert)
149
+
150
+ #rotate the file
151
+ now = DateTime.now
152
+ date_times = (0..(rotations - 1)).map { |i| now + i }
153
+
154
+ date_times.each do |date_time|
155
+ File.open(file, "w") do |file_stream|
156
+ file_stream.write(date_time.strftime(date_time_format))
157
+ end
158
+
159
+ options = { :date_time_ext => true, :date_time => date_time, :count => count }
160
+ if gzip then options[:gzip] = true end
161
+ if (is_output_dir) then options[:directory] = output_dir end
162
+ if date_time_format then options[:date_time_format] = date_time_format end
163
+
164
+ LogRotate.rotate_files(file, options)
165
+ end
166
+
167
+ #verify there are count rotated files.
168
+ manipulate_garbage_files(output_dir, base_name, :delete)
169
+
170
+ entries = Dir.glob("#{output_dir}/*").map {|entry| File.split(entry)[1]}
171
+ assert_equal(count, entries.length)
172
+
173
+ #verify the contents
174
+ date_times.slice!(0, date_times.length - count)
175
+ expected = date_times.map do |date_time|
176
+ "#{base_name}.#{date_time.strftime(date_time_format)}" + (gzip ? ".gz" : "")
177
+ end
178
+
179
+ assert_equal(expected, entries.sort)
180
+
181
+ date_times.each do |date_time|
182
+ rotated_file = "#{output_dir}/#{base_name}.#{date_time.strftime(date_time_format)}" + (gzip ? ".gz" : "")
183
+
184
+ if (gzip)
185
+ Zlib::GzipReader.open(rotated_file) do |gz|
186
+ assert_equal(gz.read(), "#{date_time.strftime(date_time_format)}")
187
+ end
188
+ else
189
+ assert_equal(IO.read("#{rotated_file}"), "#{date_time.strftime(date_time_format)}")
190
+ end
191
+ end
192
+
193
+ remove_temp_directory()
194
+ end
195
+
196
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logrotate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - DesigningPatterns
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-17 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.7.0
24
+ version:
25
+ description: This package is a library of methods that perform log rotation. The log rotate methods allow the caller to specify options (via parameters) such as how many rotated files to keep, what type of extension to place on the rotated file (date or a simple count), and whether to zip the rotated files. Live log files (currently being written to by a live process) can be rotated as well. The post_rotate option is useful in that context, as it can be used to send a HUP signal to notify the live process to reopen its log file. This package was inspired by the need to have a library version of the unix logrotate tool. The unix logrotate tool requires the user to specify options in a config file, and is usually invoked through cron.
26
+ email:
27
+ - technical.inquiries@designingpatterns.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - Manifest.txt
34
+ - History.txt
35
+ - README.txt
36
+ files:
37
+ - Manifest.txt
38
+ - LICENSE
39
+ - History.txt
40
+ - README.txt
41
+ - Rakefile
42
+ - lib/logrotate.rb
43
+ - test/test_logrotate.rb
44
+ has_rdoc: true
45
+ homepage: "Project Page: http://rubyforge.org/projects/logrotate/"
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --main
49
+ - README.txt
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project: logrotate
67
+ rubygems_version: 1.2.0
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: This package is a library of methods that perform log rotation
71
+ test_files:
72
+ - test/test_logrotate.rb