-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathread-file.rb
executable file
·144 lines (117 loc) · 3.42 KB
/
read-file.rb
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env ruby
require "optparse"
require 'fileutils'
require "date"
def parse_commandline_args(args)
args = args.dup
encoding = "shift_jis"
hour = nil
move = false
status_file = nil
dry_run = false
parser = OptionParser.new
parser.banner = <<~BANNER
Usage: read-file.rb path [options]
Example: ruby read-file.rb /path/to/file.log --hour 20 --status-file /path/to/status
Example: ruby read-file.rb /path/to/file.log --hour 20 --move
BANNER
parser.on("--encoding ENCODING", "Encoding of the file to collect, such as utf-8, shift_jis.", "Default: #{encoding}") do |v|
encoding = v
end
parser.on("--hour HOUR", "Execute collection only at this hour.", "Default: Disabled", Integer) do |v|
hour = v
end
parser.on("--move", "Move the file after collecting to prevent duplicate collecting by adding `.collected` extension.", "Default: Disabled") do
move = true
end
parser.on("--status-file PATH", "Prevent duplicate collecting in the day by keeping the last collecting time in the file.", "Default: Disabled") do |v|
status_file = v
end
parser.on("--dry-run", "For test. The file is not moved and the status file is not updated.") do
dry_run = true
end
begin
parser.parse!(args)
rescue OptionParser::ParseError => e
$stderr.puts e
$stderr.puts parser.help
return nil
end
begin
Encoding.find(encoding)
rescue ArgumentError => e
$stderr.puts e
$stderr.puts parser.help
return nil
end
if hour and (hour < 0 or hour > 23)
$stderr.puts "--hour #{hour} must be an integer from 0 to 23."
$stderr.puts parser.help
return nil
end
if args.size == 0
$stderr.puts "Need the filepath to collect."
$stderr.puts parser.help
return nil
end
if args.size > 1
$stderr.puts "Invalid arguments: #{args[1..]}"
$stderr.puts parser.help
return nil
end
path = args.first
return path, encoding, hour, move, status_file, dry_run
end
class Status
def initialize(status_file)
@status_file = status_file
dir = File.dirname(@status_file)
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
end
def status
return {} unless File.exist?(@status_file)
File.open(@status_file, "rb") do |f|
return Marshal.load(f)
end
end
def update_status(status)
File.open(@status_file, "wb") do |f|
Marshal.dump(status, f)
end
end
def last_collection_time
status["last_collection_time"]
end
def update_last_collection_time(last_collection_time)
current_status = status
current_status["last_collection_time"] = last_collection_time
update_status(current_status)
end
end
def same_date?(time, another)
time.to_date == another.to_date
end
def read(path, encoding, hour, move, status_file, dry_run)
current_time = Time.now
return nil if hour and hour != current_time.hour
if status_file
status = Status.new(status_file)
last_collection_time = status.last_collection_time
return nil if last_collection_time and same_date?(last_collection_time, current_time)
end
return nil unless File.exist?(path)
content = File.read(path, mode: "r", encoding: encoding)
unless dry_run
if move
FileUtils.mv(path, path + '.collected')
end
status.update_last_collection_time(current_time) if status_file
end
content
end
if __FILE__ == $PROGRAM_NAME
args = parse_commandline_args(ARGV)
exit 1 unless args
content = read(*args)
print content if content
end