{"id":50925231,"url":"https://github.com/bennetyee/rrtail","last_synced_at":"2026-06-16T22:02:15.274Z","repository":{"id":359902059,"uuid":"1247798309","full_name":"bennetyee/rrtail","owner":"bennetyee","description":"Remote Resilient Tail","archived":false,"fork":false,"pushed_at":"2026-05-31T23:36:30.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-01T01:15:00.283Z","etag":null,"topics":["fault-tolerance","networking","tool"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bennetyee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-23T19:48:27.000Z","updated_at":"2026-05-31T23:36:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bennetyee/rrtail","commit_stats":null,"previous_names":["bennetyee/rrtail"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bennetyee/rrtail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennetyee%2Frrtail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennetyee%2Frrtail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennetyee%2Frrtail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennetyee%2Frrtail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bennetyee","download_url":"https://codeload.github.com/bennetyee/rrtail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennetyee%2Frrtail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34425024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fault-tolerance","networking","tool"],"created_at":"2026-06-16T22:02:13.605Z","updated_at":"2026-06-16T22:02:15.265Z","avatar_url":"https://github.com/bennetyee.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rrtail -- Remote Resilient Tail\n\nThe `rrtail` program fetches the contents of an append-only log file\nin a resilient way, so that temporary networking problems are masked.\nThis means that you can `rrtail` a log file from a remote machine\n(accessible via `ssh`) while at work, close your laptop, go to a cafe,\nhome, the airport, etc, and after waking up the laptop and having it\nget a new network address, the data from the log file will just\ncontinue to stream from where you left off, as if no interruption had\noccurred.\n\n`Rrtail` takes as a source file specifier `[user@]host:path` in much\nthe same way as `scp` and runs `ssh -l user host tail --bytes=+0 path`\nto fetch the data.  If/when the `ssh` process dies, e.g., because\nyou're running `rrtail` on your laptop and you're suspending it as you\nleave the cafe, `rrtail` will pause for a few seconds, then run `ssh\n-o TcpKeepAlive=Yes -l user host tail --bytes=+COUNT path` with\n`COUNT` being the number of bytes transfered earlier.  This resumes\nthe log transfer process transparently from the point of view of the\nconsumer of `rrtail`'s output.  This _masks the network failure_.\n\nThe duration by which `rrtail` sleeps after a network problem is\nsubject to exponential backoff up to an upper limit.  There are\ncommand line arguments that control the initial value, the base value\nfor the exponent, and the upper bound.\n\nIt is assumed that the necessary `ssh` credentials are stored in a\nkeyring, so that no password interaction is necessary when\nre-establishing the remote `tail` process.\n\n## EXAMPLE\n\n### Remote Monitoring\n\n```sh\n$ rrtail hostname:/var/log/auth.log\n```\n\n```sh\n$ rrtail hostname:/var/log/syslog\n```\n\nSee BUGS below.\n\n### Visualization\n\n```sh\n$ rrtail hostname:span-data/all-circuits.log | eval live_plotter --timestamp --labels $(cat span-data/labels) -v $(expr 60 \\* 60 \\* 24 \\* 2)\n```\n\nHere, we use `rrtail` to grab log data that is used to generate a\nbunch of time-series plots that allows us to visualize energy usage\naccording to the SPAN smart breaker panel.\n\nSee https://github.com/bennetyee/live_plotter for details of that program.\n\n## BUGS\n\nThere is no attempt to detect if the source file is not actually\nappend-only.\n\nIf the source file is subject to log rotation (e.g., `logrotate`) and\nmight be renamed daily, etc, `rrtail` would probably just stop sending\noutput since `tail` defaults to `--follow=descriptor`.  We don't use\n`--follow=name` and `--retry` (or equiv `-F`) because `rrtail` won't\nknow what `COUNT` value to use for the new file.\n\nIt might be possible to `ssh` into the source host, run `tail -F` with\nits output going to a tool like `nc` such that these processes don't\nget SIGHUP when the `ssh ` dies, except `nc -l` only accepts a single\nconnection and then exits, rather than provide single-client\nresumption semantics.  Alternatively, we could also run a more\nstateful streaming server program on the source machine than just\n`tail`, and use an actual protocol between its client (a new version\nof `rrtail`) and that server to handle resumption.  Garbage collecting\nthat server process -- distinguishing between pending resumption and\nthe client exiting (including via hard reboots) would be difficult.\n\nThis is the \"initial\" release of `rrtail`.  The network error message\nmatching is not well tested.\n\n## Disclaimer\n\nThe code in this repo is entirely vibe coded using\nhttp://aistudio.google.com/.  The only manual thing done other than\ncutting-and-pasting the AI Studio generated code into the repository\nis occasionally remembering to run `rustfmt`; the Studio generated\ncode sometimes has extraneous trailing spaces and the like.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbennetyee%2Frrtail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbennetyee%2Frrtail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbennetyee%2Frrtail/lists"}