2017-01-09 111 views
0

我想运行命令并在具有Linux操作系统的远程计算机上获得结果。我使用ssh .net库通过C#代码进行连接。我可以连接并运行一些命令,它不需要使用“sudo”。但我不知道如何运行需要由sudo运行的命令,因为运行后 - 例如 - “sudo iptables -L -n”我应该输入密码,我不知道如何在执行此命令后输入密码命令。如何通过sudo运行命令并通过ssh .net输入密码c#

这是我的代码:

private void connectingToLinuxHost(string ip, string username, string password, int port) 
{ 
    SshCommandLineRunner ssh = new SshCommandLineRunner(ip, username, password, port); 
    ssh.Connect(); 
    string output1 = ssh.ExecuteCommand("ls"); 

    ssh.ExecuteCommand("sudo iptables -L -n"); 
    Thread.Sleep(1000); 
    string output2 = ssh.ExecuteCommand(password); 

    ssh.ExecuteCommand("sudo iptables -L -n \n"); 
    Thread.Sleep(1000); 
    string output3 = ssh.ExecuteCommand(password); 
} 

时,此功能来看,我可以连接到远程PC成功,输出1有正确的值,但输出2和输出3是空的。实际上很明显,sudo命令后需要输入密码。 我读过关于ssh.net的大多数问题。一些类似的问题仍未得到答复。

SSH .NET : freeze upon sudo su - user2 (他或她不知道密码,但我知道,我不知道如何通过代码输入)

How to su with SSH.Net? (我用贝壳制作方法,但我不明白什么是和像这个问题我得到了“上次登录:...”输出。)

+0

什么是'SshCommandLineRunner'?它是SSH.NET库的一部分吗?正常的方法是'CreateShellStream'来获取流并使用流的Expect和Write方法。 –

回答

1

正如已经提到的评论,最安全的方法是使用CreateShellStream并直接将密码直接写入流中sudo命令。就像您使用交互式终端一样发送密码。这可能不是一个方便的解决方案,但是,如果您不希望被锁定在您想要执行的其他操作中使用无穷无尽的流。例如:

var promptRegex = new Regex(@"\][#$>]"); // regular expression for matching terminal prompt 
var modes = new Dictionary<Renci.SshNet.Common.TerminalModes, uint>(); 
using (var stream = ssh.CreateShellStream("xterm", 255, 50, 800, 600, 1024, modes)) 
{ 
    stream.Write("sudo iptables -L -n\n"); 
    stream.Expect("password"); 
    stream.Write("mypassword\n"); 
    var output = stream.Expect(promptRegex); 
} 

缺点是,你的输出将包括你真的不想要的垃圾:控制字符,提示和其他一切被流发送。

如果您想避免使用shell流,那么您可以(取决于安全设置)通过标准输入提供密码。这是INSECURE,因为命令会在各个地方登录,您可能会将其密码泄露给具有root访问权限的其他用户。如果你是唯一的用户,或者你不关心其他人都能看到你的密码,那么这对你来说可能会更方便。

例子:

using (var cmd = ssh.RunCommand("echo -e 'mypassword\n' | sudo -S iptables -L -n")) 
{ 
    if (cmd.ExitStatus == 0) 
     Console.WriteLine(cmd.Result); 
    else 
     Console.WriteLine(cmd.Error); 
} 

最后,它也可能有一个脚本,打印您的密码标准输入。这样你的密码就不会和命令行的其余部分一起被记录下来;但是这还不是更安全,因为任何人都具有root访问权限可能会看剧本和看到密码:

using (var cmd = ssh.RunCommand("~/printpasswd.sh | sudo -S iptables -L -n")) 
{ 
    if (cmd.ExitStatus == 0) 
     Console.WriteLine(cmd.Result); 
    else 
     Console.WriteLine(cmd.Error); 
} 

和内部printpasswd.sh:

#!/bin/bash 
echo -e 'mypassword\n' 
+0

我使用你的第二个解决方案。运行代码卡在var output = stream.Expect(promptRegex);在你第一个解决方案。 –

+0

@ N_93如果第一个解决方案挂起,那么我的正则表达式用于匹配shell提示符对您来说不够普遍。但是,只要您确定密码在日志中可见,第二种解决方案就可以正常工作。 – RogerN