Interactive commands 'top' with rebex not execute?

0 votes
asked May 16, 2013 by post98 (200 points)
edited May 20, 2013

hi every body

I'd use the sample code that you put on the top, but I can not run this command?

If you are a code that can be ordered rebex 'top' can be implemented

Thank you

result:TERM environment variable not set.

Code:

using Rebex.Net;
using Rebex.TerminalEmulation;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Ssh client = new Ssh();

            client.Connect("192.168.150.129");

            // authenticate
            client.Login("reza", "1");

            // execute commands, start shells, etc...
            // ...
            Shell shell = client.StartShell(ShellMode.WellKnownShell);

            // read all response, effectively waiting for the command to end

            shell.SendCommand("top");

            // repeat while the command is running
            while (shell.IsRunning)
            {
                // read response until end or until '? ' is encountered
                string result = shell.ReadAll("? ");
                Debug.WriteLine(result);

                // if '? ' was encountered, send Y for yes
                if (result.EndsWith("? "))
                {
                    shell.SendCommand("y");
                }
            }
        }
    }
}

2 Answers

+1 vote
answered May 17, 2013 by Lukas Pokorny (85,170 points)
edited May 17, 2013
 
Best answer

The Shell object is intended to execute simple commands that don't need a pseudo terminal, which is not even requested from the server in ShellMode.WellKnownShell mode. This means that Shell object can't be used to run commands such as top (or mc, aptitude, etc.)

Instead, use VirtualTerminal or TerminalControl objects - both provide a virtual terminal, making them behave like a common SSH client (such as PuTTY). For example, to execute the top command with VirtualTerminal and display its output, the following code might be used:

    Ssh client = new Ssh();

    client.Connect("192.168.150.129");

    // authenticate
    client.Login("reza", "1");

    // start virtual termina (80x25)
    int columns = 80;
    int rows = 25;
    VirtualTerminal terminal = client.StartVirtualTerminal(null, columns, rows);

    // send 'top' command to the server
    terminal.SendToServer("top\n");

    // the 'top' command will run forever until terminated (by 'q' key, for example)
    while (true)
    {
        // process any available incoming data for 2 seconds
        TerminalState state = terminal.Process(2000);

        // break if disconnected
        if (state == TerminalState.Disconnected)
            break;

        if (state == TerminalState.DataReceived)
        {
            // display the current terminal screen content
            string[] lines = terminal.Screen.GetRegionText(0, 0, columns, rows);
            string result = string.Join("\n", lines);

            Debug.WriteLine(result);
        }
    }
0 votes
answered May 17, 2013 by post98 (200 points)
edited May 20, 2013

// the 'top' command will run forever until terminated (by 'q' key, for example)

But I can not run the top command to stop it with the key 'q'.

How can I make a program that is running the top command to stop. For example, pressing a key.

commented May 20, 2013 by Lukas Pokorny (85,170 points)
edited May 20, 2013

Please note: If this is a Windows Forms application, having a while loop inside a button click event handler is somewhat problematic - the application message queue is not being processed while the handler is running. Ideally, the content of the while loop should be run every N seconds using System.Windows.Forms.Timer object instead. Then, when a 'stop' button or key is pressed, you would call terminal.SendToServer("q") to terminate the top command.

Now, in order to keep the code simple, I will keep the while loop but call Application.DoEvents() to process the message queue, and a field to indicate to the loop that the top command should end:

public partial class Form1 : Form
{
    private bool TopShouldEnd;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Ssh client = new Ssh();

        client.Connect("192.168.150.129");

        // authenticate
        client.Login("reza", "1");

        // start virtual termina (80x25)
        int columns = 80;
        int rows = 25;
        VirtualTerminal terminal = client.StartVirtualTerminal(null, columns, rows);

        // send 'top' command to the server
        terminal.SendToServer("top\n");
        //terminal.SendToServer("q");

        // the 'top' command will run forever until terminated (by 'q' key, for example)
        while (true)
        {
            // process WinForm application's events (handle button clicks)
            Application.DoEvents();

            // process any available incoming data for 2 seconds
            TerminalState state = terminal.Process(2000);

            if (state == TerminalState.Disconnected)
                break;

            if (state == TerminalState.DataReceived)
            {
                // display the current terminal screen content
                string[] lines = terminal.Screen.GetRegionText(0, 0, columns, rows);
                string result = string.Join("\n", lines);

                Console.WriteLine(result);

                if (TopShouldEnd)
                {
                    // exit the 'top' command
                    terminal.SendToServer("q");
                    break;
                }
            }
        }

        // end the SSH session
        terminal.SendToServer("exit\n");
        terminal.Dispose();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        TopShouldEnd = true;
    }
}
...