如何通过sudo运行命令并通过ssh .net输入密码c#
我想运行命令并在具有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? (我用贝壳制作方法,但我不明白什么是和像这个问题我得到了“上次登录:...”输出。)
正如已经提到的评论,最安全的方法是使用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'
我使用你的第二个解决方案。运行代码卡在var output = stream.Expect(promptRegex);在你第一个解决方案。 –
@ N_93如果第一个解决方案挂起,那么我的正则表达式用于匹配shell提示符对您来说不够普遍。但是,只要您确定密码在日志中可见,第二种解决方案就可以正常工作。 – RogerN
什么是'SshCommandLineRunner'?它是SSH.NET库的一部分吗?正常的方法是'CreateShellStream'来获取流并使用流的Expect和Write方法。 –