Skip to content

Instantly share code, notes, and snippets.

@jedy
Last active May 31, 2022 07:20
Show Gist options
  • Save jedy/3357393 to your computer and use it in GitHub Desktop.
Save jedy/3357393 to your computer and use it in GitHub Desktop.
an example of scp in golang
// https://blogs.oracle.com/janp/entry/how_the_scp_protocol_works
package main
import (
"fmt"
"golang.org/x/crypto/ssh"
)
const privateKey = `content of id_rsa`
func main() {
signer, _ := ssh.ParsePrivateKey([]byte(privateKey))
clientConfig := &ssh.ClientConfig{
User: "jedy",
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
}
client, err := ssh.Dial("tcp", "127.0.0.1:22", clientConfig)
if err != nil {
panic("Failed to dial: " + err.Error())
}
session, err := client.NewSession()
if err != nil {
panic("Failed to create session: " + err.Error())
}
defer session.Close()
go func() {
w, _ := session.StdinPipe()
defer w.Close()
content := "123456789\n"
fmt.Fprintln(w, "D0755", 0, "testdir") // mkdir
fmt.Fprintln(w, "C0644", len(content), "testfile1")
fmt.Fprint(w, content)
fmt.Fprint(w, "\x00") // transfer end with \x00
fmt.Fprintln(w, "C0644", len(content), "testfile2")
fmt.Fprint(w, content)
fmt.Fprint(w, "\x00")
}()
if err := session.Run("/usr/bin/scp -tr ./"); err != nil {
panic("Failed to run: " + err.Error())
}
}
@baptistedonaux
Copy link

baptistedonaux commented Apr 12, 2018

Thank you for great job !

How can I determine "command" to send in Stdin ?

  • D0775 : D for directory (?) and next chars for permissions
  • C0644 : C for… create (?) and next chars for permissions

Do you have any links about theses instructions ? I searched in scp manual with no success.

[UPDATE]

I can found this post (thanks Web Archive) which gives commands availables. More, after few research it seems that SCP commands are not defined in any RFC.

@yesview
Copy link

yesview commented Mar 21, 2019

@baptistedonaux God bless you! Helped me a lot!

@juztin
Copy link

juztin commented Mar 10, 2022

Awesome! ty

This is working for me, and the file is copied over correctly, but the call to Run always returns an error: Process exited with status 1

session.Run("/usr/bin/scp -tr /tmp/")

anyone have any clues as to why this would be?

Got it!
I was writing a binary file, so I need this in-place of fmt.Fprint(w, content):

io.Copy(w, bytes.NewReader(galaArchive))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment