x-shell.4.4.2.source-code.index.adoc Maven / Gradle / Ivy
= Vert.x Shell
Vert.x Shell is a command line interface for the Vert.x runtime available from regular
terminals using different protocols.
Vert.x Shell provides a variety of commands for interacting live with Vert.x services.
Vert.x Shell can be extended with custom commands in any language supported by Vert.x
== Using Vert.x Shell
Vert.x Shell is a Vert.x Service and can be started programmatically via the {@link io.vertx.ext.shell.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:io.vertx:vertx-shell:${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":"properties","config":{"file":"file:auth.properties"}}}}' maven:io.vertx:vertx-shell:${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":""properties,"config":{"file":"file:auth.properties"}}}}' maven:io.vertx:vertx-shell:${maven.version}
----
You can also deploy this service inside your own verticle:
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deployTelnetService(io.vertx.core.Vertx)}
----
or
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deploySSHServiceWithProperties(io.vertx.core.Vertx)}
----
or
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deployHttpServiceWithProperties(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:io.vertx:vertx-shell:${maven.version}`
=== Programmatic service
The {@link io.vertx.ext.shell.ShellService} takes care of starting an instance of Vert.x Shell.
Starting a shell service available via SSH:
[source,$lang]
----
{@link examples.ShellExamples#runSSHServiceWithProperties(io.vertx.core.Vertx)}
----
Starting a shell service available via Telnet:
[source,$lang]
----
{@link examples.ShellExamples#runTelnetService}
----
The {@link io.vertx.ext.shell.term.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]
----
{@link examples.ShellExamples#runHttpService}
----
== Authentication
The SSH and HTTP connectors provide both authentication built on top of _vertx-auth_ with the following supported
providers:
- _properties_: provides `.properties` backend
- _ldap_: provides `LDAP` backend
- _mongo_ : MongoDB backend
- _jdbc_ : JDBC backend
- _shiro_ : (_deprecated_) provides `.properties` and _LDAP_ backend as seen in the ShellService presentation
These options can be created directly using directly corresponding class:
- {@link io.vertx.ext.auth.ldap.LdapAuthenticationOptions} for LDAP
- {@link io.vertx.ext.auth.jdbc.JDBCAuthenticationOptions} for JDBC
- {@link io.vertx.ext.auth.mongo.MongoAuthenticationOptions} for Mongo
As for external service configuration in Json, the `authOptions` uses the `provider` property to distinguish:
----
{
...
"authOptions": {
"provider":"properties",
"config": {
"file":"file:auth.properties"
}
}
...
}
----
== Telnet term configuration
Telnet terms are configured by {@link io.vertx.ext.shell.ShellServiceOptions#setTelnetOptions},
the {@link io.vertx.ext.shell.term.TelnetTermOptions} extends the {@link io.vertx.core.net.NetServerOptions} so they
have the exact same configuration.
== SSH term configuration
SSH terms are configured by {@link io.vertx.ext.shell.ShellServiceOptions#setSSHOptions}:
- {@link io.vertx.ext.shell.term.SSHTermOptions#setPort}: port
- {@link io.vertx.ext.shell.term.SSHTermOptions#setHost}: 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:
- {@link io.vertx.ext.shell.term.SSHTermOptions#setAuthOptions}: configures user authentication
The server key configuration reuses the key pair store configuration scheme provided by _Vert.x Core_:
- {@link io.vertx.ext.shell.term.SSHTermOptions#setKeyPairOptions}: set `.jks` key pair store
- {@link io.vertx.ext.shell.term.SSHTermOptions#setPfxKeyPairOptions}: set `.pfx` key pair store
- {@link io.vertx.ext.shell.term.SSHTermOptions#setPemKeyPairOptions}: set `.pem` key pair store
.Deploying the Shell Service on SSH with Mongo authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deploySSHServiceWithMongo(io.vertx.core.Vertx)}
----
.Running the Shell Service on SSH with Mongo authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#runSSHServiceWithMongo(io.vertx.core.Vertx)}
----
.Deploying the Shell Service on SSH with JDBC authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deploySSHServiceWithJDBC(io.vertx.core.Vertx)}
----
.Running the Shell Service on SSH with JDBC authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#runSSHServiceWithJDBC(io.vertx.core.Vertx)}
----
== HTTP term configuration
HTTP terms are configured by {@link io.vertx.ext.shell.ShellServiceOptions#setHttpOptions}, the http options
extends the {@link io.vertx.core.http.HttpServerOptions} so they expose the exact same configuration.
In addition there are extra options for configuring an HTTP term:
- {@link io.vertx.ext.shell.term.HttpTermOptions#setAuthOptions}: configures user authentication
- {@link io.vertx.ext.shell.term.HttpTermOptions#setSockJSHandlerOptions}: configures SockJS
- {@link io.vertx.ext.shell.term.HttpTermOptions#setSockJSPath}: the SockJS path in the router
.Deploying the Shell Service on HTTP with Mongo authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deployHttpServiceWithMongo(io.vertx.core.Vertx)}
----
.Running the Shell Service on HTTP with Mongo authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#runHTTPServiceWithMongo(io.vertx.core.Vertx)}
----
.Deploying the Shell Service on HTTP with JDBC authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#deployHttpServiceWithJDBC(io.vertx.core.Vertx)}
----
.Running the Shell Service on HTTP with JDBC authentication
[source,$lang,subs="+attributes"]
----
{@link examples.ShellExamples#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:
- {@link io.vertx.ext.shell.term.TelnetTermOptions#setIntputrc}
- {@link io.vertx.ext.shell.term.SSHTermOptions#setIntputrc}
- {@link io.vertx.ext.shell.term.HttpTermOptions#setIntputrc}
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 {@link io.vertx.ext.shell.command.CommandBuilder#command} method: the command process handler is called
by the shell when the command is executed, this handler can be set with the {@link io.vertx.ext.shell.command.CommandBuilder#processHandler}
method:
[source,$lang]
----
{@link examples.ShellExamples#helloWorld}
----
After a command is created, it needs to be registed to a {@link io.vertx.ext.shell.command.CommandRegistry}. The
command registry holds all the commands for a Vert.x instance.
A command is registered until it is unregistered with the {@link io.vertx.ext.shell.command.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 {@literal io.vertx.core.Context} when the command is registered in the
registry. Keep this in mind if you maintain state in a command.
The {@link io.vertx.ext.shell.command.CommandProcess} object can be used for interacting with the shell.
=== Command arguments
The {@link io.vertx.ext.shell.command.CommandProcess#args()} returns the command arguments:
[source,$lang]
----
{@link examples.ShellExamples#commandArgs}
----
Besides it is also possible to create commands using {@link io.vertx.core.cli.CLI 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]
----
{@link examples.ShellExamples#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]
----
{@link examples.ShellExamples#cliCommandWithHelp()}
----
When the command executes the {@link io.vertx.ext.shell.command.CommandProcess process} is provided for interacting
with the shell. A {@link io.vertx.ext.shell.command.CommandProcess} extends {@link io.vertx.ext.shell.term.Tty}
which is used for interacting with the terminal.
=== Terminal usage
==== terminal I/O
The {@link io.vertx.ext.shell.term.Tty#stdinHandler} handler is used to be notified when the terminal
receives data, e.g the user uses his keyboard:
[source,$lang]
----
{@link examples.ShellExamples#readStdin}
----
A command can use the {@link io.vertx.ext.shell.term.Tty#write} to write to the standard output.
[source,$lang]
----
{@link examples.ShellExamples#writeStdout}
----
==== Terminal size
The current terminal size can be obtained using {@link io.vertx.ext.shell.term.Tty#width()} and
{@link io.vertx.ext.shell.term.Tty#height()}.
[source,$lang]
----
{@link examples.ShellExamples#terminalSize}
----
==== Resize event
When the size of the terminal changes the {@link io.vertx.ext.shell.term.Tty#resizehandler(io.vertx.core.Handler)}
is called, the new terminal size can be obtained with {@link io.vertx.ext.shell.term.Tty#width()} and
{@link io.vertx.ext.shell.term.Tty#height()}.
[source,$lang]
----
{@link examples.ShellExamples#resizeHandlerTerminal}
----
==== Terminal type
The terminal type is useful for sending escape codes to the remote terminal: {@link io.vertx.ext.shell.term.Tty#type()}
returns the current terminal type, it can be null if the terminal has not advertised the value.
[source,$lang]
----
{@link examples.ShellExamples#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 {@link io.vertx.ext.shell.command.CommandProcess#session()}:
[source,$lang]
----
{@link examples.ShellExamples#session}
----
=== Process termination
Calling {@link io.vertx.ext.shell.command.CommandProcess#end()} ends the current process. It can be called directly
in the invocation of the command handler or any time later:
[source,$lang]
----
{@link examples.ShellExamples#asyncCommand}
----
=== Process events
A command can subscribe to a few process events.
==== Interrupt event
The {@link io.vertx.ext.shell.command.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]
----
{@link examples.ShellExamples#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 {@link io.vertx.ext.shell.command.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 {@link io.vertx.ext.shell.command.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]
----
{@link examples.ShellExamples#suspendResumeHandler}
----
==== End events
The {@link io.vertx.ext.shell.command.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]
----
{@link examples.ShellExamples#endHandler}
----
The end handler is called even when the command invokes {@link io.vertx.ext.shell.command.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 {@link io.vertx.ext.shell.command.CommandBuilder#completionHandler(io.vertx.core.Handler) completion
handler} is non blocking because the implementation may use Vert.x services, e.g the file system.
The {@link io.vertx.ext.shell.cli.Completion#lineTokens()} returns a list of {@link io.vertx.ext.shell.cli.CliToken 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 {@link io.vertx.ext.shell.cli.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 {@link io.vertx.ext.shell.cli.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 {@link io.vertx.ext.shell.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]
----
{@link examples.ShellExamples#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 {@link io.vertx.ext.shell.ShellServer#createShell}:
[source,$lang]
----
{@link examples.ShellExamples#creatingShell}
----
The main use case is running or testing a command:
[source,$lang]
----
{@link examples.ShellExamples#runningShellCommand}
----
The {@link io.vertx.ext.shell.term.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 {@link io.vertx.ext.shell.system.JobController#close} 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 {@link io.vertx.ext.shell.term.Term} handler must be set on a term server before starting it. This handler will
handle each term when the user connects.
An {@code Auth*Options} can be set on {@link io.vertx.ext.shell.term.SSHTermOptions} and {@link io.vertx.ext.shell.term.HttpTermOptions}.
Alternatively, an {@link io.vertx.ext.auth.authentication.AuthenticationProvider} can be {@link io.vertx.ext.shell.term.TermServer#authenticationProvider(io.vertx.ext.auth.authentication.AuthenticationProvider) set}
directly on the term server before starting it.
=== SSH term
The terminal server {@link io.vertx.ext.shell.term.Term} handler accepts incoming terminal connections.
When a remote terminal connects, the {@link io.vertx.ext.shell.term.Term} can be used to interact with connected
terminal.
[source,$lang]
----
{@link examples.ShellExamples#sshEchoTerminal}
----
The {@link io.vertx.ext.shell.term.Term} is also a {@link io.vertx.ext.shell.term.Tty}, this section explains
how to use the tty.
=== Telnet term
[source,$lang]
----
{@link examples.ShellExamples#telnetEchoTerminal}
----
=== HTTP term
The {@link io.vertx.ext.shell.term.TermServer#createHttpTermServer} method creates an HTTP term server, built
on top of Vert.x Web using the SockJS protocol.
[source,$lang]
----
{@link examples.ShellExamples#httpEchoTerminal}
----
An HTTP term can start its own HTTP server, or it can reuse an existing Vert.x Web {@link io.vertx.ext.web.Router}.
The shell can be found at `/shell.html`.
[source,$lang]
----
{@link examples.ShellExamples#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 {@link io.vertx.ext.shell.spi.CommandResolverFactory}.
[source,java]
----
public class CustomCommands implements CommandResolverFactory {
public void resolver(Vertx vertx, Handler> resolverHandler) {
resolverHandler.handler(() -> Arrays.asList(myCommand1, myCommand2));
}
}
----
The `resolver` 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 {@link io.vertx.ext.shell.ShellService}. {@link io.vertx.ext.shell.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]
----
{@link 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
----
© 2015 - 2024 Weber Informatics LLC | Privacy Policy