How to return data line by line (wodSSH / wodSSH.NET)
Hi
I have to process a command on a remote linux machine that will return a lot of text (think 'ls -alR /'). If I use ssh.Execute it returns all data as a string which is killing my memory, and in fact I need to process it line by line so I want to return the data that way. I tried several variations on following code, all gave me some text and then block completely until timeout. What am I doing wrong?
Thanks in advance,
Ernesto
...
String partialData = String.Empty;
ssh.DataReceivedEvent += (sender, args) =>
{
ssh.Timeout = 0;
while (true)
{
try
{
var tempString = ((SSH) sender).PeekLine();
((SSH)sender).Receive(tempString.Length);
if (partialData.Length > 0)
{
var s = partialData + tempString;
action(s);
partialData = String.Empty;
}
else
{
action(tempString);
}
}
catch (Exception ex)
{
//receive whats left of the buffer, waiting for the next batch
var partialString = ((SSH) sender).Receive();
partialData += partialString;
break;
}
}
ssh.Timeout = timeout;
};
ssh.Connect(hostname, port);
...
Action<String> action
is a delegate that will be called to send each line.
How to return data line by line
Hi Ernesto.
I didn't check the code very carefully, since I have to ask first: why didn't you use ReceiveLine method in the first place?
Perhaps that would help?
Jasmine.
How to return data line by line
Because ReceiveLine will block if there is no complete line in buffer, while PeekLine raises an exception. If I don't get the exception, I know there is a line in buffer and so I can use ReceiveLine (in later tests I replaced with Receive(length) but it is the same). But even so, I still got blocked sometimes.
Maybe the receive buffer is modified while I am extracting the data? if so, how can I prevent this to happening?
How to return data line by line
Hi Ernesto.
You should make a choice to use events or use Blocking = True mode, don't use both.
If you use events, then DataReceived event will fire when there's new data arrived, which you can consume. Since you're using Blocking = False in that case, ReceiveLine will also return immediately even if no data is waiting, so this is what you need.
If you use Blocking = True, don't use events, but use ReceiveLine in some loop.
Which option suits you better?
Jasmine.
How to return data line by line
ok, I will try with both modes to see which one is better for our app. In blocking mode, how do you define the loop? In the code below I use DataReady property, but in the help it says explicitly that this is not reliable. What should I use then?
Could you write a small example using the non blocking mode?
...
var linesReceived = 0;
ssh.Command = "ls -alR /";
try
{
ssh.Connect(hostname, port);
while (true)
{
var tempLine = ssh.ReceiveLine();
Console.WriteLine("{0} {1}", ++linesReceived, tempLine);
if (ssh.DataReady == 0)
break;
}
}
catch (Exception ex)
{
DebugMessage(String.Format("Connection exception {0}: {1}", ex.GetType(), ex.Message));
throw;
}
The exception code needs more work, at least I should capture the 'None found' exception (is it an Exception instance or some ENoneFoundException or something like that?) to cover the case when the command output does not include EOL at the end.
thanks
Ernesto
How to return data line by line
Hi Ernesto.
When to break out of loop depends on you. You should check if State == Connected - to make sure connection didn't drop while waiting for data to arrive. Besides that, get out of loop when you're personally ready, when you have received data you have expected.
Jasmine.
How to return data line by line
ok so what is the best way to check if there is still data? I want to receive all data sent. After the command is executed, the connection is closed? Maybe I could use that
How to return data line by line
Hi Ernesto.
I'm not sure what you're doing, so I can't say how to receive all data you send. Receive should return it. How to know it's end of what you have sent, and you're receiving data you expect to receive as a result of your command? Depends on the command itself. You should know what you have sent and what to expect back, and what is the 'separator' for those, perhaps just a CR LF sequence?
Jasmine.