scp

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2024 License: MPL-2.0 Imports: 14 Imported by: 0

README

Copy files over SCP with Go

Go Report Card

This is a fork of Bram Vandenbogaerde's excellent go-scp module. It adds a proxy io.Reader and io.Writer that could very well replace the more limited PassThru Factory. The io.Reader proxy is added to the copyFromRemote, and intercepts the stream coming from the remote, providing a more accurate progress from what is downloaded (provided download is slower than writing to disk) The io.Writer proxy is added to the CopyPassThru, and intercepts the stream going to the remote, providing a more accurate progress from what is uploaded (provided upload is slower than reading to disk) The proxies could easily be extended to also intercept the local reading/writing, rendering PassThru completely obsolete. But since it wasn't a requirement of this fork, it was left undone.

This package makes it very easy to copy files over scp in Go. It uses the golang.org/x/crypto/ssh package to establish a secure connection to a remote server in order to copy the files via the SCP protocol.

Example usage
package main

import (
	"fmt"
	scp "github.com/bramvdbogaerde/go-scp"
	"github.com/bramvdbogaerde/go-scp/auth"
	"golang.org/x/crypto/ssh"
	"os"
        "context"
)

func main() {
	// Use SSH key authentication from the auth package
	// we ignore the host key in this example, please change this if you use this library
	clientConfig, _ := auth.PrivateKey("username", "/path/to/rsa/key", ssh.InsecureIgnoreHostKey())

	// For other authentication methods see ssh.ClientConfig and ssh.AuthMethod

	// Create a new SCP client
	client := scp.NewClient("example.com:22", &clientConfig)

	// Connect to the remote server
	err := client.Connect()
	if err != nil {
		fmt.Println("Couldn't establish a connection to the remote server ", err)
		return
	}

	// Open a file
	f, _ := os.Open("/path/to/local/file")

	// Close client connection after the file has been copied
	defer client.Close()

	// Close the file after it has been copied
	defer f.Close()

	// Finally, copy the file over
	// Usage: CopyFromFile(context, file, remotePath, permission)

        // the context can be adjusted to provide time-outs or inherit from other contexts if this is embedded in a larger application.
	err = client.CopyFromFile(context.Background(), *f, "/home/server/test.txt", "0655")

	if err != nil {
		fmt.Println("Error while copying file ", err)
	}
}
Using an existing SSH connection

If you have an existing established SSH connection, you can use that instead.

func connectSSH() *ssh.Client {
   // setup SSH connection
}

func main() {
   sshClient := connectSSH()

   // Create a new SCP client, note that this function might
   // return an error, as a new SSH session is established using the existing connecton

   client, err := scp.NewClientBySSH(sshClient)
   if err != nil {
      fmt.Println("Error creating new SSH session from existing connection", err)
   }

   /* .. same as above .. */
}
Copying Files from Remote Server

It is also possible to copy remote files using this library. The usage is similar to the example at the top of this section, except that CopyFromRemote needsto be used instead.

For a more comprehensive example, please consult the TestDownloadFile function in t he tests/basic_test.go file.

Using the Proxy reader or writer

It is as simple as providing an io.ReadCloser or io.WriteCloser as the last parameter (can be nil when not using this functionality)

License

This library is licensed under the Mozilla Public License 2.0.
A copy of the license is provided in the LICENSE.txt file.

Copyright (c) 2020 Bram Vandenbogaerde

Fork by Jean-Pierre Doyon for Newtrax/Sandvik

Documentation

Overview

Package scp. Simple scp package to copy files over SSH.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Ack

func Ack(writer io.Writer) error

Ack writes an `Ack` message to the remote, does not await its response, a seperate call to ParseResponse is therefore required to check if the acknowledgement succeeded.

func CopyN

func CopyN(writer io.Writer, src io.Reader, size int64) (int64, error)

CopyN an adaptation of io.CopyN that keeps reading if it did not return a sufficient amount of bytes.

func ParseFileInfos

func ParseFileInfos(message string, fileInfos *FileInfos) error

func ParseFileTime

func ParseFileTime(
	message string,
	fileInfos *FileInfos,
) error

Types

type Client

type Client struct {
	// Host the host to connect to.
	Host string

	// ClientConfig the client config to use.
	ClientConfig *ssh.ClientConfig

	// Timeout the maximal amount of time to wait for a file transfer to complete.
	// Deprecated: use context.Context for each function instead.
	Timeout time.Duration

	// RemoteBinary the absolute path to the remote SCP binary.
	RemoteBinary string
	// contains filtered or unexported fields
}

func NewClient

func NewClient(host string, config *ssh.ClientConfig) Client

NewClient returns a new scp.Client with provided host and ssh.clientConfig.

func NewClientBySSH

func NewClientBySSH(ssh *ssh.Client) (Client, error)

NewClientBySSH returns a new scp.Client using an already existing established SSH connection.

func NewClientBySSHWithTimeout

func NewClientBySSHWithTimeout(ssh *ssh.Client, timeout time.Duration) (Client, error)

NewClientBySSHWithTimeout same as NewClientWithTimeout but uses an existing SSH client. Deprecated: provide meaningful context to each "Copy*" function instead.

func NewClientWithTimeout

func NewClientWithTimeout(host string, config *ssh.ClientConfig, timeout time.Duration) Client

NewClientWithTimeout returns a new scp.Client with provides host, ssh.ClientConfig and timeout. Deprecated: provide meaningful context to each "Copy*" function instead.

func (*Client) Close

func (a *Client) Close()

func (*Client) Connect

func (a *Client) Connect() error

Connect connects to the remote SSH server, returns error if it couldn't establish a session to the SSH server.

func (*Client) Copy

func (a *Client) Copy(
	ctx context.Context,
	r io.Reader,
	remotePath string,
	permissions string,
	size int64,
) error

Copy copies the contents of an io.Reader to a remote location.

func (*Client) CopyFile

func (a *Client) CopyFile(
	ctx context.Context,
	fileReader io.Reader,
	remotePath string,
	permissions string,
) error

CopyFile copies the contents of an io.Reader to a remote location, the length is determined by reading the io.Reader until EOF if the file length in know in advance please use "Copy" instead.

func (*Client) CopyFilePassThru

func (a *Client) CopyFilePassThru(
	ctx context.Context,
	fileReader io.Reader,
	remotePath string,
	permissions string,
	passThru PassThru,
	proxy ProxyInterface,
) error

CopyFilePassThru copies the contents of an io.Reader to a remote location, the length is determined by reading the io.Reader until EOF if the file length in know in advance please use "Copy" instead. Access copied bytes by providing a PassThru reader factory. Proxy allows Intercepting the IoWriter as it is written for progress reporting or any other stream modification/monitoring reason and can be set to nil to disable this behaviour.

func (*Client) CopyFromFile

func (a *Client) CopyFromFile(
	ctx context.Context,
	file os.File,
	remotePath string,
	permissions string,
) error

CopyFromFile copies the contents of an os.File to a remote location, it will get the length of the file by looking it up from the filesystem.

func (*Client) CopyFromFilePassThru

func (a *Client) CopyFromFilePassThru(
	ctx context.Context,
	file os.File,
	remotePath string,
	permissions string,
	passThru PassThru,
) error

CopyFromFilePassThru copies the contents of an os.File to a remote location, it will get the length of the file by looking it up from the filesystem. Access copied bytes by providing a PassThru reader factory.

func (*Client) CopyFromRemote

func (a *Client) CopyFromRemote(ctx context.Context, file *os.File, remotePath string) error

CopyFromRemote copies a file from the remote to the local file given by the `file` parameter. Use `CopyFromRemotePassThru` if a more generic writer is desired instead of writing directly to a file on the file system.

func (*Client) CopyFromRemoteFileInfos

func (a *Client) CopyFromRemoteFileInfos(
	ctx context.Context,
	w io.Writer,
	remotePath string,
	passThru PassThru,
	proxy ProxyInterface,
) (*FileInfos, error)

CopyFroRemoteFileInfos copies a file from the remote to a given writer and return a FileInfos struct containing information about the file such as permissions, the file size, modification time and access time Proxy allows Intercepting the IoReader as it is written for progress reporting or any other stream modification/monitoring reason and can be set to nil to disable this behaviour.

func (*Client) CopyFromRemotePassThru

func (a *Client) CopyFromRemotePassThru(
	ctx context.Context,
	w io.Writer,
	remotePath string,
	passThru PassThru,
	proxy ProxyInterface,
) error

CopyFromRemotePassThru copies a file from the remote to the given writer. The passThru parameter can be used to keep track of progress and how many bytes that were download from the remote. `passThru` can be set to nil to disable this behaviour. Proxy allows Intercepting the IoReader as it is written for progress reporting or any other stream modification/monitoring reason and can be set to nil to disable this behaviour.

func (*Client) CopyPassThru

func (a *Client) CopyPassThru(
	ctx context.Context,
	r io.Reader,
	remotePath string,
	permissions string,
	size int64,
	passThru PassThru,
	proxy ProxyInterface,
) error

CopyPassThru copies the contents of an io.Reader to a remote location. Access copied bytes by providing a PassThru reader factory Proxy allows Intercepting the IoWriter as it is written for progress reporting or any other stream modification/monitoring reason and can be set to nil to disable this behaviour.

func (*Client) SSHClient

func (a *Client) SSHClient() *ssh.Client

Returns the underlying SSH client, this should be used carefully as it will be closed by `client.Close`.

type ClientConfigurer

type ClientConfigurer struct {
	// contains filtered or unexported fields
}

ClientConfigurer a struct containing all the configuration options used by an scp client.

func NewConfigurer

func NewConfigurer(host string, config *ssh.ClientConfig) *ClientConfigurer

NewConfigurer creates a new client configurer. It takes the required parameters: the host and the ssh.ClientConfig and returns a configurer populated with the default values for the optional parameters.

These optional parameters can be set by using the methods provided on the ClientConfigurer struct.

func (*ClientConfigurer) ClientConfig

func (c *ClientConfigurer) ClientConfig(config *ssh.ClientConfig) *ClientConfigurer

ClientConfig alters the ssh.ClientConfig.

func (*ClientConfigurer) Create

func (c *ClientConfigurer) Create() Client

Create builds a client with the configuration stored within the ClientConfigurer.

func (*ClientConfigurer) Host

func (c *ClientConfigurer) Host(host string) *ClientConfigurer

Host alters the host of the client connects to.

func (*ClientConfigurer) RemoteBinary

func (c *ClientConfigurer) RemoteBinary(path string) *ClientConfigurer

RemoteBinary sets the path of the location of the remote scp binary Defaults to: /usr/bin/scp.

func (*ClientConfigurer) SSHClient

func (c *ClientConfigurer) SSHClient(sshClient *ssh.Client) *ClientConfigurer

func (*ClientConfigurer) Timeout

func (c *ClientConfigurer) Timeout(timeout time.Duration) *ClientConfigurer

Timeout Changes the connection timeout. Defaults to one minute.

type CloseSSHCLient

type CloseSSHCLient struct {
	// contains filtered or unexported fields
}

Close handler to close an SSH client

func (CloseSSHCLient) Close

func (scp CloseSSHCLient) Close()

type EmptyHandler

type EmptyHandler struct{}

Close handler equivalent to a no-op. Used by default when no resources have to be cleaned.

func (EmptyHandler) Close

func (EmptyHandler) Close()

type FileInfos

type FileInfos struct {
	Message     string
	Filename    string
	Permissions uint32
	Size        int64
	Atime       int64
	Mtime       int64
}

func NewFileInfos

func NewFileInfos() *FileInfos

func ParseResponse

func ParseResponse(reader io.Reader, writer io.Writer) (*FileInfos, error)

ParseResponse reads from the given reader (assuming it is the output of the remote) and parses it into a Response structure.

func (*FileInfos) Update

func (fileInfos *FileInfos) Update(new *FileInfos)

type ICloseHandler

type ICloseHandler interface {
	Close()
}

Callback for freeing managed resources

type PassThru

type PassThru func(r io.Reader, total int64) io.Reader

type ProgressWriter

type ProgressWriter struct {
	Writer io.Writer
	Total  int64
}

func (*ProgressWriter) Write

func (pw *ProgressWriter) Write(p []byte) (int, error)

type ProxyInterface

type ProxyInterface interface {
	GetIoWriter(io.Writer) io.Writer
	GetIoReader(io.Reader) io.Reader
}

type ResponseType

type ResponseType = byte
const (
	Ok      ResponseType = 0
	Warning ResponseType = 1
	Error   ResponseType = 2
	Create  ResponseType = 'C'
	Time    ResponseType = 'T'
)

Directories

Path Synopsis
Copyright (c) 2020 Bram Vandenbogaerde * You may use, distribute or modify this code under the * terms of the Mozilla Public License 2.0, which is distributed * along with the source code.
Copyright (c) 2020 Bram Vandenbogaerde * You may use, distribute or modify this code under the * terms of the Mozilla Public License 2.0, which is distributed * along with the source code.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL