systemd-journal 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -4
- data/Rakefile +1 -1
- data/examples/ssh_watcher.rb +4 -3
- data/lib/systemd/journal.rb +89 -36
- data/lib/systemd/journal/compat.rb +19 -8
- data/lib/systemd/journal/native.rb +8 -1
- data/lib/systemd/journal/version.rb +2 -1
- data/lib/systemd/journal_error.rb +1 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfbc842565f8f2b0c02a231336a2398a52d5fd3e
|
4
|
+
data.tar.gz: 55318a3e7b014bbff59acfb837363961ece1817b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a0251260147d45da969179dd6053eda8826cf08187e55efd2fa6d83c7994fe75ee82683c4ca9b80770cd3172d21299fe46f960a8bbe975f9e12f2e8fa8cfc62
|
7
|
+
data.tar.gz: 96b8d2c07dae3dca254e36d6b2fefb6c190edd61749ff9a6e941056837fbc8e5c1650727633a900afed77bfd19108ac5d7766d0e14436951721ee494665c23c5
|
data/README.md
CHANGED
@@ -8,11 +8,11 @@ Ruby bindings for reading from the systemd journal.
|
|
8
8
|
|
9
9
|
Add this line to your application's Gemfile:
|
10
10
|
|
11
|
-
gem 'systemd-journal',
|
11
|
+
gem 'systemd-journal', '~> 0.1.0'
|
12
12
|
|
13
13
|
And then execute:
|
14
14
|
|
15
|
-
|
15
|
+
bundle install
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
@@ -21,7 +21,6 @@ For example, printing all messages:
|
|
21
21
|
require 'systemd/journal'
|
22
22
|
|
23
23
|
j = Systemd::Journal.new
|
24
|
-
j.seek(:head)
|
25
24
|
|
26
25
|
while j.move_next
|
27
26
|
puts j.read_field('MESSAGE')
|
@@ -32,7 +31,6 @@ Or to print all data in each entry:
|
|
32
31
|
require 'systemd/journal'
|
33
32
|
|
34
33
|
j = Systemd::Journal.new
|
35
|
-
j.seek(:head)
|
36
34
|
|
37
35
|
while j.move_next
|
38
36
|
j.current_entry do |key, value|
|
data/Rakefile
CHANGED
data/examples/ssh_watcher.rb
CHANGED
@@ -9,12 +9,13 @@ class SSHWatcher
|
|
9
9
|
|
10
10
|
def run
|
11
11
|
@journal.add_match('_EXE', '/usr/bin/sshd')
|
12
|
-
# skip all existing entries
|
12
|
+
# skip all existing entries -- sd_journal_seek_tail() is currently broken.
|
13
13
|
while @journal.move_next ; end
|
14
14
|
|
15
15
|
while true
|
16
|
-
@journal.wait(1_000_000 * 5)
|
17
|
-
|
16
|
+
if @journal.wait(1_000_000 * 5) != :nop
|
17
|
+
process_event(@journal.current_entry) while @journal.move_next
|
18
|
+
end
|
18
19
|
end
|
19
20
|
|
20
21
|
end
|
data/lib/systemd/journal.rb
CHANGED
@@ -4,16 +4,28 @@ require 'systemd/journal/compat'
|
|
4
4
|
require 'systemd/journal_error'
|
5
5
|
|
6
6
|
module Systemd
|
7
|
+
# Class to allow interacting with the systemd journal.
|
8
|
+
# To read from the journal, instantiate a new {Systemd::Journal}; to write to
|
9
|
+
# the journal, use
|
10
|
+
# {Systemd::Journal::Compat::ClassMethods#message Journal.message} or
|
11
|
+
# {Systemd::Journal::Compat::ClassMethods#print Journal.print}.
|
7
12
|
class Journal
|
8
13
|
include Systemd::Journal::Compat
|
9
14
|
|
10
15
|
# Returns a new instance of a Journal, opened with the provided options.
|
11
16
|
# @param [Hash] opts optional initialization parameters.
|
12
|
-
# @option opts [Integer] :flags a set of bitwise OR-ed
|
13
|
-
# which control what journal files are opened.
|
17
|
+
# @option opts [Integer] :flags a set of bitwise OR-ed
|
18
|
+
# {Systemd::Journal::Flags} which control what journal files are opened.
|
19
|
+
# Defaults to `0`, meaning all journals avaiable to the current user.
|
14
20
|
# @option opts [String] :path if provided, open the journal files living
|
15
21
|
# in the provided directory only. Any provided flags will be ignored per
|
16
22
|
# since sd_journal_open_directory does not currently accept any flags.
|
23
|
+
# @example Read only system journal entries
|
24
|
+
# j = Systemd::Journal.new(flags: Systemd::Journal::Flags::SYSTEM_ONLY)
|
25
|
+
# @example Directly open a journal directory
|
26
|
+
# j = Systemd::Journal.new(
|
27
|
+
# path: '/var/log/journal/5f5777e46c5f4131bd9b71cbed6b9abf'
|
28
|
+
# )
|
17
29
|
def initialize(opts = {})
|
18
30
|
flags = opts[:flags] || 0
|
19
31
|
path = opts[:path]
|
@@ -32,8 +44,9 @@ module Systemd
|
|
32
44
|
end
|
33
45
|
|
34
46
|
# Move the read pointer to the next entry in the journal.
|
35
|
-
# @return [Boolean] True if moving to the next entry was successful.
|
36
|
-
#
|
47
|
+
# @return [Boolean] True if moving to the next entry was successful.
|
48
|
+
# @return [Boolean] False if unable to move to the next entry, indicating
|
49
|
+
# that the pointer has reached the end of the journal.
|
37
50
|
def move_next
|
38
51
|
case (rc = Native::sd_journal_next(@ptr))
|
39
52
|
when 0 then false # EOF
|
@@ -43,9 +56,9 @@ module Systemd
|
|
43
56
|
end
|
44
57
|
|
45
58
|
# Move the read pointer forward by `amount` entries.
|
46
|
-
# @return the actual number of entries which the pointer
|
47
|
-
# this number is less than the requested,
|
48
|
-
# journal.
|
59
|
+
# @return [Integer] the actual number of entries by which the read pointer
|
60
|
+
# moved. If this number is less than the requested amount, the read
|
61
|
+
# pointer has reached the end of the journal.
|
49
62
|
def move_next_skip(amount)
|
50
63
|
rc = Native::sd_journal_next_skip(@ptr, amount)
|
51
64
|
raise JournalError.new(rc) if rc < 0
|
@@ -54,7 +67,8 @@ module Systemd
|
|
54
67
|
|
55
68
|
# Move the read pointer to the previous entry in the journal.
|
56
69
|
# @return [Boolean] True if moving to the previous entry was successful.
|
57
|
-
#
|
70
|
+
# @return [Boolean] False if unable to move to the previous entry,
|
71
|
+
# indicating that the pointer has reached the beginning of the journal.
|
58
72
|
def move_previous
|
59
73
|
case (rc = Native::sd_journal_previous(@ptr))
|
60
74
|
when 0 then false # EOF
|
@@ -64,9 +78,9 @@ module Systemd
|
|
64
78
|
end
|
65
79
|
|
66
80
|
# Move the read pointer backwards by `amount` entries.
|
67
|
-
# @return the actual number of entries which the pointer
|
68
|
-
# this number is less than the requested,
|
69
|
-
# journal.
|
81
|
+
# @return [Integer] the actual number of entries by which the read pointer
|
82
|
+
# was moved. If this number is less than the requested amount, the read
|
83
|
+
# pointer has reached the beginning of the journal.
|
70
84
|
def move_previous_skip(amount)
|
71
85
|
rc = Native::sd_journal_previous_skip(@ptr, amount)
|
72
86
|
raise JournalError.new(rc) if rc < 0
|
@@ -74,15 +88,14 @@ module Systemd
|
|
74
88
|
end
|
75
89
|
|
76
90
|
# Seek to a position in the journal.
|
77
|
-
# Note: after seeking, you must call move_next or move_previous
|
78
|
-
# you can call read_field or current_entry
|
91
|
+
# Note: after seeking, you must call {#move_next} or {#move_previous}
|
92
|
+
# before you can call {#read_field} or {#current_entry}.
|
79
93
|
#
|
80
94
|
# @param [Symbol, Time] whence one of :head, :tail, or a Time instance.
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# @return [Boolean] True on success, otherwise an error is raised.
|
95
|
+
# `:head` (or `:start`) will seek to the beginning of the journal.
|
96
|
+
# `:tail` (or `:end`) will seek to the end of the journal. When a `Time`
|
97
|
+
# is provided, seek to the journal entry logged closest to that time.
|
98
|
+
# @return [True]
|
86
99
|
def seek(whence)
|
87
100
|
rc = case whence
|
88
101
|
when :head, :start
|
@@ -102,10 +115,14 @@ module Systemd
|
|
102
115
|
end
|
103
116
|
|
104
117
|
# Read the contents of the provided field from the current journal entry.
|
105
|
-
# move_next or move_previous must be called at least once after
|
118
|
+
# {#move_next} or {#move_previous} must be called at least once after
|
106
119
|
# initialization or seeking prior to attempting to read data.
|
107
|
-
# @param [String] field the name of the field to read
|
120
|
+
# @param [String] field the name of the field to read.
|
108
121
|
# @return [String] the value of the requested field.
|
122
|
+
# @example Read the `MESSAGE` field from the current entry
|
123
|
+
# j = Systemd::Journal.new
|
124
|
+
# j.move_next
|
125
|
+
# puts j.read_field('MESSAGE')
|
109
126
|
def read_field(field)
|
110
127
|
len_ptr = FFI::MemoryPointer.new(:size_t, 1)
|
111
128
|
out_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
@@ -120,12 +137,16 @@ module Systemd
|
|
120
137
|
|
121
138
|
# Read the contents of all fields from the current journal entry.
|
122
139
|
# If given a block, it will yield each field in the form of
|
123
|
-
# (fieldname, value)
|
140
|
+
# `(fieldname, value)`.
|
124
141
|
#
|
125
|
-
# move_next or move_previous must be called at least once after
|
126
|
-
# initialization or seeking prior to calling current_entry
|
142
|
+
# {#move_next} or {#move_previous} must be called at least once after
|
143
|
+
# initialization or seeking prior to calling {#current_entry}
|
127
144
|
#
|
128
145
|
# @return [Hash] the contents of the current journal entry.
|
146
|
+
# @example Print all items in the current entry
|
147
|
+
# j = Systemd::Journal.new
|
148
|
+
# j.move_next
|
149
|
+
# j.current_entry{ |field, value| puts "#{field}: #{value}" }
|
129
150
|
def current_entry
|
130
151
|
Native::sd_journal_restart_data(@ptr)
|
131
152
|
|
@@ -150,18 +171,29 @@ module Systemd
|
|
150
171
|
|
151
172
|
# Block until the journal is changed.
|
152
173
|
# @param timeout_usec [Integer] the maximum number of microseconds to wait
|
153
|
-
# or
|
174
|
+
# or `-1` to wait indefinitely.
|
175
|
+
# @example Wait for an event for a maximum of 3 seconds
|
176
|
+
# j = Systemd::Journal.new
|
177
|
+
# j.seek(:tail)
|
178
|
+
# if j.wait(3 * 1_000_000) != :nop
|
179
|
+
# # event occurred
|
180
|
+
# end
|
181
|
+
# @return [Symbol] :nop if the wait time was reached (no events occured).
|
182
|
+
# @return [Symbol] :append if new entries were appened to the journal.
|
183
|
+
# @return [Symbol] :invalidate if journal files were added/removed/rotated.
|
154
184
|
def wait(timeout_usec = -1)
|
155
185
|
rc = Native::sd_journal_wait(@ptr, timeout_usec)
|
156
|
-
raise JournalError.new(rc) if rc < 0
|
186
|
+
raise JournalError.new(rc) if rc.is_a?(Fixnum) && rc < 0
|
187
|
+
rc
|
157
188
|
end
|
158
189
|
|
159
190
|
# Add a filter to journal, such that only entries where the given filter
|
160
191
|
# matches are returned.
|
161
|
-
# move_next or move_previous must be invoked after adding a match
|
162
|
-
# attempting to read from the journal.
|
192
|
+
# {#move_next} or {#move_previous} must be invoked after adding a match
|
193
|
+
# before attempting to read from the journal.
|
163
194
|
# @param [String] field the column to filter on, e.g. _PID, _EXE.
|
164
195
|
# @param [String] value the match to search for, e.g. '/usr/bin/sshd'
|
196
|
+
# @return [nil]
|
165
197
|
def add_match(field, value)
|
166
198
|
match = "#{field.to_s.upcase}=#{value}"
|
167
199
|
rc = Native::sd_journal_add_match(@ptr, match, match.length)
|
@@ -170,8 +202,18 @@ module Systemd
|
|
170
202
|
|
171
203
|
# Add an OR condition to the filter. All previously added matches
|
172
204
|
# and any matches added afterwards will be OR-ed together.
|
173
|
-
# move_next or move_previous must be invoked after adding a match
|
174
|
-
# attempting to read from the journal.
|
205
|
+
# {#move_next} or {#move_previous} must be invoked after adding a match
|
206
|
+
# before attempting to read from the journal.
|
207
|
+
# @return [nil]
|
208
|
+
# @example Filter entries returned using an OR condition
|
209
|
+
# j = Systemd::Journal.new
|
210
|
+
# j.add_match('PRIORITY', 5)
|
211
|
+
# j.add_match('_EXE', '/usr/bin/sshd')
|
212
|
+
# j.add_disjunction
|
213
|
+
# while j.move_next
|
214
|
+
# # current_entry is either an sshd event or
|
215
|
+
# # has priority 5
|
216
|
+
# end
|
175
217
|
def add_disjunction
|
176
218
|
rc = Native::sd_journal_add_disjunction(@ptr)
|
177
219
|
raise JournalError.new(rc) if rc < 0
|
@@ -179,22 +221,33 @@ module Systemd
|
|
179
221
|
|
180
222
|
# Add an AND condition to the filter. All previously added matches
|
181
223
|
# and any matches added afterwards will be AND-ed together.
|
182
|
-
# move_next or move_previous must be invoked after adding a match
|
183
|
-
# attempting to read from the journal.
|
224
|
+
# {#move_next} or {#move_previous} must be invoked after adding a match
|
225
|
+
# before attempting to read from the journal.
|
226
|
+
# @return [nil]
|
227
|
+
# @example Filter entries returned using an AND condition
|
228
|
+
# j = Systemd::Journal.new
|
229
|
+
# j.add_match('PRIORITY', 5)
|
230
|
+
# j.add_match('_EXE', '/usr/bin/sshd')
|
231
|
+
# j.add_conjunction
|
232
|
+
# while j.move_next
|
233
|
+
# # current_entry is an sshd event with priority 5
|
234
|
+
# end
|
184
235
|
def add_conjunction
|
185
236
|
rc = Native::sd_journal_add_conjunction(@ptr)
|
186
237
|
raise JournalError.new(rc) if rc < 0
|
187
238
|
end
|
188
239
|
|
189
|
-
#
|
240
|
+
# Remove all matches and conjunctions/disjunctions.
|
241
|
+
# @return [nil]
|
190
242
|
def clear_matches
|
191
243
|
Native::sd_journal_flush_matches(@ptr)
|
192
244
|
end
|
193
245
|
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
246
|
+
# Get the number of bytes the Journal is currently using on disk.
|
247
|
+
# If {Systemd::Journal::Flags::LOCAL_ONLY} was passed when opening the
|
248
|
+
# journal, this value will only reflect the size of journal files of the
|
249
|
+
# local host, otherwise of all hosts.
|
250
|
+
# @return [Integer] size in bytes
|
198
251
|
def disk_usage
|
199
252
|
size_ptr = FFI::MemoryPointer.new(:uint64)
|
200
253
|
rc = Native::sd_journal_get_usage(@ptr, size_ptr)
|
@@ -7,19 +7,30 @@ module Systemd
|
|
7
7
|
# by Daniel Mack (https://github.com/zonque/systemd-journal.gem)
|
8
8
|
module Compat
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
# system is unusable
|
11
|
+
LOG_EMERG = 0
|
12
|
+
# action must be taken immediately
|
13
|
+
LOG_ALERT = 1
|
14
|
+
# critical conditions
|
15
|
+
LOG_CRIT = 2
|
16
|
+
# error conditions
|
17
|
+
LOG_ERR = 3
|
18
|
+
# warning conditions
|
19
|
+
LOG_WARNING = 4
|
20
|
+
# normal but significant condition
|
21
|
+
LOG_NOTICE = 5
|
22
|
+
# informational
|
23
|
+
LOG_INFO = 6
|
24
|
+
# debug-level messages
|
25
|
+
LOG_DEBUG = 7
|
18
26
|
|
27
|
+
# @private
|
19
28
|
def self.included(base)
|
20
29
|
base.extend(ClassMethods)
|
21
30
|
end
|
22
31
|
|
32
|
+
# methods in this module will be available as class methods on
|
33
|
+
# {Systemd::Journal}
|
23
34
|
module ClassMethods
|
24
35
|
|
25
36
|
# write a simple message to the systemd journal.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Systemd
|
2
2
|
class Journal
|
3
|
+
# Provides the FFI bindings to the native `libsystemd-journal` shared
|
4
|
+
# library.
|
3
5
|
module Native
|
4
6
|
require 'ffi'
|
5
7
|
extend FFI::Library
|
@@ -26,7 +28,12 @@ module Systemd
|
|
26
28
|
attach_function :sd_journal_enumerate_data, [:pointer, :pointer, :pointer], :int
|
27
29
|
|
28
30
|
# event notification
|
29
|
-
|
31
|
+
enum :wake_reason, [
|
32
|
+
:nop,
|
33
|
+
:append,
|
34
|
+
:invalidate
|
35
|
+
]
|
36
|
+
attach_function :sd_journal_wait, [:pointer, :uint64], :wake_reason
|
30
37
|
|
31
38
|
# filtering
|
32
39
|
attach_function :sd_journal_add_match, [:pointer, :string, :size_t], :int
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: systemd-journal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Ledbetter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
version: '0'
|
68
68
|
requirements: []
|
69
69
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.0.
|
70
|
+
rubygems_version: 2.0.3
|
71
71
|
signing_key:
|
72
72
|
specification_version: 4
|
73
73
|
summary: Ruby bindings to libsystemd-journal
|