file-tail 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.all_images.yml +7 -15
- data/.github/workflows/static.yml +51 -0
- data/.gitignore +2 -0
- data/CHANGES.md +42 -12
- data/README.md +266 -27
- data/Rakefile +9 -1
- data/VERSION +1 -1
- data/bin/rtail +1 -1
- data/file-tail.gemspec +6 -6
- data/lib/file/tail/logfile.rb +1 -2
- data/lib/file/tail/version.rb +1 -1
- data/lib/file/tail.rb +12 -10
- data/tests/file_tail_test.rb +2 -2
- data/tmp/.gitkeep +0 -0
- metadata +10 -11
- /data/{COPYING → LICENSE} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fcbea1582da9d2d6ce23fc0826608abf44625e90577916288001461593c2e0a
|
|
4
|
+
data.tar.gz: '0780cfca7c7d53f9a005ac2e1035daa249a758eab32a3b29aefb4142bd624127'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: adeee1b62fe358f4e8f3ae1f13127b6b94e741e9520f94611bff8e4f1083f5ccbb5a0fbb3e8d9a6e68281e12231304b8cb24de644b7c062c3db76e9062ca4589
|
|
7
|
+
data.tar.gz: a9057bdfb9b771c1ee58cda13ea0f7639b2ff1b599b5628f5815060f52063d1ee354cd2dfd2368b96add7da4a0cdad3447c6622ed45bcc95a7f8926c8168fd46
|
data/.all_images.yml
CHANGED
|
@@ -1,27 +1,19 @@
|
|
|
1
1
|
dockerfile: |-
|
|
2
|
-
RUN apk add --no-cache build-base git
|
|
3
|
-
|
|
4
|
-
if [[ "$(ruby -e 'print RUBY_VERSION')" > '3' ]]
|
|
5
|
-
then
|
|
6
|
-
gem update --system
|
|
7
|
-
gem install gem_hadar bundler
|
|
8
|
-
else
|
|
9
|
-
gem install gem_hadar
|
|
10
|
-
gem install bundler -v 2.4.22
|
|
11
|
-
fi
|
|
12
|
-
NUR
|
|
2
|
+
RUN apk add --no-cache build-base yaml-dev git openssl-dev
|
|
3
|
+
|
|
13
4
|
fail_fast: true
|
|
5
|
+
|
|
14
6
|
script: &script |-
|
|
15
7
|
echo -e "\e[1m"
|
|
16
8
|
ruby -v
|
|
17
9
|
echo -e "\e[0m"
|
|
18
|
-
bundle
|
|
10
|
+
bundle update --all
|
|
11
|
+
bundle install --jobs=$(getconf _NPROCESSORS_ONLN)
|
|
19
12
|
rake test
|
|
20
13
|
|
|
21
14
|
images:
|
|
15
|
+
ruby:4.0-alpine: *script
|
|
16
|
+
ruby:3.4-alpine: *script
|
|
22
17
|
ruby:3.3-alpine: *script
|
|
23
18
|
ruby:3.2-alpine: *script
|
|
24
19
|
ruby:3.1-alpine: *script
|
|
25
|
-
ruby:3.0-alpine: *script
|
|
26
|
-
ruby:2.7-alpine: *script
|
|
27
|
-
ruby:2.6-alpine: *script
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
+
name: Deploy static content to Pages
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
# Runs on pushes targeting the default branch
|
|
6
|
+
push:
|
|
7
|
+
branches: [ "master" ]
|
|
8
|
+
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pages: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
19
|
+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
20
|
+
concurrency:
|
|
21
|
+
group: "pages"
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
# Single deploy job since we're just deploying
|
|
26
|
+
deploy:
|
|
27
|
+
environment:
|
|
28
|
+
name: github-pages
|
|
29
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout
|
|
33
|
+
uses: actions/checkout@v4
|
|
34
|
+
- name: Setup Pages
|
|
35
|
+
uses: actions/configure-pages@v5
|
|
36
|
+
- name: Setup Ruby
|
|
37
|
+
uses: ruby/setup-ruby@v1
|
|
38
|
+
with:
|
|
39
|
+
ruby-version: '3.4'
|
|
40
|
+
- name: Generate Documentation
|
|
41
|
+
run: |
|
|
42
|
+
gem install gem_hadar
|
|
43
|
+
bundle install
|
|
44
|
+
rake doc
|
|
45
|
+
- name: Upload artifact
|
|
46
|
+
uses: actions/upload-pages-artifact@v3
|
|
47
|
+
with:
|
|
48
|
+
path: 'doc'
|
|
49
|
+
- name: Deploy to GitHub Pages
|
|
50
|
+
id: deployment
|
|
51
|
+
uses: actions/deploy-pages@v4
|
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
|
@@ -1,33 +1,63 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-01-02 v1.4.0
|
|
4
|
+
|
|
5
|
+
- Enhanced file reopening logic to handle `Errno::ENOENT` and `Errno::ESTALE`
|
|
6
|
+
errors separately, preventing line skipping during file rotation
|
|
7
|
+
- Fixed buffer size parameter passing and cleaned up the close block
|
|
8
|
+
- Added nil safety check for `@out.path` before removing temporary files
|
|
9
|
+
- Updated gemspec to include the `LICENSE` file and added a GitHub Actions
|
|
10
|
+
workflow
|
|
11
|
+
- Replaced the old documentation in README with a comprehensive architecture
|
|
12
|
+
overview, usage examples, and debugging sections
|
|
13
|
+
- Added automated documentation deployment workflow using GitHub Actions with
|
|
14
|
+
Ruby **3.4** environment
|
|
15
|
+
- Removed unnecessary `t =` assignment for thread in `rtail` binary
|
|
16
|
+
- Removed support for Ruby **3.0** Alpine image in CI configuration
|
|
17
|
+
- Renamed `COPYING` file to `LICENSE` for better standard compliance
|
|
18
|
+
- Added `.yardoc` to gitignore and rake ignore list
|
|
19
|
+
- Updated test file path to use the `tmp` directory for better test
|
|
20
|
+
organization
|
|
21
|
+
- Added `tmp` directory to gitignore, gemspec, and git tracking with
|
|
22
|
+
`tmp/.gitkeep`
|
|
23
|
+
- Updated CI image configuration to support Ruby **4.0** with `yaml-dev` and
|
|
24
|
+
`openssl-dev` dependencies
|
|
25
|
+
- Updated gem metadata and dependencies, including `rubygems_version` to
|
|
26
|
+
**4.0.2** and `gem_hadar` development dependency to **>= 2.16.3**
|
|
27
|
+
- Added changelog generation support to the Rakefile for automated changelog
|
|
28
|
+
management
|
|
29
|
+
- Updated Dockerfile dependencies for Ruby version detection and added Ruby
|
|
30
|
+
**3.4**-alpine image support
|
|
31
|
+
- Fixed typos in the codebase
|
|
32
|
+
|
|
3
33
|
## 2024-09-13 v1.3.0
|
|
4
34
|
|
|
5
35
|
### Significant Changes
|
|
6
36
|
|
|
7
37
|
* **Improved waiting for log output by counting lines**
|
|
8
|
-
|
|
38
|
+
+ Increased timeout from 2 seconds to 10 seconds in multiple places
|
|
9
39
|
* **Added Ruby version check in Dockerfile**
|
|
10
|
-
|
|
11
|
-
|
|
40
|
+
+ Update `gem update --system` and installation to be conditional on Ruby version
|
|
41
|
+
+ Replace `bundle` with `bundle install` in script section
|
|
12
42
|
* **Convert CHANGES file to CHANGES\.md**
|
|
13
43
|
|
|
14
44
|
### Bug Fixes
|
|
15
45
|
|
|
16
46
|
* **Add exit handler to delete temporary file**
|
|
17
|
-
|
|
47
|
+
- Added at_exit block to delete test file created in setup method.
|
|
18
48
|
* **Refactor File class for debugging**
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
- Remove hardcoded `$DEBUG` variable usage in reopen_file and output_debug_information methods
|
|
50
|
+
- Introduce debug? method to check if `FILE_TAIL_DEBUG` environment variable is set to 1.
|
|
21
51
|
|
|
22
52
|
### Dependency Updates
|
|
23
53
|
|
|
24
54
|
* **Update Ruby dependencies and add new development dependencies**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
55
|
+
+ Added `.all_images.yml` file with Dockerfile configuration
|
|
56
|
+
+ Updated Gemfile to use Ruby **3.5.18** instead of **2.7.8**
|
|
57
|
+
+ Updated Rakefile to ignore additional files
|
|
58
|
+
+ Updated `file-tail.gemspec` to include `.all_images.yml` in the list of files
|
|
59
|
+
+ Updated `tests/file_tail_test.rb` to use absolute path for test file
|
|
60
|
+
+ Added new development dependencies: `all_images`, `simplecov`, and `debug`
|
|
31
61
|
+ Updated dependency versions: `gem_hadar` to **1.17.1**, `test-unit` to
|
|
32
62
|
**3.0**, and `tins` to **1.0**
|
|
33
63
|
|
data/README.md
CHANGED
|
@@ -5,69 +5,308 @@
|
|
|
5
5
|
This is a small ruby library that allows it to "tail" files in Ruby, including
|
|
6
6
|
following a file, that still is growing like the unix command 'tail -f' can.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Documentation
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Complete API documentation is available at: [GitHub.io](https://flori.github.io/file-tail/)
|
|
11
|
+
|
|
12
|
+
## Architecture Overview
|
|
13
|
+
|
|
14
|
+
File::Tail follows a well-defined architectural pattern with clear
|
|
15
|
+
separation of concerns between several key components:
|
|
11
16
|
|
|
17
|
+
### Core Components
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
**File::Tail Module**
|
|
20
|
+
- The central hub extending File objects with tailing capabilities 🔄
|
|
21
|
+
- Provides core methods for forward/backward traversal and tailing 📊
|
|
22
|
+
- Handles file system events like rotation, truncation, and deletion 🔁
|
|
23
|
+
|
|
24
|
+
**File::Tail::Logfile**
|
|
25
|
+
- A convenience class that simplifies opening and tailing files with options 🚀
|
|
26
|
+
- Includes File::Tail module for direct file access 🧠
|
|
27
|
+
- Supports various initialization patterns for flexible usage 🔄
|
|
28
|
+
|
|
29
|
+
**File::Tail::Group**
|
|
30
|
+
- Manages multiple files to be tailed together 🔄
|
|
31
|
+
- Uses ThreadGroup to coordinate multiple tailing threads ⏳
|
|
32
|
+
- Provides batch operations for concurrent file monitoring 📊
|
|
33
|
+
|
|
34
|
+
**File::Tail::Tailer**
|
|
35
|
+
- A Thread subclass that supervises a single file's tailing 🧠
|
|
36
|
+
- Uses queues for line buffering and thread-safe communication 📦
|
|
37
|
+
- Implements method_missing for thread-local variable access ⚡
|
|
38
|
+
|
|
39
|
+
### Component Interactions
|
|
40
|
+
|
|
41
|
+
```mermaid
|
|
42
|
+
graph LR
|
|
43
|
+
A[File::Tail] --> B[File::Tail::Logfile]
|
|
44
|
+
A --> C[File::Tail::Group]
|
|
45
|
+
C --> D[File::Tail::Tailer]
|
|
46
|
+
D --> E[Thread]
|
|
47
|
+
A --> F[File::Tail::LineExtension]
|
|
48
|
+
F --> G[Lines from tailers]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The File::Tail module acts as the foundation, providing core functionality that
|
|
52
|
+
is extended by Logfile and Group classes. The Group class coordinates multiple
|
|
53
|
+
Tailer threads, each managing a single file's tailing process.
|
|
54
|
+
|
|
55
|
+
### Loading Mechanism
|
|
56
|
+
|
|
57
|
+
File::Tail supports two primary access patterns:
|
|
58
|
+
|
|
59
|
+
1. **Direct File Extension** - Extending File objects directly with File::Tail:
|
|
60
|
+
```ruby
|
|
61
|
+
File.open(filename) do |log|
|
|
62
|
+
log.extend(File::Tail)
|
|
63
|
+
log.backward(10)
|
|
64
|
+
log.tail { |line| puts line }
|
|
65
|
+
end
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. **Logfile Convenience Class** - Using the Logfile wrapper for simpler usage:
|
|
69
|
+
```ruby
|
|
70
|
+
File::Tail::Logfile.tail('app.log', :backward => 10) do |line|
|
|
71
|
+
puts line
|
|
72
|
+
end
|
|
73
|
+
```
|
|
14
74
|
|
|
15
75
|
## Installation
|
|
16
76
|
|
|
17
77
|
To install file-tail via its gem type:
|
|
18
78
|
|
|
19
|
-
|
|
79
|
+
```bash
|
|
80
|
+
gem install file-tail
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
You can also put this line into your Gemfile:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
gem 'file-tail'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
and bundle. This will make the File::Tail module available for extending File objects.
|
|
20
90
|
|
|
21
91
|
## Usage
|
|
22
92
|
|
|
23
93
|
File::Tail is a module in the File class. A lightweight class interface for
|
|
24
94
|
logfiles can be seen under File::Tail::Logfile.
|
|
25
95
|
|
|
26
|
-
Direct
|
|
96
|
+
### Direct Extension of File Objects
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
File.open(filename) do |log|
|
|
100
|
+
log.extend(File::Tail)
|
|
101
|
+
log.interval # 10
|
|
102
|
+
log.backward(10)
|
|
103
|
+
log.tail { |line| puts line }
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
It's also possible to mix File::Tail in your own File classes (see also File::Tail::Logfile):
|
|
27
108
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
109
|
+
```ruby
|
|
110
|
+
class MyFile < File
|
|
111
|
+
include File::Tail
|
|
112
|
+
end
|
|
113
|
+
log = MyFile.new("myfile")
|
|
114
|
+
log.interval # 10
|
|
115
|
+
log.backward(10)
|
|
116
|
+
log.tail { |line| print line }
|
|
117
|
+
```
|
|
34
118
|
|
|
35
|
-
|
|
36
|
-
(see also File::Tail::Logfile):
|
|
119
|
+
The forward/backward method returns self, so it's possible to chain methods together like that:
|
|
37
120
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
log # MyFile.new("myfile")
|
|
42
|
-
log.interval # 10
|
|
43
|
-
log.backward(10)
|
|
44
|
-
log.tail { |line| print line }
|
|
121
|
+
```ruby
|
|
122
|
+
log.backward(10).tail { |line| puts line }
|
|
123
|
+
```
|
|
45
124
|
|
|
46
|
-
|
|
47
|
-
methods together like that:
|
|
125
|
+
### Multiple File Tailing with Group
|
|
48
126
|
|
|
49
|
-
|
|
127
|
+
```ruby
|
|
128
|
+
group = File::Tail::Group.new
|
|
129
|
+
group.add_filename('app.log')
|
|
130
|
+
group.add_filename('error.log')
|
|
131
|
+
group.tail { |line| puts line }
|
|
132
|
+
```
|
|
50
133
|
|
|
51
|
-
|
|
134
|
+
### Advanced Usage with Callbacks
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
log = File::Tail::Logfile.open('app.log')
|
|
138
|
+
log.after_reopen { |file| puts "File reopened: #{file.path}" }
|
|
139
|
+
log.tail { |line| puts line }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Backward Traversal
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
# Tail last 10 lines of file
|
|
146
|
+
File::Tail::Logfile.open('app.log', :backward => 10) do |log|
|
|
147
|
+
log.tail { |line| puts line }
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Skip first 5 lines and tail
|
|
151
|
+
File::Tail::Logfile.open('app.log', :forward => 5) do |log|
|
|
152
|
+
log.tail { |line| puts line }
|
|
153
|
+
end
|
|
154
|
+
```
|
|
52
155
|
|
|
53
156
|
## Documentation
|
|
54
157
|
|
|
55
158
|
To create the documentation of this module, type
|
|
56
159
|
|
|
57
|
-
```
|
|
160
|
+
```bash
|
|
58
161
|
$ rake doc
|
|
59
162
|
```
|
|
60
163
|
|
|
61
164
|
and the API documentation is generated.
|
|
62
165
|
|
|
63
|
-
In the examples
|
|
166
|
+
In the examples directory is a small example of tail and
|
|
64
167
|
pager program that use this module. You also may want look
|
|
65
168
|
at the end of examples/tail.rb for a little example.
|
|
66
169
|
|
|
170
|
+
## Debugging and Troubleshooting
|
|
171
|
+
|
|
172
|
+
File::Tail provides built-in debugging capabilities through environment variables:
|
|
173
|
+
|
|
174
|
+
### Enabling Debug Output
|
|
175
|
+
|
|
176
|
+
Set the `FILE_TAIL_DEBUG` environment variable to enable detailed debugging information:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
export FILE_TAIL_DEBUG=1
|
|
180
|
+
ruby your_tail_script.rb
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This will output information about:
|
|
184
|
+
- File paths being tailed
|
|
185
|
+
- Line counts and intervals
|
|
186
|
+
- Reopening events
|
|
187
|
+
- Sleep intervals and timing
|
|
188
|
+
|
|
189
|
+
### Exception Handling
|
|
190
|
+
|
|
191
|
+
File::Tail defines several specific exceptions for different failure scenarios:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
begin
|
|
195
|
+
log.tail { |line| puts line }
|
|
196
|
+
rescue File::Tail::DeletedException
|
|
197
|
+
# Handle file deletion
|
|
198
|
+
rescue File::Tail::ReopenException
|
|
199
|
+
# Handle file rotation/reopening
|
|
200
|
+
rescue File::Tail::BreakException
|
|
201
|
+
# Handle end-of-file with break_if_eof set
|
|
202
|
+
rescue File::Tail::ReturnException
|
|
203
|
+
# Internal exception for controlling tailing behavior
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Configuration
|
|
208
|
+
|
|
209
|
+
### Key Attributes
|
|
210
|
+
|
|
211
|
+
File::Tail provides several configurable attributes for fine-tuning behavior:
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
log = File::Tail::Logfile.open('app.log')
|
|
215
|
+
log.interval = 1.0 # Initial sleep interval (default: 10)
|
|
216
|
+
log.max_interval = 5.0 # Maximum sleep interval (default: 10)
|
|
217
|
+
log.reopen_deleted = true # Reopen deleted files (default: true)
|
|
218
|
+
log.reopen_suspicious = true # Reopen on suspicious events (default: true)
|
|
219
|
+
log.suspicious_interval = 60 # Interval before suspicious event detection (default: 60)
|
|
220
|
+
log.break_if_eof = false # Break on EOF (default: false)
|
|
221
|
+
log.return_if_eof = false # Return on EOF (default: false)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Advanced Configuration
|
|
225
|
+
|
|
226
|
+
```ruby
|
|
227
|
+
# Configure for high-traffic logs
|
|
228
|
+
log.interval = 0.1
|
|
229
|
+
log.max_interval = 1.0
|
|
230
|
+
log.suspicious_interval = 30
|
|
231
|
+
|
|
232
|
+
# Configure for low-traffic logs
|
|
233
|
+
log.interval = 5.0
|
|
234
|
+
log.max_interval = 30.0
|
|
235
|
+
log.suspicious_interval = 120
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Performance Considerations
|
|
239
|
+
|
|
240
|
+
### Thread Safety
|
|
241
|
+
|
|
242
|
+
File::Tail uses thread-safe mechanisms for concurrent file monitoring:
|
|
243
|
+
- ThreadGroup for managing tailer threads
|
|
244
|
+
- Mutex and ConditionVariable for synchronization
|
|
245
|
+
- Queue-based line buffering for thread communication
|
|
246
|
+
|
|
247
|
+
### Memory Management
|
|
248
|
+
|
|
249
|
+
The library implements efficient memory usage:
|
|
250
|
+
- Lines are buffered in queues per tailer
|
|
251
|
+
- Exponential backoff reduces CPU usage when files are quiet
|
|
252
|
+
- Proper thread lifecycle management prevents resource leaks
|
|
253
|
+
|
|
254
|
+
### File System Event Handling
|
|
255
|
+
|
|
256
|
+
File::Tail gracefully handles various file system events:
|
|
257
|
+
- File rotation (log rotation)
|
|
258
|
+
- File truncation
|
|
259
|
+
- File deletion
|
|
260
|
+
- File reopening after deletion
|
|
261
|
+
|
|
262
|
+
## Error Handling
|
|
263
|
+
|
|
264
|
+
File::Tail provides comprehensive error handling for common file system scenarios:
|
|
265
|
+
|
|
266
|
+
### File::Tail Exception Hierarchy
|
|
267
|
+
|
|
268
|
+
```mermaid
|
|
269
|
+
classDiagram
|
|
270
|
+
class TailException {
|
|
271
|
+
<<abstract>>
|
|
272
|
+
+message
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
class DeletedException
|
|
276
|
+
class ReturnException
|
|
277
|
+
class BreakException
|
|
278
|
+
class ReopenException
|
|
279
|
+
|
|
280
|
+
TailException <|-- DeletedException
|
|
281
|
+
TailException <|-- ReturnException
|
|
282
|
+
TailException <|-- BreakException
|
|
283
|
+
TailException <|-- ReopenException
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Safe Usage Pattern
|
|
287
|
+
|
|
288
|
+
```ruby
|
|
289
|
+
def safe_tail(filename)
|
|
290
|
+
File::Tail::Logfile.open(filename) do |log|
|
|
291
|
+
log.tail { |line| puts line }
|
|
292
|
+
rescue File::Tail::DeletedException
|
|
293
|
+
puts "File was deleted, stopping tailing"
|
|
294
|
+
rescue File::Tail::ReopenException
|
|
295
|
+
puts "File reopened, continuing tailing"
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Download
|
|
301
|
+
|
|
302
|
+
The latest version of *File::Tail* (file-tail) can be found at
|
|
303
|
+
|
|
304
|
+
https://github.com/flori/file-tail
|
|
305
|
+
|
|
67
306
|
## Author
|
|
68
307
|
|
|
69
308
|
Florian Frank mailto:flori@ping.de
|
|
70
309
|
|
|
71
310
|
## License
|
|
72
311
|
|
|
73
|
-
|
|
312
|
+
This software is licensed under the [Apache 2.0 license](LICENSE).
|
data/Rakefile
CHANGED
|
@@ -12,10 +12,18 @@ GemHadar do
|
|
|
12
12
|
description 'Library to tail files in Ruby'
|
|
13
13
|
test_dir 'tests'
|
|
14
14
|
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '*.rbc', '.rbx',
|
|
15
|
-
'.AppleDouble', '.bundle', 'errors.lst', '.utilsrc'
|
|
15
|
+
'.AppleDouble', '.bundle', 'errors.lst', '.utilsrc', 'tmp', '.yardoc'
|
|
16
16
|
readme 'README.md'
|
|
17
17
|
licenses << 'Apache-2.0'
|
|
18
18
|
|
|
19
|
+
changelog do
|
|
20
|
+
filename 'CHANGES.md'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
github_workflows(
|
|
24
|
+
'static.yml' => {}
|
|
25
|
+
)
|
|
26
|
+
|
|
19
27
|
dependency 'tins', '~>1.0'
|
|
20
28
|
|
|
21
29
|
development_dependency 'test-unit', '~>3.0'
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.4.0
|
data/bin/rtail
CHANGED
data/file-tail.gemspec
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: file-tail 1.
|
|
2
|
+
# stub: file-tail 1.4.0 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "file-tail".freeze
|
|
6
|
-
s.version = "1.
|
|
6
|
+
s.version = "1.4.0".freeze
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
|
10
10
|
s.authors = ["Florian Frank".freeze]
|
|
11
|
-
s.date = "
|
|
11
|
+
s.date = "1980-01-02"
|
|
12
12
|
s.description = "Library to tail files in Ruby".freeze
|
|
13
13
|
s.email = "flori@ping.de".freeze
|
|
14
14
|
s.extra_rdoc_files = ["README.md".freeze, "lib/file-tail.rb".freeze, "lib/file/tail.rb".freeze, "lib/file/tail/group.rb".freeze, "lib/file/tail/line_extension.rb".freeze, "lib/file/tail/logfile.rb".freeze, "lib/file/tail/tailer.rb".freeze, "lib/file/tail/version.rb".freeze]
|
|
15
|
-
s.files = [".all_images.yml".freeze, ".gitignore".freeze, ".travis.yml".freeze, "CHANGES.md".freeze, "
|
|
15
|
+
s.files = [".all_images.yml".freeze, ".github/workflows/static.yml".freeze, ".gitignore".freeze, ".travis.yml".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/rtail".freeze, "examples/pager.rb".freeze, "examples/tail.rb".freeze, "file-tail.gemspec".freeze, "lib/file-tail.rb".freeze, "lib/file/tail.rb".freeze, "lib/file/tail/group.rb".freeze, "lib/file/tail/line_extension.rb".freeze, "lib/file/tail/logfile.rb".freeze, "lib/file/tail/tailer.rb".freeze, "lib/file/tail/version.rb".freeze, "tests/file_tail_group_test.rb".freeze, "tests/file_tail_test.rb".freeze, "tests/test_helper.rb".freeze, "tmp/.gitkeep".freeze]
|
|
16
16
|
s.homepage = "http://github.com/flori/file-tail".freeze
|
|
17
17
|
s.licenses = ["Apache-2.0".freeze]
|
|
18
18
|
s.rdoc_options = ["--title".freeze, "File-tail - File::Tail for Ruby".freeze, "--main".freeze, "README.md".freeze]
|
|
19
|
-
s.rubygems_version = "
|
|
19
|
+
s.rubygems_version = "4.0.2".freeze
|
|
20
20
|
s.summary = "File::Tail for Ruby".freeze
|
|
21
21
|
s.test_files = ["tests/file_tail_group_test.rb".freeze, "tests/file_tail_test.rb".freeze, "tests/test_helper.rb".freeze]
|
|
22
22
|
|
|
23
23
|
s.specification_version = 4
|
|
24
24
|
|
|
25
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["
|
|
25
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, [">= 2.16.3".freeze])
|
|
26
26
|
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.0".freeze])
|
|
27
27
|
s.add_development_dependency(%q<all_images>.freeze, [">= 0".freeze])
|
|
28
28
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
data/lib/file/tail/logfile.rb
CHANGED
|
@@ -51,7 +51,7 @@ class File
|
|
|
51
51
|
end
|
|
52
52
|
if backward = opts[:backward] || opts[:rewind]
|
|
53
53
|
(args = []) << backward
|
|
54
|
-
args <<
|
|
54
|
+
args << opts[:bufsiz] if opts[:bufsiz]
|
|
55
55
|
file.backward(*args)
|
|
56
56
|
elsif forward = opts[:forward] || opts[:wind]
|
|
57
57
|
file.forward(forward)
|
|
@@ -64,7 +64,6 @@ class File
|
|
|
64
64
|
block.call file
|
|
65
65
|
ensure
|
|
66
66
|
file.close
|
|
67
|
-
nil
|
|
68
67
|
end
|
|
69
68
|
else
|
|
70
69
|
file
|
data/lib/file/tail/version.rb
CHANGED
data/lib/file/tail.rb
CHANGED
|
@@ -17,7 +17,7 @@ class File
|
|
|
17
17
|
class DeletedException < TailException; end
|
|
18
18
|
|
|
19
19
|
# The ReturnException is raised and caught
|
|
20
|
-
# internally to implement "tail -10"
|
|
20
|
+
# internally to implement "tail -10" behavior.
|
|
21
21
|
class ReturnException < TailException; end
|
|
22
22
|
|
|
23
23
|
# The BreakException is raised if the <code>break_if_eof</code>
|
|
@@ -26,7 +26,7 @@ class File
|
|
|
26
26
|
class BreakException < TailException; end
|
|
27
27
|
|
|
28
28
|
# The ReopenException is raised internally if File::Tail
|
|
29
|
-
# gets suspicious something unusual has
|
|
29
|
+
# gets suspicious something unusual has happened to
|
|
30
30
|
# the tailed file, e. g., it was rotated away. The exception
|
|
31
31
|
# is caught and an attempt to reopen it is made.
|
|
32
32
|
class ReopenException < TailException
|
|
@@ -66,14 +66,14 @@ class File
|
|
|
66
66
|
attr_accessor :reopen_suspicious
|
|
67
67
|
|
|
68
68
|
# The callback is called with _self_ as an argument after a reopen has
|
|
69
|
-
#
|
|
70
|
-
# rotated.
|
|
69
|
+
# occurred. This allows a tailing script to find out, if a logfile has
|
|
70
|
+
# been rotated.
|
|
71
71
|
def after_reopen(&block)
|
|
72
72
|
@after_reopen = block
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
# This attribute is the
|
|
76
|
-
# gets suspicious that something has
|
|
75
|
+
# This attribute is the interval in seconds before File::Tail
|
|
76
|
+
# gets suspicious that something has happened to it's tailed file
|
|
77
77
|
# and an attempt to reopen it is made.
|
|
78
78
|
#
|
|
79
79
|
# If the attribute <code>reopen_suspicious</code> is
|
|
@@ -241,16 +241,18 @@ class File
|
|
|
241
241
|
if @stat
|
|
242
242
|
if stat.ino != @stat.ino or stat.dev != @stat.dev
|
|
243
243
|
@stat = nil
|
|
244
|
-
raise ReopenException.new(:top)
|
|
244
|
+
raise ReopenException.new(:top) # File ino/dev has changed, start from top
|
|
245
245
|
end
|
|
246
246
|
if stat.size < @stat.size
|
|
247
247
|
@stat = nil
|
|
248
|
-
raise ReopenException.new(:top)
|
|
248
|
+
raise ReopenException.new(:top) # File shrunk, start from top
|
|
249
249
|
end
|
|
250
250
|
end
|
|
251
251
|
@stat = stat
|
|
252
|
-
rescue Errno::ENOENT
|
|
253
|
-
raise ReopenException
|
|
252
|
+
rescue Errno::ENOENT
|
|
253
|
+
raise ReopenException.new(:top) # File was missing, maybe it has been rotated, start from top
|
|
254
|
+
rescue Errno::ESTALE
|
|
255
|
+
raise ReopenException # File is stale let's try opening again with same mo
|
|
254
256
|
end
|
|
255
257
|
|
|
256
258
|
def sleep_interval
|
data/tests/file_tail_test.rb
CHANGED
|
@@ -12,8 +12,8 @@ class FileTailTest < Test::Unit::TestCase
|
|
|
12
12
|
include FileUtils
|
|
13
13
|
|
|
14
14
|
def setup
|
|
15
|
-
@out = File.new(File.join(
|
|
16
|
-
at_exit { rm_f File.expand_path(
|
|
15
|
+
@out = File.new(File.join('tmp', "test.#$$"), "wb")
|
|
16
|
+
at_exit { path = @out&.path and rm_f File.expand_path(path) }
|
|
17
17
|
append(@out, 100)
|
|
18
18
|
@in = File.new(@out.path, "rb")
|
|
19
19
|
@in.extend(File::Tail)
|
data/tmp/.gitkeep
ADDED
|
File without changes
|
metadata
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: file-tail
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: gem_hadar
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
|
-
- - "
|
|
16
|
+
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
18
|
+
version: 2.16.3
|
|
20
19
|
type: :development
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
|
-
- - "
|
|
23
|
+
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
25
|
+
version: 2.16.3
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: test-unit
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -109,11 +108,12 @@ extra_rdoc_files:
|
|
|
109
108
|
- lib/file/tail/version.rb
|
|
110
109
|
files:
|
|
111
110
|
- ".all_images.yml"
|
|
111
|
+
- ".github/workflows/static.yml"
|
|
112
112
|
- ".gitignore"
|
|
113
113
|
- ".travis.yml"
|
|
114
114
|
- CHANGES.md
|
|
115
|
-
- COPYING
|
|
116
115
|
- Gemfile
|
|
116
|
+
- LICENSE
|
|
117
117
|
- README.md
|
|
118
118
|
- Rakefile
|
|
119
119
|
- VERSION
|
|
@@ -131,11 +131,11 @@ files:
|
|
|
131
131
|
- tests/file_tail_group_test.rb
|
|
132
132
|
- tests/file_tail_test.rb
|
|
133
133
|
- tests/test_helper.rb
|
|
134
|
+
- tmp/.gitkeep
|
|
134
135
|
homepage: http://github.com/flori/file-tail
|
|
135
136
|
licenses:
|
|
136
137
|
- Apache-2.0
|
|
137
138
|
metadata: {}
|
|
138
|
-
post_install_message:
|
|
139
139
|
rdoc_options:
|
|
140
140
|
- "--title"
|
|
141
141
|
- File-tail - File::Tail for Ruby
|
|
@@ -154,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
154
154
|
- !ruby/object:Gem::Version
|
|
155
155
|
version: '0'
|
|
156
156
|
requirements: []
|
|
157
|
-
rubygems_version:
|
|
158
|
-
signing_key:
|
|
157
|
+
rubygems_version: 4.0.2
|
|
159
158
|
specification_version: 4
|
|
160
159
|
summary: File::Tail for Ruby
|
|
161
160
|
test_files:
|
/data/{COPYING → LICENSE}
RENAMED
|
File without changes
|