A Node-RED node terminal front-end, to execute backend CLI commands.
Run the following npm command in your Node-RED user directory (typically ~/.node-red):
npm install bartbutenaers/node-red-contrib-xterm
Remark: when installing this node, NPM will show a warning in the console log:
Reason is that the xterm-addon-fit (which is an xterm plugin) has xterm as (peer) dependency in its package.json file, and since npm version 3.x such peer dependencies aren't installed automatically anymore. But that is NO problem since xterm is installed automatically anyway, when you install this Node-RED node ...
Please buy my wife a coffee to keep her happy, while I am busy developing Node-RED stuff for you ...
:warning: Since this node allows commands to be executed on the server, it is very important that your Node-RED is secured!
But you should take care of that anyway, since other nodes (e.g. Exec and Daemon nodes) also allow execution of commands on the server ...
To avoid introducing extra security riscs, this node uses the standard Node-RED communication mechanism (see also the 'Detailed Information' section below):
RED.comms
websocket channel.As a result: when you have secured your Node-RED environment, the communication for this terminal will have the same security level...
All processes launched from node-pty will launch at the same permission level of the parent process (i.e. the Node-RED process). Take care particularly when using node-pty inside a server that's accessible on the internet. It is recommended to launch the pseudo-terminal inside a container (like e.g. a Docker container) to protect the host machine.
This contribution offers a terminal window entirely integrated into Node-RED. It consists out of two parts that closely work together:
Each flow editor instance will have its own terminal session on the server side, which means that each editor will have its own independent terminal screen. As a result, multiple users can execute commands (in their own flow editor instance), independently from each other.
Currently macOS, Linux and Windows are supported on the server side.
Remark: this node can be used to connect to the server, where the Node-RED backend is running. But it is also possible to logon to other servers, for example on Linux using the ssh
command. Thanks to Paul for explaining this step by step in this discussion.
A custom sidebar tabsheet is available, that can be setup in a few steps:
All node-related information (pseudo terminal started, pseudo terminal stopped, ...) and server side errors are being displayed INSIDE the terminal window.
A short demo of the sidebar tabsheet:
The following settings can be adjusted, to customize the terminal window:
The number of rows and columns that need to be displayed inside the terminal. Both characteristcs are specified in number of characters.
Specifies how the cursor should be displayed in the terminal window.
The modifier key hold to multiply scroll speed.
The number of rows that are retained when lines are scrolled beyond the initial viewport.
The background color of the terminal window.
The foreground color of the text on the terminal window.
The scroll speed multiplier used for scrolling.
The scroll speed multiplier used for fast scrolling.
Whether the cursor should be blinking or not.
Whether to draw bold text in bright colors.
Enable logging of all the data being send (both on client and server side), to simplify troubleshooting in case of problems.
The "Terminal Input" node can be used to store frequently used commands, and inject those commands into the terminal.
A short demo to explain how it works:
[{"id":"800e772a.b109c8","type":"xterm_in","z":"e2675d9d.6854e","command":"ls -ltr","addEnter":true,"confirmation":false,"name":"Directory listing","x":1260,"y":180,"wires":[]},{"id":"5a5f258.ad842dc","type":"xterm_in","z":"e2675d9d.6854e","command":"df -h","addEnter":true,"confirmation":false,"name":"Top disc usage","x":1260,"y":240,"wires":[]},{"id":"8ae725e0.57d5a8","type":"xterm_in","z":"e2675d9d.6854e","command":"ifconfig","addEnter":true,"confirmation":false,"name":"Network configuration","x":1280,"y":300,"wires":[]},{"id":"598184d3.be34ec","type":"xterm_in","z":"e2675d9d.6854e","command":"Iwlist wlan0 scan","addEnter":true,"confirmation":false,"name":"Available wireless networks","x":1300,"y":360,"wires":[]},{"id":"236fb7f7.0affc8","type":"xterm_in","z":"e2675d9d.6854e","command":"reboot","addEnter":true,"confirmation":true,"name":"Reboot","x":1240,"y":420,"wires":[]},{"id":"9dba7376.805f1","type":"xterm_in","z":"e2675d9d.6854e","command":"shutdown -h now","addEnter":true,"confirmation":true,"name":"Shutdown","x":1250,"y":480,"wires":[]},{"id":"5a5741.492658c","type":"xterm_in","z":"e2675d9d.6854e","command":"pwd","addEnter":true,"confirmation":false,"name":"Current directory","x":1260,"y":120,"wires":[]},{"id":"ee8feb7c.0cf0d8","type":"xterm_in","z":"e2675d9d.6854e","command":"pwd\npwd\npwd","addEnter":false,"confirmation":false,"name":"Example script","x":1260,"y":540,"wires":[]}]
The following settings can be adjusted, to customize the behaviour of the Terminal Input node:
Specify the command(s) that need to be executed in the terminal window . Multiple commands (each on a separate line!) can be added to create a script, as you can see in this demo:
Specify whether an 'enter' key (i.e. a newline character) will be added automatically after the last command.
Remark: this checkbox has more added value in case of a single command, since multiple commands are separated by enter's anyway ...
Critical commands (e.g. reboot the system) can be protected by a confirmation dialog, to avoid those commands being executed in the wrong circumstances. E.g. you might have pressed the inject button by accident...
The following demo explains how to a 'reboot' command can be secured, and cancelled when being clicked:
The following diagram explains the entire trajectory between the terminal and the operating system:
This communication mechanism allows data to be pushed on the fly to the terminal (e.g. when tailing a file), where it will be displayed to the user).
Since multiple flow editors can be active at the same time, some kind of terminal management is required. To accomplish this, the sidebar coding assigns a unique terminal Id to the flow editor where it is being displayed. That terminal id is being transferred all the time between the terminal window (client side) and the pseudo terminal (server side), to make sure the data of the multiple terminals doesn't get mixed.
This is also the main reason why I had to implement my own Terminal Input node: this node will also sends that unique terminal id to the server, to make sure that the data will be inject in the terminal window of the SAME flow editor (where the Terminal Input node's button has been clicked)! If I would have reused the Inject node, the server wouldn't have been able to determine in which terminal the data should be inserted. Therefore it is not possible to use the Inject node to inject commands into the terminal!
It would have been nice to have a Terminal output node, to capture the output of a command and process that data in your Node-RED flow. However such a Terminal Output node runs on the server, which means it is a single node instance that would get the data from all commands from all connected terminals. This way data from all connected terminals gets mixed, which is totally useless. Moreover the data would also contain the input from the user (so not only the terminal output)! Therefore it is not possible to create a useful Terminal Output node.
It is also not useful to have an output on the Terminal Input node: a single Terminal Input node on the server side, will be visualized in every flow editor. So the injected commands from all users will arrive at the same Terminal Input node instance, which means the data again will be mixed.
The node-pty pseudo terminal is written partly in the C-language, which means it needs to be compiled during installation. This requires the necessary build tools be installed on your system, and then it can cause a lot of headache solving all build conflichts...
However this node uses node-pty-prebuilt-multiarch, which offers prebuilt node-pty binaries for a series of operating systems and hardware architectures:
This way you can install this node hopefully a bit easier ...
But there will be lots of other platforms where the binaries will be build automatically. On some platforms you will even have execute manual steps to get a succesfull build, like e.g. for Oracle Cloud Free Instance as described here.
When a flow editor is being closed in the browser, the corresponding pseudo terminal process on the server should be stopped. Otherwise the pseudo terminal processes keep stacking up, and the number of pseudo terminals is limited by the host operating system. Since the server side cannot detect a flow editor being disconnected (see Nick's answer), the sidebar tab will send a heartbeat to the server every 5 seconds. When such a heartbeat doesn't arrive within 15 seconds, the pseudo terminal process (corresponding to the that terminal id) will be stopped automatically.
As a result you can also refresh your (flow editor) browser page, without running into troubles: the old pseudo terminal process will be killed within 15 seconds if the page should get a new unique terminal id. And a new terminal can be started...
If this should occur unexpected (e.g. due to network latency problems), you just need to start the terminal again. The 'Start' and 'Stop' buttons will always detect first whether a terminal is already running for this terminal id anyway ...