sshkit.ex
sshkit.ex copied to clipboard
SCP upload with `recursive: true` should notify user of an error when the destination directory does not exist
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.
I've started looking into this. My current insights:
-
The remote sends a "warning" with the message
"scp: /some/nonexistent/destination: No such file or directory\n"
:{:data, channel, 0, <<1, …>>}
-
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.
-
That never happens.
I'll check the SCP sources to see what the behavior should be in such cases 🤔
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…
- …we skip the current file and continue with the next item
- …we close the directory and continue with the next items (for recursive uploads)
I'll update the upload implementation accordingly after #122 is merged.