I'm trying to write a simple utility in pure Nim for monitoring a file by following new content added to it (kinda like tail -f FILE), but it appears it doesn't work for some reason.
However, if I add the discard file.getFileSize() line, then it works.
Any ideas what am I doing wrong? Thanks!
# monitor.nim
import os
proc monitorFile(filename: string) =
let file = open(filename, fmRead)
file.setFilePos(0, fspEnd)
while true:
try:
let line = file.readLine()
echo "Newline: ", line
except EOFError:
sleep(100)
# discard file.getFileSize()
monitorFile("/tmp/test.log")
This is a pretty crude way of monitoring a file for changes. A better way to do this would be with std/selectors and wait for Read events and then read the file to the end.
Alternatively you could use something like this: https://github.com/elcritch/dmon-nim
FYI: Currently on OSX:
nim -v
Nim Compiler Version 2.2.0 [MacOSX: amd64]
Compiled at 2024-10-02
Copyright (c) 2006-2024 by Andreas Rumpf
active boot switches: -d:release
Trying to run the test example result in the following compile error:
dennismisener@Denniss-iMac dmon-nim % n tests/example.nim
/Users/dennismisener/.nimble/pkgs2/faststreams-0.3.0-97edf9797924af48566a0af8267203dc21d80c77/faststreams/buffers.nim(65, 9) template/generic instantiation of `offset` from here
/Users/dennismisener/.nimble/pkgs2/stew-0.1.0-46d58c4feb457f3241e3347778334e325dce5268/stew/ptrops.nim(39, 11) Error: invalid pragma: checks: off
dennismisener@Denniss-iMac dmon-nim % v /Users/dennismisener/.nimble/pkgs2/stew-0.1.0-46d58c4feb457f3241e3347778334e325dce5268/stew/ptrops.nim
Commenting out the imbedded '{.checks: off.}' statement seems to solve the problem.
{BTW: this was with stew 0.1.0 -- installing 0.2.0 didn't seem to help)
Hmmm, thanks for the report. Feel free to file an issue.
I suspect it's a nimble issue with older nimble that semi-randomly decides package versions. I recommend doing nimble install nimble@\#head and verifying nimble -v returns at least 0.16.4. Then do another nimble install -d.
If that still fails please post the output of nimble deps --tree.
I'm looking to learn more about cross-platform file monitoring, so I must ask what is the reasoning behind using kqueue directly, versus say using std/selectors module (which already abstracts some of these notification subsystems).
Do you need lower level facilities from kqueue?
Do you need lower level facilities from kqueue?
Possibly? If not, then using std/selectors would be much preferred. Unfortunately both Mac and Windows use completely different subsystems.
Linux uses file descriptors but otherwise the inotify api is different than using select. So I'm figuring kqueue might be similar.
Also, I suspect the MacOS library is just a wrapper around Darwin's kqueue.
I'm looking to learn more about cross-platform file monitoring, so I must ask what is the reasoning behind using kqueue directly
Please make a PR for the BSD's! ;) I also recommend trying Claude Sonnet. It's pretty handy for making systems examples.
FYI, I've tried the std/selectors module on both macOS and OpenBSD and it works. Here's my test example:
# follow.nim
import
selectors, tables, strformat, os
type
FileSource = object
path: string
file: File
proc monitorsFiles() =
let names = ["a.log", "b.log", "c.log"]
var sources: Table[int, FileSource]
for name in names:
let file = open(name, fmRead)
file.setFilePos(0, fspEnd)
sources[file.getFileHandle()] = FileSource(path: name, file: file)
let selector = newSelector[int]()
let events = {Read}
for source in sources.values:
selector.registerHandle(source.file.getFileHandle(), events, 0)
echo fmt"Monitoring files..."
while true:
try:
let triggers = selector.select(500)
if triggers.len > 0:
for trigger in triggers:
if trigger.events == {Read}:
assert trigger.errorCode == 0.OSErrorCode
let source = sources[trigger.fd]
stdout.write fmt"{source.path}: {source.file.readAll()}"
except IOSelectorsException:
sleep(100)
monitorsFiles()
Thanks for the feedback:
I see you've already addressed the issue in the recent update... It wow works fine out of the box. Speedy delivery! 5 stars {grin}