No such File or Directory

May 8, 2013 at 2:31 PM
Hello,

First I'd like to say that you have a great product here!

I am working with the latest binary (SshNet 4.0 Binary, 2013.4.7) and still get the scp error: "No such File or Directory" when trying to upload a file using the scp client. My C# code is listed below, but I have tried many variations of of this code based on the forum discussion with the same results. The target directory on linux "/data" is valid. Any suggestions would be greatly appreciated.

Thanks
Jim
    private void SCP_Upload_File()
    {
        try
        {
            string file = "C://temp//test.sh";
            if (!File.Exists(file)) return;

            FileInfo scriptInfo = new FileInfo(file);
            if ( ! scriptInfo.Exists)  return;

            ConnectionInfo connectionInfo = new PasswordConnectionInfo(host, port, user, pw);

            ScpClient scpClient = new ScpClient(connectionInfo);
            scpClient.BufferSize = 8 * 1024;
            scpClient.Connect();

            if (!scpClient.IsConnected)
            {
                return;
            }

            string targetPath = @"/data/test.sh";
            scpClient.Upload(scriptInfo.OpenRead(), targetPath);
            scpClient.Disconnect();
        }
        catch (Exception e)
        {
            lb_Log.Items.Add(e.Message);
        }
    }
May 8, 2013 at 11:01 PM
Any luck with this one? I too am finding the library WONDERFUL! THANK YOU! SSH works like a charm. Now I would like to copy a result that I redirected from the SSH command:
~/command --some_args >~/result.txt
Now via SCP, I say:
//The Configure and Connected are some extensions I cooked up to help it out by convention.
using (var client = new ScpClient(Host, User, Password).Configure().Connected())
{
  using (var fs = new FileStream("local.txt", FileMode.Create, FileAccess.Write, FileShare.Read))
  {
    //TODO: May hook up Downloading event (in fact I am, but for sake of example, the point is moot.
    client.Download("~/result.txt", fs);
    //ScpException: scp: ~/result.txt: No such file or directory
  }
}
However, like my colleague here, getting the same issue. It's there! I checked via Ssh. Is there a trick to making the Scp client work?

I could run the following and pick up the file: scp root@10.10.0.1:~/result.txt local.txt

Regards,

Michael Powell
May 8, 2013 at 11:07 PM
May be helpful, I ran an experiment with "local.txt" instead of "~/local.txt" and wouldn't you know it, I got the file transferred! Yay!

However, I would expect anything after the ":" in a typical Scp command would be fair game for Download remote file name, but who knew?

Perhaps some documentation around that issue would be a good thing.

HTH

Regards,

Michael Powell
May 9, 2013 at 2:36 PM
My file upload issue was finally resolved by adding the modified Upload method (redled, Feb 7, 2012) to the ScpClient.cs:
    public void Upload_2(FileInfo fileInfo, string filePath)
    {
        using (var input = new PipeStream())
        using (var channel = this.Session.CreateChannel<ChannelSession>())
        {
            channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
            {
                input.Write(e.Data, 0, e.Data.Length);
                input.Flush();
            };

            channel.Open();

            //  Send channel command request
            string directoryPath = filePath.Substring(0, filePath.LastIndexOf('/') + 1);
            string filename = filePath.Substring(filePath.LastIndexOf('/') + 1);

            if (String.IsNullOrEmpty(directoryPath))
                channel.SendExecRequest(string.Format("scp -qt {0}", filename));
            else
                channel.SendExecRequest(string.Format("cd {0};", directoryPath) + string.Format("scp -qt {0}", filename));
            this.CheckReturnCode(input);

            this.InternalUpload(channel, input, fileInfo, filename);

            channel.Close();
        }
    }
May 9, 2013 at 2:45 PM
This is in ScpClient itself? So it is a bug in ScpClient? Any chance that's finding its way back into the master/trunk, much less NuGet package? Thank ye!
May 9, 2013 at 4:29 PM
Yes. In the ScpClient itself.
May 29, 2013 at 2:35 PM
The issues with this code snippet is that a user might not have the rights to do anything but scp.
Calling the "cd" command will only raise an error.
For my purposes, I created an additional method in ScpClient that assumes the directory structure already exists on the remote host.
That way, I can simply copy files over without worrying about any of this. And since it does not split the string, the leading / is not lost in the process (which ultimately leads to the observed behaviour of copying into one's home folder).
This is, no doubt, only a workaround, but it works for me.
        /// <summary>
        /// Uploads the specified stream to the remote host.
        /// This method assumes that the remote directory structure already exists.
        /// </summary>
        /// <param name="source">Stream to upload.</param>
        /// <param name="path">Remote host file name.</param>
        public void UploadFile(Stream source, string path)
        {
          using (var input = new PipeStream())
            using (var channel = this.Session.CreateChannel<ChannelSession>())
            {
                channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
                {
                    input.Write(e.Data, 0, e.Data.Length);
                    input.Flush();
                };

                channel.Open();

                channel.SendExecRequest(string.Format("scp -rt \"{0}\"", path));
                this.CheckReturnCode(input);

                this.InternalUpload(channel, input, source, path);
                this.CheckReturnCode(input);

                channel.Close();
            }
        }