Documentation
¶
Overview ¶
Package rsyncclient implements an rsync client (only), but note that gokrazy/rsync contains a native Go rsync implementation that supports sending and receiving files as client or server, compatible with the original tridge rsync (from the samba project) or openrsync (used on OpenBSD and macOS 15+).
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func New ¶
New creates a new Client. You can call Client.Run one or more times with the same Client.
func (*Client) Run ¶
Run starts one run of the rsync protocol (not the rsync daemon protocol), see also https://michael.stapelberg.ch/posts/2022-07-02-rsync-how-does-it-work/.
If you just want to transfer some data from an already running rsync server or remote system, use the github.com/gokrazy/rsync/rsynccmd package instead, which will take care of starting rsync as a subprocess (locally or remotely), or of connecting to an rsync daemon via TCP.
The Run method operates on any kind of connection (using the io.ReadWriter interface) and is meant to be used when you need more control over the setup. For example, maybe you want to set up some custom tunneling to an rsync process running deep in some remote cloud infrastructure.
Or maybe you want to connect an rsync client and server to each other via a custom RPC protocol. In that case, you will need to transport the Client.ServerCommandOptions to the server and then arrange for two io.ReadWriter connections between client and server.
Example (ReceiveFromSubprocess) ¶
package main import ( "context" "io" "log" "os/exec" "github.com/gokrazy/rsync/rsyncclient" ) func main() { args, src, dest := []string{"-av"}, "/usr/share/man", "/tmp/man" client, err := rsyncclient.New(args) if err != nil { log.Fatal(err) } // Start an rsync server and run an rsync client on its stdin/stdout. rsync := exec.Command("rsync", client.ServerCommandOptions(src)...) stdin, err := rsync.StdinPipe() if err != nil { log.Fatal(err) } stdout, err := rsync.StdoutPipe() if err != nil { log.Fatal(err) } if err := rsync.Start(); err != nil { log.Fatal(err) } // Create an io.ReadWriter from a Reader and a Writer. rw := &struct { io.Reader io.Writer }{ Reader: stdout, // The client reads from the server's stdout. Writer: stdin, // The client writes to the server's stdin. } if _, err := client.Run(context.Background(), rw, []string{dest}); err != nil { log.Fatal(err) } }
Output:
Example (SendToGoroutine) ¶
package main import ( "context" "io" "log" "github.com/gokrazy/rsync/internal/rsyncopts" "github.com/gokrazy/rsync/rsyncclient" "github.com/gokrazy/rsync/rsyncd" ) func main() { ctx := context.Background() args, src, dest := []string{"-av"}, "/usr/share/man", "/tmp/man" client, err := rsyncclient.New(args, rsyncclient.WithSender()) if err != nil { log.Fatal(err) } // Start an rsync server and run an rsync client on // an io.Pipe()-backend stdin/stdout. rsync, err := rsyncd.NewServer(nil) if err != nil { log.Fatal(err) } // stdin from the view of the rsync server stdinrd, stdinwr := io.Pipe() stdoutrd, stdoutwr := io.Pipe() go func() { conn := rsyncd.NewConnection(stdinrd, stdoutwr, "<io.Pipe>") pc, err := rsyncopts.ParseArguments(client.ServerCommandOptions(dest)) if err != nil { log.Fatalf("parsing server args: %v", err) } if err := rsync.InternalHandleConn(ctx, conn, nil, pc); err != nil { log.Fatal(err) } }() // Create an io.ReadWriter from a Reader and a Writer. rw := &struct { io.Reader io.Writer }{ Reader: stdoutrd, // The client reads from the server's stdout. Writer: stdinwr, // The client writes to the server's stdin. } if _, err := client.Run(ctx, rw, []string{src}); err != nil { log.Fatal(err) } }
Output:
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option specifies the client options.
func WithStderr ¶
WithStderr makes the Client write to the specified stderr instead of os.Stderr.
func WithoutNegotiate ¶
func WithoutNegotiate() Option
WithoutNegotiate disables protocol version negotiation (enabled by default).
type Result ¶
type Result struct {
Stats *rsyncstats.TransferStats
}
Result contains information about a transfer.