I want a way to replicate this command using ssh/crypto:
ssh user@host /bin/bash < dummy.sh
I can easily run binaries that's already in the host with simple
session.Run(cmd)
But I am having issues running complex command like this.
评论:
Perhyte:
titpetric:As /u/JHunz said, the
<
is not really part of the command line sent to the other machine. It just tells the local shell to connectdummy.sh
to the stdin of thessh
command (which is why it only works if the file is locally available). It's pretty much exactly as if you typed the contents of that file into ssh, then pressed Ctrl+D to simulate EOF and close the command.Now, as for how to replicate this in Go: the interface for
crypto/ssh.Session
seems to be similar to that ofos/Exec.Cmd
, so my guess would be something like:file, err := os.Open("dummy.sh") if err != null { return err; } defer file.Close() session.Stdin = file session.Run(cmd)
Disclaimer: I've never had occasion to use the
crypto/ssh
package.
JHunz:The cmd here should be something like "bash -c" for crypto/ssh, or "ssh user@host bash -c" for using os/exec, as a slice ofc. +1 on the explanation.
It's also possible to copy the originating script to the remote machine by running
cat > /tmp/outfile.sh
as the cmd. The file will be sent to Stdin, cat which executes on the remote host will read from it, and then write the contents into a file on the system. It might be better do so it like this, just so there's no weird tty issues or whatever (I haven't hit them myself, but some things require a tty and break if you don't have one).
pzduniak:The reading of the file and passing it in via the < is part of the shell, not SSH, so it's no wonder you're having trouble replicating it using just the SSH package. I'm guessing the best approach is to read the whole script in, then pass it all as the cmd to Session.Run
janderssen:You should execute it in sh -c - otherwise you'd pollute the system with temporary scripts.
notacyborg-v0:Ignoring best practises (ie error handling), the basic way I do this in our server is as follows :
signer, err := ssh.ParsePrivateKey([]byte(connectionInfo.PrivateKey)) sshConfig := &ssh.ClientConfig{ User: connectionInfo.UserID, Auth: []ssh.AuthMethod{ ssh.PublicKeys(signer), }, Timeout: time.Second * 5, } conn, err := net.DialTimeout("tcp", connectionInfo.AddressString(), sshConfig.Timeout) .. c, chans, reqs, err := ssh.NewClientConn(conn, connectionInfo.AddressString(), sshConfig) .. client = ssh.NewClient(c, chans, reqs)
So to run a command
session, err := client.NewSession() var b bytes.Buffer session.Stdout = &b session.Run("ls -l") // or what ever you want to execute
b contains output
Copy a script to the server for execution:
session, err := client.NewSession() bytesReader := bytes.NewReader(bytesToWrite) scp.Copy(int64(len(bytesToWrite)), 0644, filename, bytesReader, path, session)
I hope this helps.
Thanks, I have been trying to avoid doing that but looks like this is the only way out. Let me try it.
