I am currently uploading files to a unix server using SFTP using Renci SSH.NET, and it works fine. However, I now would like to upload files to a "Symlink container", and then create a symlink in another directory pointing to these files. Is that possible? I haven't found a class to manage symlinks, so how can this be achieved?
Use the SftpClient.SymbolicLink method.
public void SymbolicLink(string path, string linkPath)
Note that the meaning of the paths is a mess. The most common SFTP server, the OpenSSH, is buggy and uses the paths in a wrong order. Many other SFTP servers follow the bug for a compatibility. But not all. So you have to test which order is used by your servers.
See
https://bugzilla.mindrot.org/show_bug.cgi?id=861
http://bugs.proftpd.org/show_bug.cgi?id=4080
I have worked with SSH.net and I don't have found something about symlinks. However I found that SSH.net supports custom commands therefor you can write the Linux command (I think that it's ln) to create the symblink.
In this url you can get an example about how to use a custom command with SSH How to run several commands with SSH.Net?
Maybe if you need to create a lot symlinks, you can create a class or you can download the source code and add a new method.
I hope this can help you.
Related
I am trying to create a IoT DPS device with a symmetric key, For that to work, I need a ProvisioningTransportHandlerMqtt.
I have tried the console application fromlearn: https://learn.microsoft.com/en-us/azure/iot-dps/how-to-legacy-device-symm-key?tabs=windows&pivots=programming-language-csharp and I can provision devices with it.
I have tried making an interactive .Net notebook, and I can also provision devices from that:
The issue is only in my own cs file. When I try to run a similar line in a cs file the object is different:
The samplecode from Microsoft produces a valid transportHandeler:
I have no clue how to create a proper transportHandler. How do I get a proper ProvisioningTransportHandlerMqtt()?
Turned out including the DotNetty dlls in my app solved the issue.
I have successfully established a connection to a remote Linux server using the SSH.NET package with the following code (I am using a ShellStream because I have to use sudo su):
using (var client = new SshClient(server, username, password))
{
client.Connect();
List<string> commands = new List<string>();
commands.Add("sudo su - user");
commands.Add("vi test.properties");
ShellStream shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024);
// Execute commands under root account
foreach (string command in commands) {
WriteStream(command, shellStream);
}
client.Disconnect();
}
private static void WriteStream(string cmd, ShellStream stream)
{
stream.WriteLine(cmd + "; echo this-is-the-end");
while (stream.Length == 0)
Thread.Sleep(500);
}
I am trying to edit the test.properties file that is in the remote Linux server using a C# function that I created.
My code (using C# in Visual Studio) that is used to modify the text file is uses System.IO.File.ReadAllText, but it does not recognize the path of the remote server, for example:
The text file in the Linux server is in this location: /home/user/test.properties, so I am using this in my code:
System.IO.File.ReadAllText("/home/user/test.properties")
I am getting the following error:
Could not find a part of the path 'C:\home\user\test.properties'
For some reason it tries to look in my local file system instead of the remote server.
Is there a different approach I should be taking?
Thanks in advance!
In general, to modify remote files, use SFTP. In SSH.NET that's what SftpClient is for.
Though as you seem to need to use elevated privileges (su) – an important factor that your question title fails to mention – it's way more difficult. The right solution is to avoid the need for su. See somewhat related:
Allowing automatic command execution as root on Linux using SSH.
Another option would be to try to execute the SFTP server under su. Though that would require modification of SSH.NET code. See related Java question:
Using JSch to SFTP when one must also switch user
If you want to keep your current shell approach with su, you are stuck with simulating shell commands. Note that connecting to SSH server won't make other .NET classes (like the File) magically be able to work with remote files (even if SFTP was possible, let only when it is not, due to the su requirement).
The easiest way to read remote file using shell is using the cat command:
cat /home/user/test.properties
Alright, so after finishing the task, this is what I did since asking the question here:
1.After your(#Martin Prikryl) response I've tried using a combination of SSH and WinSCP:
WinSCP to download the file.
.NET to modify the locally downloaded file.
WinSCP to upload the file(and deleting it from the local folder afterwards).
SSH to move the file to its appropriate location in the server.
I discarded this solution because it worked pretty well in the lower environment,
but in the production I had permissions issues so I couldn't even download it, let alone that it might be a security issue(its a sensitive file).
2.My next solution was using only SSH to simulate shell commands, as you previously mentioned, I was limited to that because I was stuck using sudo su.
I connected to the server with SSH and used the 'sed' command to only show lines that contain specific words(instead of using cat to get the whole file).
I then used my .NET code to pull the values that I needed for my GET operation
For the POST operation I used 'sed' again to replace lines.
I have a script in Perl which runs on a Unix server (Solaris to be precise). The script uses ftp utility to condition files in a mainframe server and then transfer them to Unix server.
Recently, I am trying to develop a Windows desktop application using Windows forms and C#. I am trying to use the SSH.NET library available from codeplex. The problem is, whenever I run a normal Unix command from the application it works, but when I try to run the script it does not work. I have checked the connection and the application is properly connecting to the server. I have used both the below methods but no luck :-
using (ssh client = new SshClient("Ip", "username", "password"))
{
client.Connect();
SshCommand cmd = client.RunCommand("script");
client.Disconnect();
}
using (ssh client = new SshClient("hostnameOrIp", "username", "password"))
{
client.Connect();
SshCommand cmd = client.createCommand("script");
cmd.execute();
client.Disconnect();
}
It would be a huge help if somebody points me towards a proper direction.
EDIT :- Running the script with the full path has worked as the non interactive shell that is invoked doesn't read the /etc/profile/ env variables when it loads. I will try out the other options suggested as well and edit the post if something works.
You need to debug your unix script. Modify the script to pipe stderr to a text file, and see what it says. For instance, the script might be relying on properties of the environment which change when you run it with ssh.net
Your question is pretty vague.
But first, I'd try is to add a path to the script. Either absolute (/home/user/script) or relative (./script).
*nix shells by default do not look for executables in the current working directory (home directory in this case). They find them only, if you have . in your PATH.
Note that the RunCommand uses a non-interactive session. It may have a different environment (PATH) than the interactive session you use in the SSH terminal. Different set of start-up scripts is used for interactive and non-interactive sessions.
Please make sure the default path for the user is correct and script is exist in the path. In order to debug the last command/script run/exit status you can again run shell command echo $? via C# ssh client to get the detail about the error. That may give some insight about the error
I want to connect to remote server to upload some files via SCP/SSH.
I am using SharpSSH for this but it doesnt work.
Everytime the ScpClint wants to connect i get the JSchException verify: False.
Here is my code:
Scp scpClient = new Scp();
scpClient.To(#"C:localPath", "hostIP", "/var/...", sshUser, sshPwd);
Does anybody an have any suggestions on how to fix this problem? Maybe another library? I also tried Renci.SshNet but there I can connect or it doesn't give any errors, but no matter what I try to upload nothing is to find on the Server.
Which version of the library are you using? That code is fairly old and unmaintained. My usual recommendation is to try SSHNet since that's a much more solid library, written for .NET, but you said you've already tried that. Perhaps it's a problem on the remote side if you cannot connect with either of the libraries?
I have an application that deploys game data files to different gaming consoles. If matching files on the users machine and the console have identical size and dates, they must not be re-deployed.
On Xbox, this is easily accomplished because an XDK library used to upload files on the console allows me to set the date on the uploaded files to match the dates on the user's machine.
On Ps3 however, I use an FTP service running on the console. I use WebClient.UploadFileAsync to upload files to the console. However, I cannot figure out how I can set the uploaded file's date timestamp, leaving me with only the file size to determine identical files which is unsafe.
I was wondering if there was a way to set a file's date timestamp through the WebClient interface?
I don't think you can use the WebClient interface for this.
There seem to be various non-standard FTP extension commands implemented by some FTP servers to support the setting of a file's last modified time. The ones I know about are:
MDTM - This is the standard command for getting the a file's last modification time (as used by GetDateTimestamp()). Some servers support a set operation by specifying a timestamp argument to the command. as well as a filename.
MFMT - This was defined in an IETF experimental draft MFMT, to standardise this operation and avoid the non-standard use of the MDTM command described above.
SITE UTIME
If the FTP server running on the PS3 supports any of these extensions (check the result of the FEAT command), then you could use a simple socket FTP connection to issue the appropriate command to the server, after uploading the file.
WebClient will hand off ftp connections to FtpWebRequest. If you use FtpWebRequest directly you can send FTP commands to the server. The commands that are supported are defined as fields of WebRequestMethods.Ftp. One of those commands is GetDateTimestamp.
So if you construct an FtpWebRequest manually (instead of through WebClient) and send either the GateDateTimestamp or the ListDirectoryDetails command, you should be able to get the timestamp of the target file.