See: Description
| Interface | Description |
|---|---|
| Shell |
An interactive session between a consumer and a shell.
|
| ShellServer |
The shell server.
A shell server is associated with a collection of
term servers: the ShellServer.registerTermServer(TermServer)
method registers a term server. |
| ShellService |
The shell service, provides a remotely accessible shell available via Telnet or SSH according to the
ShellServiceOptions configuration.
The shell service will expose commands using CommandResolver on the classpath and
the shared command registry for the Vert.x instance. |
| Class | Description |
|---|---|
| ShellServerOptions |
The configurations options for the shell server.
|
| ShellServerOptionsConverter |
Converter for
ShellServerOptions. |
| ShellServiceOptions |
The configurations options for the shell service, the shell connectors can be configured
with
TelnetTermOptions, SSHTermOptions and HttpTermOptions. |
| ShellServiceOptionsConverter |
Converter for
ShellServiceOptions. |
| ShellVerticle |
ShellService
or deployed as a service.
=== Shell service
The shell can be started as a service directly either from the command line or as a the Vert.x deployment:
.Starting a shell service available via Telnet
[source,subs="+attributes"]
----
vertx run -conf '{"telnetOptions":{"port":5000}}' maven:${maven.groupId}:${maven.artifactId}:${maven.version}
----
or
.Starting a shell service available via SSH
[source,subs="+attributes"]
----
# create a key pair for the SSH server
keytool -genkey -keyalg RSA -keystore ssh.jks -keysize 2048 -validity 1095 -dname CN=localhost -keypass secret -storepass secret
# create the auth config
echo user.admin=password > auth.properties
# start the shell
vertx run -conf '{"sshOptions":{"port":4000,"keyPairOptions":{"path":"ssh.jks","password":"secret"},"authOptions":{"provider":"shiro","config":{"properties_path":"file:auth.properties"}}}}' maven:${maven.groupId}:${maven.artifactId}:${maven.version}
----
or
.Starting a shell service available via HTTP
[source,subs="+attributes"]
----
# create a certificate for the HTTP server
keytool -genkey -keyalg RSA -keystore keystore.jks -keysize 2048 -validity 1095 -dname CN=localhost -keypass secret -storepass secret
# create the auth config
echo user.admin=password > auth.properties
vertx run -conf '{"httpOptions":{"port":8080,"ssl":true,"keyStoreOptions":{"path":"keystore.jks","password":"secret"},"authOptions":{"provider":""shiro,"config":{"properties_path":"file:auth.properties"}}}}' maven:${maven.groupId}:${maven.artifactId}:${maven.version}
----
You can also deploy this service inside your own verticle:
[source,$lang,subs="+attributes"]
----
examples.Examples#deployTelnetService(io.vertx.core.Vertx)
----
or
[source,$lang,subs="+attributes"]
----
examples.Examples#deploySSHServiceWithShiro(io.vertx.core.Vertx)
----
or
[source,$lang,subs="+attributes"]
----
examples.Examples#deployHttpServiceWithShiro(io.vertx.core.Vertx)
----
NOTE: when Vert.x Shell is already on your classpath you can use `service:io.vertx.ext.shell` instead
or `maven:${maven.groupId}:${maven.artifactId}:${maven.version}`
=== Programmatic service
The ShellService takes care of starting an instance of Vert.x Shell.
Starting a shell service available via SSH:
[source,$lang]
----
examples.Examples#runSSHServiceWithShiro(io.vertx.core.Vertx)
----
Starting a shell service available via Telnet:
[source,$lang]
----
examples.Examples#runTelnetService
----
The TelnetTermOptions extends the Vert.x Core `NetServerOptions` as the Telnet server
implementation is based on a `NetServer`.
CAUTION: Telnet does not provide any authentication nor encryption at all.
Starting a shell service available via HTTP:
[source,$lang]
----
examples.Examples#runHttpService
----
== Authentication
The SSH and HTTP connectors provide both authentication built on top of _vertx-auth_ with the following supported
providers:
- _shiro_ : provides `.properties` and _LDAP_ backend as seen in the ShellService presentation
- _jdbc_ : JDBC backend
- _mongo_ : MongoDB backend
These options can be created directly using directly AuthOptions:
- ShiroAuthOptions for Shiro
- JDBCAuthOptions for JDBC
- MongoAuthOptions for Mongo
As for external service configuration in Json, the `authOptions` uses the `provider` property to distinguish:
----
{
...
"authOptions": {
"provider":"shiro",
"config": {
"properties_path":"file:auth.properties"
}
}
...
}
----
== Telnet term configuration
Telnet terms are configured by ShellServiceOptions.setTelnetOptions(io.vertx.ext.shell.term.TelnetTermOptions),
the TelnetTermOptions extends the NetServerOptions so they
have the exact same configuration.
== SSH term configuration
SSH terms are configured by ShellServiceOptions.setSSHOptions(io.vertx.ext.shell.term.SSHTermOptions):
- SSHTermOptions.setPort(int): port
- SSHTermOptions.setHost(java.lang.String): host
Only username/password authentication is supported at the moment, it can be configured with property file
or LDAP, see Vert.x Auth for more info:
- SSHTermOptions.setAuthOptions(io.vertx.ext.auth.AuthOptions): configures user authentication
The server key configuration reuses the key pair store configuration scheme provided by _Vert.x Core_:
- SSHTermOptions.setKeyPairOptions(io.vertx.core.net.JksOptions): set `.jks` key pair store
- SSHTermOptions.setPfxKeyPairOptions(io.vertx.core.net.PfxOptions): set `.pfx` key pair store
- SSHTermOptions.setPemKeyPairOptions(io.vertx.core.net.PemKeyCertOptions): set `.pem` key pair store
.Deploying the Shell Service on SSH with Mongo authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#deploySSHServiceWithMongo(io.vertx.core.Vertx)
----
.Running the Shell Service on SSH with Mongo authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#runSSHServiceWithMongo(io.vertx.core.Vertx)
----
.Deploying the Shell Service on SSH with JDBC authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#deploySSHServiceWithJDBC(io.vertx.core.Vertx)
----
.Running the Shell Service on SSH with JDBC authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#runSSHServiceWithJDBC(io.vertx.core.Vertx)
----
== HTTP term configuration
HTTP terms are configured by ShellServiceOptions.setHttpOptions(io.vertx.ext.shell.term.HttpTermOptions), the http options
extends the HttpServerOptions so they expose the exact same configuration.
In addition there are extra options for configuring an HTTP term:
- HttpTermOptions.setAuthOptions(io.vertx.ext.auth.AuthOptions): configures user authentication
- HttpTermOptions.setSockJSHandlerOptions(io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions): configures SockJS
- HttpTermOptions.setSockJSPath(java.lang.String): the SockJS path in the router
.Deploying the Shell Service on HTTP with Mongo authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#deployHttpServiceWithMongo(io.vertx.core.Vertx)
----
.Running the Shell Service on HTTP with Mongo authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#runHTTPServiceWithMongo(io.vertx.core.Vertx)
----
.Deploying the Shell Service on HTTP with JDBC authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#deployHttpServiceWithJDBC(io.vertx.core.Vertx)
----
.Running the Shell Service on HTTP with JDBC authentication
[source,$lang,subs="+attributes"]
----
examples.Examples#runHTTPServiceWithJDBC(io.vertx.core.Vertx)
----
== Keymap configuration
The shell uses a default keymap configuration that can be overriden using the `inputrc` property of the various
term configuration object:
- TelnetTermOptions.setIntputrc(java.lang.String)
- SSHTermOptions.setIntputrc(java.lang.String)
- HttpTermOptions.setIntputrc(java.lang.String)
The `inputrc` must point to a file available via the classloader or the filesystem.
The `inputrc` only function bindings and the available functions are:
- _backward-char_
- _forward-char_
- _next-history_
- _previous-history_
- _backward-delete-char_
- _backward-delete-char_
- _backward-word_
- _end-of-line_
- _beginning-of-line_
- _delete-char_
- _delete-char_
- _complete_
- _accept-line_
- _accept-line_
- _kill-line_
- _backward-word_
- _forward-word_
- _backward-kill-word_
NOTE: Extra functions can be added, however this is done by implementing functions of the `Term.d` project on which
Vert.x Shell is based, for instance the https://github.com/termd/termd/blob/c1629623c8a3add4bde7778640bf8cc233a7c98f/src/examples/java/examples/readlinefunction/ReverseFunction.java[reverse function]
can be implemented and then declared in a `META-INF/services/io.termd.core.readline.Function` to be loaded by the shell.
== Base commands
To find out the available commands you can use the _help_ builtin command:
. Verticle commands
.. verticle-ls: list all deployed verticles
.. verticle-undeploy: undeploy a verticle
.. verticle-deploy: deploys a verticle with deployment options as JSON string
.. verticle-factories: list all known verticle factories
. File system commands
.. ls
.. cd
.. pwd
. Bus commands
.. bus-tail: display all incoming messages on an event bus address
.. bus-send: send a message on the event bus
. Net commands
.. net-ls: list all available net servers, including HTTP servers
. Shared data commands
.. local-map-put
.. local-map-get
.. local-map-rm
. Various commands
.. echo
.. sleep
.. help
.. exit
.. logout
. Job control
.. fg
.. bg
.. jobs
NOTE: this command list should evolve in next releases of Vert.x Shell. Other Vert.x project may provide commands to extend
Vert.x Shell, for instance Dropwizard Metrics.
== Extending Vert.x Shell
Vert.x Shell can be extended with custom commands in any of the languages supporting code generation.
A command is created by the CommandBuilder.command(java.lang.String) method: the command process handler is called
by the shell when the command is executed, this handler can be set with the CommandBuilder.processHandler(io.vertx.core.Handler<io.vertx.ext.shell.command.CommandProcess>)
method:
[source,$lang]
----
examples.Examples#helloWorld
----
After a command is created, it needs to be registed to a CommandRegistry. The
command registry holds all the commands for a Vert.x instance.
A command is registered until it is unregistered with the CommandRegistry.unregisterCommand(java.lang.String).
When a command is registered from a Verticle, this command is unregistered when this verticle is undeployed.
NOTE: Command callbacks are invoked in the io.vertx.core.Context when the command is registered in the
registry. Keep this in mind if you maintain state in a command.
The CommandProcess object can be used for interacting with the shell.
=== Command arguments
The CommandProcess.args() returns the command arguments:
[source,$lang]
----
examples.Examples#commandArgs
----
Besides it is also possible to create commands using Vert.x CLI: it makes easier to
write command line argument parsing:
- _option_ and _argument_ parsing
- argument _validation_
- generation of the command _usage_
[source,$lang]
----
examples.Examples#cliCommand()
----
When an option named _help_ is added to the CLI object, the shell will take care of generating the command usage
when the option is activated:
[source,$lang]
----
examples.Examples#cliCommandWithHelp()
----
When the command executes the process is provided for interacting
with the shell. A CommandProcess extends Tty
which is used for interacting with the terminal.
=== Terminal usage
==== terminal I/O
The Tty.stdinHandler(io.vertx.core.Handler<java.lang.String>) handler is used to be notified when the terminal
receives data, e.g the user uses his keyboard:
[source,$lang]
----
examples.Examples#readStdin
----
A command can use the Tty.write(java.lang.String) to write to the standard output.
[source,$lang]
----
examples.Examples#writeStdout
----
==== Terminal size
The current terminal size can be obtained using Tty.width() and
Tty.height().
[source,$lang]
----
examples.Examples#terminalSize
----
==== Resize event
When the size of the terminal changes the Tty.resizehandler(io.vertx.core.Handler)
is called, the new terminal size can be obtained with Tty.width() and
Tty.height().
[source,$lang]
----
examples.Examples#resizeHandlerTerminal
----
==== Terminal type
The terminal type is useful for sending escape codes to the remote terminal: Tty.type()
returns the current terminal type, it can be null if the terminal has not advertised the value.
[source,$lang]
----
examples.Examples#terminalType
----
=== Shell session
The shell is a connected service that naturally maintains a session with the client, this session can be
used in commands to scope data. A command can get the session with CommandProcess.session():
[source,$lang]
----
examples.Examples#session
----
=== Process termination
Calling CommandProcess.end() ends the current process. It can be called directly
in the invocation of the command handler or any time later:
[source,$lang]
----
examples.Examples#asyncCommand
----
=== Process events
A command can subscribe to a few process events.
==== Interrupt event
The CommandProcess.interruptHandler(io.vertx.core.Handler) is called when the process
is interrupted, this event is fired when the user press _Ctrl+C_ during the execution of a command. This handler can
be used for interrupting commands _blocking_ the CLI and gracefully ending the command process:
[source,$lang]
----
examples.Examples#interruptHandler
----
When no interrupt handler is registered, pressing _Ctrl+C_ will have no effect on the current process and the event
will be delayed and will likely be handled by the shell, like printing a new line on the console.
==== Suspend/resume events
The CommandProcess.suspendHandler(io.vertx.core.Handler) is called when the process
is running and the user press _Ctrl+Z_, the command is _suspended_:
- the command can receive the suspend event when it has registered an handler for this event
- the command will not receive anymore data from the standard input
- the shell prompt the user for input
- the command can receive interrupts event or end events
The CommandProcess.resumeHandler(io.vertx.core.Handler) is called when the process
is resumed, usually when the user types _fg_:
- the command can receive the resume event when it has registered an handler for this event
- the command will receive again data from the standard input when it has registered an stdin handler
[source,$lang]
----
examples.Examples#suspendResumeHandler
----
==== End events
The CommandProcess.endHandler(io.vertx.core.Handler) (io.vertx.core.Handler)} is
called when the process is running or suspended and the command terminates, for instance the shell session is closed,
the command is _terminated_.
[source,$lang]
----
examples.Examples#endHandler
----
The end handler is called even when the command invokes CommandProcess.end().
This handler is useful for cleaning up resources upon command termination, for instance closing a client or a timer.
=== Command completion
A command can provide a completion handler when it wants to provide contextual command line interface completion.
Like the process handler, the completion
handler is non blocking because the implementation may use Vert.x services, e.g the file system.
The Completion.lineTokens() returns a list of tokens
from the beginning of the line to the cursor position. The list can be empty if the cursor when the cursor is at the
beginning of the line.
The Completion.rawLine() returns the current completed from the beginning
of the line to the cursor position, in raw format, i.e without any char escape performed.
Completion ends with a call to Completion.complete(java.util.List).
== Shell server
The Shell service is a convenient facade for starting a preconfigured shell either programmatically or as a Vert.x service.
When more flexibility is needed, a ShellServer can be used instead of the service.
For instance the shell http term can be configured to use an existing router instead of starting its own http server.
Using a shell server requires explicit configuration but provides full flexiblity, a shell server is setup in a few
steps:
[source,$lang]
----
examples.Examples#shellServer
----
<1> create a the shell server
<2> create an HTTP term server mounted on an existing router
<3> create an SSH term server
<4> register term servers
<5> register all base commands
<6> finally start the shell server
Besides, the shell server can also be used for creating in process shell session: it provides a programmatic interactive shell.
In process shell session can be created with ShellServer.createShell(io.vertx.ext.shell.term.Term):
[source,$lang]
----
examples.Examples#creatingShell
----
The main use case is running or testing a command:
[source,$lang]
----
examples.Examples#runningShellCommand
----
The Pty pseudo terminal is the main interface for interacting with the command
when it's running:
- uses standard input/output for writing or reading strings
- resize the terminal
The JobController.close(io.vertx.core.Handler<java.lang.Void>) closes the shell, it will terminate all jobs in the current shell
session.
== Terminal servers
Vert.x Shell also provides bare terminal servers for those who need to write pure terminal applications.
A Term handler must be set on a term server before starting it. This handler will
handle each term when the user connects.
An AuthOptions can be set on SSHTermOptions and HttpTermOptions.
Alternatively, an AuthProvider can be set
directly on the term server before starting it.
=== SSH term
The terminal server Term handler accepts incoming terminal connections.
When a remote terminal connects, the Term can be used to interact with connected
terminal.
[source,$lang]
----
examples.Examples#sshEchoTerminal
----
The Term is also a Tty, this section explains
how to use the tty.
=== Telnet term
[source,$lang]
----
examples.Examples#telnetEchoTerminal
----
=== HTTP term
The TermServer.createHttpTermServer(io.vertx.core.Vertx) method creates an HTTP term server, built
on top of Vert.x Web using the SockJS protocol.
[source,$lang]
----
examples.Examples#httpEchoTerminal
----
An HTTP term can start its own HTTP server, or it can reuse an existing Vert.x Web Router.
The shell can be found at `/shell.html`.
[source,$lang]
----
examples.Examples#httpEchoTerminalUsingRouter
----
The later option is convenient when the HTTP shell is integrated in an existing HTTP server.
The HTTP term server by default is configured for serving:
- the `shell.html` page
- the `https://github.com/chjj/term.js/[term.js]` client library
- the `vertxshell.js` client library
The `vertxshell.js` integrates `term.js` is the client side part of the HTTP term.
It integrates `term.js` with SockJS and needs the URL of the HTTP term server endpoint:
[source,javascript]
----
window.addEventListener('load', function () {
var url = 'http://localhost/shell';
new VertxTerm(url, {
cols: 80,
rows: 24
});
});
----
Straight websockets can also be used, if so, the remote term URL should be suffixed with `/websocket`:
[source,javascript]
----
window.addEventListener('load', function () {
var url = 'ws://localhost/shell/websocket';
new VertxTerm(url, {
cols: 80,
rows: 24
});
});
----
For customization purpose these resources can be copied and customized, they are available in the Vert.x Shell
jar under the `io.vertx.ext.shell` packages.
== Command discovery
The command discovery can be used when new commands need to be added to Vert.x without an explicit registration.
For example, the _Dropwizard_ metrics service, adds specific metrics command to the shell service on the fly.
It can be achieved via the java.util.ServiceLoader of a CommandResolverFactory.
[source,java]
----
public class CustomCommands implements CommandResolverFactory {
public void resolver(Vertx vertx, Handlerresolver method is async, because the resolver may need to wait some condition before commands
are resolved.
The shell service discovery using the service loader mechanism:
.The service provider file `META-INF/services/io.vertx.ext.shell.spi.CommandResolverFactory`
[source]
----
my.CustomCommands
----
This is only valid for the ShellService. ShellServer
don't use this mechanism.
== Command pack
A command pack is a jar that provides new Vert.x Shell commands.
Such jar just need to be present on the classpath and it is discovered by Vertx. Shell.
[source,java]
----
examples.pack.CommandPackExample
----
The command pack uses command discovery mechanism, so it needs the descriptor:
.`META-INF/services/io.vertx.ext.shell.spi.CommandResolverFactory` descriptor
[source]
----
examples.pack.CommandPackExample
----Copyright © 2018 Eclipse. All rights reserved.