tailpipe: aqwari.net/io/tailpipe Index | Examples | Files

package tailpipe

import "aqwari.net/io/tailpipe"

Package tailpipe allows for reading normal files indefinitely. With the tailpipe package, code that uses the standard library's io.Reader interface can be transparently adapted to receive future updates to normal files.



Package Files



var ErrNotSupported = errors.New("Operation not supported by underlying stream")

The Follow function allows for the creation of a File with an underlying stream that may not implement all interfaces which a File implements. Such Files will return ErrNotSupported when this is the case.

type File Uses

type File struct {
    Rotated <-chan struct{}
    // contains filtered or unexported fields

A File represents an open normal file. A File is effectively of infinite length; all reads to the file will block until data are available, even if EOF on the underlying file is reached.

The tailpipe package will attempt to detect when a file has been rotated. Programs that wish to be notified when such a rotation occurs should receive from the Rotated channel.

func Follow Uses

func Follow(r io.Reader) *File

Follow converts an existing io.Reader to a tailpipe.File. This can be useful when opening files with special permissions. In general, the behavior of a tailpipe.File is only suitable for normal files; using Follow on an io.Pipe, net.Conn, or other non-file stream will yield undesirable results.

func Open Uses

func Open(path string) (*File, error)

Open opens the given file for reading.


tail, err := tailpipe.Open("/var/log/messages")
if err != nil {
defer tail.Close()
go func() {
    for range tail.Rotated {
        log.Printf("file %s rotated; following new file", tail.Name())
scanner := bufio.NewScanner(tail)
for scanner.Scan() {
    if bytes.Contains(scanner.Bytes(), []byte("ntpd")) {
        if _, err := os.Stdout.Write(scanner.Bytes()); err != nil {

func (*File) Close Uses

func (f *File) Close() error

Close closes the underlying file or stream. It also has the side effect of closing the File's Rotated channel. Close is safe to call multiple times.

func (*File) Name Uses

func (f *File) Name() string

Name returns the name of the underlying file, if available. If the underlying stream does not have a name, Name returns an empty string.

func (*File) Read Uses

func (f *File) Read(p []byte) (n int, err error)

Read reads up to len(p) bytes into p. If end-of-file is reached, Read will block until new data are available. Read returns the number of bytes read and any errors other than io.EOF.

If the underlying stream is an *os.File, Read will attempt to detect if it has been replaced, such as during log rotation. If so, Read will re-open the file at the original path provided to Open. Re-opening does not occur until the old file is exhausted.

func (*File) Seek Uses

func (f *File) Seek(offset int64, whence int) (int64, error)

Seek calls Seek on the underlying stream. If the underlying stream does not provide a Seek method, ErrNotSupported is returned.


a File's Rotated channel should not be relied upon to provide an accurate count of file rotations; because the tailpipe will only perform a non-blocking send on the Rotated channel, a goroutine may miss a new notification while it is responding to a previous notification. This is addressed by buffering the channel, but can still be a problem with files that are rotated very frequently.

Package tailpipe imports 5 packages (graph). Updated 2018-04-28. Refresh now. Tools for package owners. This is an inactive package (no imports and no commits in at least two years).