sshkit.ex icon indicating copy to clipboard operation
sshkit.ex copied to clipboard

SCP upload with `recursive: true` should notify user of an error when the destination directory does not exist

Open brienw opened this issue 7 years ago • 2 comments

I just observed that when attempting to SCP upload a directory with recursive: true, SSHKit does not notify the user of an error if the target destination directory does not exist. Instead SSHKit appears to hang until a timeout happens.

to reproduce (these snippets from an ExUnit test):


    local = "test/fixtures/local_workspace/"
    remote = "/some/nonexistent/destination"

    {:ok, conn} = SSH.connect(host.ip, Keyword.merge(@defaults, options))
    :ok = SCP.upload(conn, local, remote, recursive: true)
    # The above line with never return, instead a timeout exception is observed (inside ExUnit, in my case)

If i create the directory ahead of time, things work as expected


    local = "test/fixtures/local_workspace/"
    remote = "/some/nonexistent/destination"

    {:ok, conn} = SSH.connect(host.ip, Keyword.merge(@defaults, options))
    {:ok, _, 0} = SSH.run(conn, "mkdir -p #{remote}")
    :ok = SCP.upload(conn, local, remote, recursive: true)
    # YAY! It works now!

I haven't looked into the SCP protocol to see if there is a way to check for this yet, and I haven't done any troubleshooting to find out where exactly it 'hangs'. After I'm done backfilling more of these SCP tests I can come back and take a longer look at this if you would like.

brienw avatar May 31 '17 17:05 brienw

I've started looking into this. My current insights:

  1. The remote sends a "warning" with the message "scp: /some/nonexistent/destination: No such file or directory\n":

    {:data, channel, 0, <<1, …>>}
    
  2. The download state switches to:

    {:next, "/Users/pmeinhardt/Code/bitcrowd/sshkit.ex/test/fixtures/local_dir", [["other.txt"], []], ["scp: /some/nonexistent/destination: No such file or directory"]}
    

    waiting for a message from the remote or for the connection to be closed by the remote.

  3. That never happens.

I'll check the SCP sources to see what the behavior should be in such cases 🤔

pmeinhardt avatar May 23 '18 14:05 pmeinhardt

Sifting through the OpenSSH scp C sources, I understand the behavior as follows:

Whenever the remote (sink) sends a warning code 1 in response to us (source) sending data…

  1. …we skip the current file and continue with the next item
  2. …we close the directory and continue with the next items (for recursive uploads)

I'll update the upload implementation accordingly after #122 is merged.

pmeinhardt avatar May 23 '18 14:05 pmeinhardt