fieldrndservices / libssh2-labview

A LabVIEW library for SSH client support via libssh2
Apache License 2.0
22 stars 2 forks source link

Example "Execute Multiple Commands with a Single Channel" not working #28

Closed MakeNModify closed 3 years ago

MakeNModify commented 4 years ago

Hallo,

first thank you for this great tool.

Tested in LabView2017 and LabView2020 on Win 10 (19042.630). Installed Version 1.0.0.20 via VI Package Manager. The server I'm connecting to is running Debian Buster with Armbian Linux 4.19.62-sunxi on a Banana-Pi

The example "Single Command Execution" works as expected. But the example "Execute Multiple Commands with a Single Channel" returns the Commands as Response. So I send echo "Hello World from the first command!" and get echo "Hello World from the first command!" (exactly the same) back. Same goes for other commands.

Tried to add an \r at the end as a test, same result but with \r\n at the end.

If you need any other info, let me know

volks73 commented 4 years ago

Thank you for your interest in this toolkit. I am happy to hear at least the "Single Command Execution" example works for your environment. Thank you for the extensive system description and additional attempts with the line endings, as well.

While not communicated through the issue tracker, I have had other users express problems with communicating with Raspberry-Pis. I am assuming the Banana-Pi is a similar device and runs a similar SSH server. Unfortunately, I never heard back about a resolution for communicating with Raspberry Pis. I don't know if the source of your problems is related, but I wanted to make a note here for others and in the future.

I will need some time to research the Debian Buster distribution and its SSH server. I would assume it is running an OpenSSH server, but maybe there is some feature missing from the libssh2 library and ultimately this toolkit that prevents it from working with Raspberry/Banana Pis. I don't have a Banana-Pi, but I do have a Raspberry Pi. It appears it is time for me to create my own test system for Raspberry Pis. However, this will have to wait until the weekend.

Some things to try in the mean time:

  1. Do you have another SSH server not running on the Banana-Pi that you could try with the "Execute Multiple Commands with a Single Channel" example?
  2. Open the block diagram to the Execute Multiple Commands with a Single Channel example and try different terminal types. The default is "dump". Do any of the terminal types work?
  3. Does the "Execute Multiple Commands with Multiple Channels" example work for you?
  4. Can you spin up a Virtual Machine (VM) running Debian Buster, Ubuntu, or similar Linux distribution and SSH into it from your Windows host?
  5. Instead of the password authentication, can you setup a passwordless authentication with the Banana-Pi and then try the Execute Multiple Commands with a Single Channel?
  6. Do any of the other examples work/not work?
MakeNModify commented 4 years ago

Hallo, thank you for your fast reply. I'll try to test the suggested things tomorrow when I'm back at work. I have several Linux devices and VMs I can test against.

MakeNModify commented 4 years ago

I tested on a other device running debian 4.19.0-12-amd64 without much success. It looks a bit like timing problem... It sends the first command and returns the first line of the welcome message of the system. Then it sends the second command and returns the first command (not the answer to it but the command it self). If I try to introduce a delay inside LabView it dose not change. Can't run a VM atm since it collides with WSL2 which i need to work :/ (trying to get it to work anyway but not much success yet).

Will try to keep testing if I find the time but since it doesn't seem like an easy to fix/find problem I'll have to find an alternative for now (sorry I'm under some time constraints). Thank you for your support. If I should find a solution I'll let you know.

volks73 commented 4 years ago

@MakeNModify: I understand you are under a time constraint, but I had a thought. While it may appear to be a timing issue, the indication that adding a Wait between reading the response of the first command and then writing the second command not working and the second response reading yields the first command suggests the Channel should be flushed between commands. A buffer somewhere in the stack (TCP, libssh2, LabVIEW) is possibly retaining the previous command and not getting cleared between writes/reads. There is the [libssh2_channel_flush_ex()]() function in the libssh2 C library, which has been implemented in this LabVIEW toolkit as "Flush.vi". If you still have time, please try the following:

Add_Flush_between_commands_snippet

which adds the Flush.vi after reading the first response but before writing the second command. I think this should clear out all the various buffers and provide a "clean" channel for the second command.

If you do not have time, then no worries and I am sorry this toolkit did not work for you.

MakeNModify commented 4 years ago

Did a quick test. The Pi just repeats what was sent and the other system answers with the welcome message most of the time (sometimes only on the first and then repeats the sent message on the second argument)... Will again have look tomorrow.

I think it's awesome that you did this library and want to support this project and others by helping to find the error, even if im might not use it in my current project.

volks73 commented 4 years ago

@MakeNModify Good News...I guess! I hooked up a Raspberry Pi with the latest OS and tried the "Execute Multiple Commands with a Single Channel" example I get the same behavior you are experiencing. In other words, I am able to reproduce the issue independent of your system. However, I do not have a fix at the moment. I will need some more time to debug, but I wanted to let you know some progress has been made.

MakeNModify commented 4 years ago

Great to hear that you could reproduce it 👍thanks for your support.

volks73 commented 3 years ago

@MakeNModify I believe I have a resolution. The short:

Execute_Multiple_Commands_with_a_Single_Channel_to_a_Raspberry_Pi

Add a Read.vi after creating the shell but before sending the first command.

The long:

The "Channel" commands are relatively low level and meant to be used more like building blocks to create a more full featured SSH library and more specifically, a feature full terminal/shell/interactive ssh client experience. For example, when you login into a Raspberry Pi with the ssh command from a terminal/shell on a host computer or using PuTTY, the following, higher level steps are taken:

  1. Establish a TCP connection between the Pi and the host computer.
  2. Cast TCP connection into a SSH session
  3. Authenticate and encrypt SSH session
  4. Create a SSH Shell for interactivity
  5. Print a login message
  6. Display prompt on Pi
  7. Type first command
  8. Print response to first command
  9. Type second command
  10. Print response to second command

This is summarized by the following terminal session using Windows Terminal, OpenSSH client, and Powershell:

> ssh pi@raspberrypi.local
pi@raspberrypi.local's password:
Linux raspberrypi 5.4.79-v7+ #1373 SMP Mon Nov 23 13:22:33 GMT 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Dec  3 10:52:49 2020 from 169.254.4.192

Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.

pi@raspberrypi:~ $ echo 'Hello World from first command'
Hello World from first command
pi@raspberrypi:~ $ echo 'Hello World from second command'
Hello World from second command
pi@raspberrypi:~ $ exit

The OpenSSH client or PuTTY are implementing Steps 1-4 for us in the background after hitting ENTER with the ssh command. If the OpenSSH client or PuTTY were implemented in LabVIEW, the Channel VIs in this toolkit would be used to implement/build Steps 1-4.

Ideally, a higher level toolkit that uses this lower level toolkit would wrap the Channel VIs to implement Steps 1-4 in a "SSH Shell" VI. At the moment, I feel creating a full featured, interactive SSH shell experience in LabVIEW is beyond the scope of this toolkit, and better handled in a separate toolkit/add-on/project that uses this toolkit for the plumbing.

Anyways, looking at the above example SSH shell session with the Raspberry Pi, a login message from the operating system (OS) is printed to the terminal. This is actually printed to STDOUT, which is written to the TCP connection through the SSH server when a SSH shell is created. Anything written to STDOUT on the Pi during a SSH session is written to the TCP connection and resides on the host computer's "read buffer". It is also important to remember that a TCP connection is a bi-directional communication protocol with independent transmit and receive buffers/streams/endpoints. In other words, reading and writing happen at the same time and you do not need to process reads before writes or writes before reads. This is further demonstration with the following VI snippet, which I hestitate to provide because someone, somewhere will use it for production:

Simultaneous Read-Write_to_a_Raspberry_Pi

The login message is written to the SSH read buffer. The first command is written to the SSH write buffer even though login message is still unread from the read buffer. Thus, when the first read occurs after sending the first command, the login message is actually read, not the response from the first command. All that is really needed is to read the login message before sending the first command, then all of the responses line up with the commands.

Side note, I tried the Flush.vi before sending the first command to "clear the login message", but it had no effect. I also tried different terminal types. This had no effect.

There might be some way to avoid printing the login message to STDOUT when connecting via a SSH session, but that is a system/Pi configuration or a different SSH channel type (exec?).

I found the answers to the What Is the Difference Between the Shell Channel and the Exec Channel in JSC question useful and informative.

MakeNModify commented 3 years ago

Thank you that makes sence. Will see if I can use it this ore an other project. Much to learn, so little time... Anyways this was very helpful and I'll try it on Monday (should not take me to long). This issue is solved for me I think ;) thanks for the support.

volks73 commented 3 years ago

I have added the two VI snippets from my previous post as "official" examples as of 27dfd06131955224255b532f600895f840979430.

A new release with the new examples along with some additional fixes will be made in the near future.