4

我正在编写一个非常小的 C# 程序,旨在允许我通过 SSH(使用 SSH .NET 客户端库)远程连接到服务器,并执行命令,主要是有关打印机的命令,例如“lpstat”。在此之前,我曾经为此目的使用 Putty 并手动检查内容(主要是打印机状态)。我想自动化其中的一些。使用 Putty 我正在与 user1 连接(在连接后提示输入用户/密码时)并且必须“sudo su - user2”才能执行 lpstat 和其他命令。

现在问题来了:一旦我连接到 SSH .NET,命令“sudo su -”似乎会冻结连接。为什么 ?会不会和Serverfault的这个问题一样?如果有另一种方式以 user2 身份连接(即以不同方式使用 SSH .NET),那对我来说没问题。

重要笔记:

  • 我不知道 user2 或 root 的密码
  • 它是一个生产服务器。我不是它的管理员,也不是一个非常高级的 Unix 用户。我不想更改该服务器配置。
  • 我相信冻结与要求输入密码的命令有关,但我不确定。

我当前的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Renci.SshNet;
using System.IO;
using System.Threading;

namespace SSHChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            SshClient sshClient = new SshClient(
                "IP",
                666, // port
                "user1",
                "user1Password");

            sshClient.Connect();
            SshCommand sshCommand;
            String res;

            //sshCommand = sshClient.RunCommand("ls d /"); // works fine
            sshCommand = sshClient.RunCommand("sudo su - user2"); // freezes ...
            sshCommand = sshClient.RunCommand("ls d /"); // ... so this code is never executed.

            sshClient.Disconnect();
        }
    }
}
4

2 回答 2

1

您是否解决了(6 年零 4 个月前)的问题?

这个来自 github 的用户kasbst在这里回答

我听从了他/她的回答,效果很好。

  • 我使用的是 CentOS 7 服务器(无需安装expect)。
  • 视觉工作室 2017

以下是他/她的代码和示例

private static void WriteStream(string cmd, ShellStream stream)
{
      stream.WriteLine(cmd + "; echo this-is-the-end");
      while (stream.Length == 0)
           Thread.Sleep(500);
}

private static string ReadStream(ShellStream stream)
{
      StringBuilder result = new StringBuilder();

      string line;
      while ((line = stream.ReadLine()) != "this-is-the-end")
             result.AppendLine(line);

      return result.ToString();
}

private static void SwithToRoot(string password, ShellStream stream)
{
       // Get logged in and get user prompt
       string prompt = stream.Expect(new Regex(@"[$>]"));
       //Console.WriteLine(prompt);

       // Send command and expect password or user prompt
       stream.WriteLine("su - root");
       prompt = stream.Expect(new Regex(@"([$#>:])"));
       //Console.WriteLine(prompt);

       // Check to send password
       if (prompt.Contains(":"))
       {
            // Send password
            stream.WriteLine(password);
            prompt = stream.Expect(new Regex(@"[$#>]"));
            //Console.WriteLine(prompt);
        }
}

样本:

using (var client = new SshClient(server, username, password))
{
          client.Connect();

          List<string> commands = new List<string>();
          commands.Add("pwd");
          commands.Add("cat /etc/sudoers");

          ShellStream shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024);

          // Switch to root
          SwithToRoot("rootpassword", shellStream);

          // Execute commands under root account
          foreach (string command in commands) {
                  WriteStream(command, shellStream);

                  string answer = ReadStream(shellStream);
                  int index = answer.IndexOf(System.Environment.NewLine);
                  answer = answer.Substring(index + System.Environment.NewLine.Length);
                  Console.WriteLine("Command output: " + answer.Trim());
           }

           client.Disconnect();
}

其他一些解释

我不知道 user2 或 root 的密码

在服务器设置中,用户可以在不提示密码的情况下切换帐号。

ls d /

一定是ls -d /

它只是在服务器的控制台上显示结果/输出,以便查看结果,使用ReadStream功能。

于 2019-10-11T07:38:34.270 回答
0

ssh.RunCommand("echo "" + rootPwd + "" | sudo -S " + command);

于 2021-04-15T19:14:50.520 回答