The Equinox OSGi console is based on Apache Felix Gogo, which provides a Unix-like shell for OSGi frameworks. The OSGi console is useful for runtime configuration and management of the framework and bundles deployed within it. It can also be useful for debugging and troubleshooting of OSGi-based applications.
The Equinox console provides:
This guide shows how to configure and use the console in a minimal OSGi runtime.
The minimal bundle set needed to start Equinox with the console on the command line is as follows:
All of these bundles are available in the Equinox SDK zip file available from the Equinox Downloads site.
Extract these bundles into a directory, then inside that directory create a configuration/config.ini file with the following content:
osgi.bundles=\ org.apache.felix.gogo.runtime,\ org.apache.felix.gogo.command,\ org.apache.felix.gogo.shell,\ org.eclipse.equinox.console
Now this minimal Equinox configuration can be started with a console available on the command
line, by passing the -console
option, for example:
$ java -jar org.eclipse.osgi_*.jar -console osgi> ss "Framework is launched." id State Bundle 0 ACTIVE org.eclipse.osgi_3.15.200.v20200214-1600 1 ACTIVE org.apache.felix.gogo.runtime_1.1.0.v20180713-1646 2 ACTIVE org.apache.felix.gogo.command_1.0.2.v20170914-1324 3 ACTIVE org.apache.felix.gogo.shell_1.1.0.v20180713-1646 4 ACTIVE org.eclipse.equinox.console_1.4.0.v20190819-1430 osgi> exit Really want to stop Equinox? (y/n; default=y)
Starting the console in a Telnet session is enabled by passing a port number with the
-console
option, for example:
$ java -jar org.eclipse.osgi_*.jar -console 1234
Once Equinox is started, connect to the Telnet session from another terminal using the port number that was specified above:
$ telnet localhost 1234 Trying ::1... Connected to localhost. Escape character is '^]'. osgi> ss "Framework is launched." id State Bundle 0 ACTIVE org.eclipse.osgi_3.15.200.v20200214-1600 1 ACTIVE org.apache.felix.gogo.runtime_1.1.0.v20180713-1646 2 ACTIVE org.apache.felix.gogo.command_1.0.2.v20170914-1324 3 ACTIVE org.apache.felix.gogo.shell_1.1.0.v20180713-1646 4 ACTIVE org.eclipse.equinox.console_1.4.0.v20190819-1430 osgi> disconnect Disconnect from console? (y/n; default=y) Connection closed by foreign host.
It is possible to set the port in the configuration/config.ini file with the addition of this line:
osgi.console=1234 # ... or ... osgi.console=localhost:1234
The osgi.console
property specifies the port (and optionally the hostname) on
which the console should listen for Telnet connections without needing to pass the -console
option at all, but if -console
is passed it will override any setting present in the
configuration/config.ini file.
To start a console session in an SSH session, a few more bundles are needed:
All of these bundles are available in the Equinox SDK zip file available from the Equinox Downloads site.
Extract these bundles into a directory, then inside that directory create a configuration/config.ini file with the following content:
osgi.bundles=\ org.apache.felix.gogo.runtime,\ org.apache.felix.gogo.command,\ org.apache.felix.gogo.shell,\ org.apache.sshd.osgi,\ org.eclipse.equinox.console,\ org.eclipse.equinox.console.jaas.fragment,\ org.eclipse.equinox.console.ssh@start,\ org.slf4j.api osgi.console.ssh=127.0.0.1:1234 osgi.console.ssh.useDefaultSecureStorage=true
Equinox uses JAAS to authenticate SSH sessions, the default login provider of which must be configured by creating a JAAS configuration file, for example by creating a file configuration/console.auth.config with the following content:
equinox_console { org.eclipse.equinox.console.jaas.SecureStorageLoginModule REQUIRED; };
Then when starting Equinox, it must be told where the JAAS configuration is by setting the
java.security.auth.login.config
system property. The default JAAS login provider stores
its credentials in a one-way encrypted store file that must be specified with the
org.eclipse.equinox.console.jaas.file
system property:
$ java -Dssh.server.keystore=configuration/hostkey.ser \ -Dorg.eclipse.equinox.console.jaas.file=configuration/store \ -Djava.security.auth.login.config=configuration/console.auth.config \ -jar org.eclipse.osgi_*.jar
The default JAAS login provider dynamically creates one default user equinox with password equinox. After logging in with these credentials for the first time, the user will be prompted to create a new account and the default account will be removed.
Once Equinox is started, connect to the SSH session from another terminal using the hostname and port specified in the configuration/config.ini file:
$ ssh -p 1234 equinox@127.0.0.1 The authenticity of host '[127.0.0.1]:1234 ([127.0.0.1]:1234)' can't be established. RSA key fingerprint is SHA256:7x3eOsDRM5lyL5vRsVREy8hIawIfqRiZ7CBnk6GkfRA. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[127.0.0.1]:1234' (RSA) to the list of known hosts. Password authentication Password: Currently the default user is the only one; since it will be deleted after first login, create a new user: username: mbooth password: Confirm password: roles: admin osgi> disconnect Disconnect from console? (y/n; default=y) Connection to 127.0.0.1 closed.
The password must be at least 8 symbols long and the username may contain alphanumerical characters, underscores and dots. On subsequent connections the user will be required to supply the newly created credentials:
$ ssh -p 1234 mbooth@127.0.0.1 Password authentication Password: osgi> disconnect Disconnect from console? (y/n; default=y) Connection to 127.0.0.1 closed.
Once logged in there are various commands for administering users. Type help at the OSGi console prompt to explore commands to perform the following functions:
Only authentication is implemented in the default JAAS login provider so by default all authenticated users have similar rights. Roles exist to allow authorization to be added in custom JAAS login providers.
A custom JAAS login provider can be used by creating a bundle fragment that extends the org.apache.sshd.osgi bundle. This fragment is used to provide or import the package of the custom login provider. This is necessary for the SSH system to be able to load the provider class.
If a custom JAAS login provider is used, then the osgi.console.ssh.useDefaultSecureStorage
property must not be set in the configuration/config.ini at all and the custom login provider
must be specified in the configuration/console.auth.config file instead of the default
entry there.
It's common to want to use public key authentication with SSH and it is possible to configure Equinox to do that instead of using JAAS authentication. First an SSH key-pair should be created as normal and then a file created that contains the list of authorized keys that Equinox should consult when users attempt to connect:
$ ssh-keygen -f ~/.ssh/equinox Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/mbooth/.ssh/equinox Your public key has been saved in /home/mbooth/.ssh/equinox.pub The key fingerprint is: SHA256:0k7MSbLLzhhzI7Gw6oSYEx8Fv5UpNHMPTdOUDj8rplQ mbooth@thinkpad-p50 The key's randomart image is: +---[RSA 3072]----+ | . + oooo.. | | + + =o.o | | + = o+ | | . + BE.+ | |. o o o.S o | |o+ + +.=o . | |=.o =.=o.. | |.o O.. | |o. . o | +----[SHA256]-----+ $ cat ~/.ssh/equinox.pub > configuration/equinox_authorized_keys
Next the following line must be removed from the configuration/config.ini file:
# Remove this line to use public key authentication # Must only be present when using the default JAAS login provider osgi.console.ssh.useDefaultSecureStorage=true
Now when starting Equinox, instead of telling it about the JAAS configuration, it must be
told about the authorized keys file by setting the ssh.server.authorized_keys
system property:
$ java -Dssh.server.keystore=configuration/hostkey.ser \ -Dssh.server.authorized_keys=configuration/equinox_authorized_keys \ -jar org.eclipse.osgi_*.jar
And that allows users to use their SSH keys instead of a username/password pair when connecting to the SSH console session:
$ ssh -i ~/.ssh/equinox -p 1234 localhost The authenticity of host '[localhost]:1234 ([127.0.0.1]:1234)' can't be established. RSA key fingerprint is SHA256:m2JKy2fRZA1aqvxHBBe+Awsgk98ryI29fH03Rg7jeHw. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[localhost]:1234' (RSA) to the list of known hosts. osgi> disconnect Disconnect from console? (y/n; default=y) Connection to localhost closed.
The authorized keys file given to Equinox will be read every time a connection is made, which allows adding and removing of keys dynamically at runtime.
Equinox also supports customizing the public key authentication mechanism. If no
specific authorized keys file is configured via system property then the OSGi service
registry will be searched for available authenticators. To enable this feature set the
ssh.custom.publickeys.auth
system property to true
.
It is possible to start Equinox console sessions over both Telnet and SSH simultaneously.
For this, both the osgi.console
and osgi.console.ssh
properties must
be specified in the configuration/config.ini file:
# Telnet session osgi.console=<hostname>:<port> # SSH session osgi.console.ssh=<hostname>:<port>
These properties specify the port on which to listen and the hostname (or IP address) to which it binds for incoming connections.
For both properties, the hostname (or IP address) is optional and may be omitted. If the hostname is omitted, then localhost is assumed. If the hostname is the same for both properties, or both hostnames are omitted then the SSH session must have a different port number to the Telnet session.
It is possible to configure Telnet and SSH console sessions through the Configuration Admin
Service instead of using the osgi.console
and osgi.console.ssh
properties. This is helpful in more complex scenarios, for example when you want to run different
instances of the console in different subsystems of the framework. In this case if the port is
configured through a system property, the same value is used for all console instances and only one
will be able to bind to the socket.
To enable this feature, the Configuration Admin bundle and it's dependencies must be added to the Equinox instance:
All of these bundles are available in the Equinox SDK zip file available from the Equinox Downloads site.
And then in the configuration/config.ini file, the osgi.console.useConfigAdmin
property must be used in place of the usual configuration properties:
# Remove these properties: #osgi.console=<hostname>:<port> #osgi.console.ssh=<hostname>:<port> # Use the Config Admin Service instead: osgi.console.useConfigAdmin=true
Now a custom bundle must be written that uses the Configuration Admin Service to configure
Telnet and SSH console sessions. The Persistent Identity (PID) for the Telnet configuration is
osgi.console.telnet
and for the SSH configuration is osgi.console.ssh
.
Both configurations have the following properties, all expecting values of type String:
host
port
enabled
The enabled
property determines if the Telnet or SSH session is to be started
at all. If the value is true
, it is started. If the value is false
,
or the property enabled
is absent, the Telnet or SSH session is not started.
The Equinox console works similarly to Unix-style shells. Multiple commands can be sent when separated by a semi-colon and the output of commands may be piped to the input of other commands. For example:
osgi> ss | grep slf4j 8 ACTIVE org.slf4j.api_1.7.2.v20121108-1250 true osgi> stop 8 ; start 8
IO redirection can be simulated with the cat and tac commands. For example:
osgi> ss | tac out.txt osgi> cat out.txt | grep slf4j 8 ACTIVE org.slf4j.api_1.7.2.v20121108-1250 true
The console also has standard command line editing features such as:
However some of these editing features are only supported when using the console via a Telnet or SSH session.
Equinox console commands have the notion of command scope. The scope is a kind of namespace that can be used, for example, to differentiate between commands with the same name, but provided by different providers.
The scope is a prefix of the command name, separated from it by a colon. When writing the
command in the console, specifying the scope is optional: A command may be written as
command_name
or scope:command_name
. If the scope is not specified,
then the command with this name from the default scope is used. If there is no such command in
the default scope, all scopes are searched.
If there is more than one command with the specified name in different, non-default scopes, it is not guaranteed which one will be actually executed. Therefore, if there are commands with the same name but in different scopes, the scope prefix must be specified explicitly with the command name to ensure that exactly the desired command is executed.
The Equinox console is now based on Apache Felix Gogo, which has a different way of implementing console commands than the traditional Equinox way. Equinox adapts these legacy commands for the Gogo-based shell and makes them available in the equinox scope. For compatibility, the default scope is the equinox scope.
Typing help (or man) at the OSGi console prompt with no arguments, the help for
all available commands is displayed. To limit the output to commands from a specific scope, the
-scope <scope_name>
parameter can be passed to the help command:
osgi> help -scope equinox close - shutdown and exit scope: equinox diag - Displays unsatisfied constraints for the specified bundle(s) scope: equinox parameters: Bundle[] IDs of bundle(s), for which to display unsatisfied constraints ...etc...
The help text for a specific command can be shown by passing a
command_name
or scope:command_name
to the help command. If
the scope is not specified, then the help text is shown for the command from the default scope
if it exists:
osgi> help headers headers - print bundle headers scope: equinox parameters: Bundle[] bundles to print headers for osgi> help felix:headers headers - display bundle headers scope: felix parameters: Bundle[] target bundles
The default help command provided by the Apache Felix Gogo shell does not provide help for the legacy Equinox commands, which are adapted by the Equinox console for the Gogo shell. For this reason the Equinox console provides its own help command in the equinox scope that delegates to the default help command whilst also providing help for legacy commands.
When using the Equinox console standalone on the command line, the exit command can be used to terminate Equinox and return to the system command prompt.
For both Telnet and SSH sessions, the session can be closed without terminating Equinox with the disconnect command.Traditionally in Equinox commands are provided by a class implementing the
org.eclipse.osgi.framework.console.CommandProvider
interface. The Equinox console
provides an adapter from this legacy type of command to the new type of command used in Gogo but it is
preferred that new commands are implemented as Gogo commands directly.
Commands for Apache Felix Gogo are plain old Java object (POJO) classes with all the commands implemented as public methods. The methods may have arbitrary arguments. These classes are registered as services, with two special properties:
osgi.command.scope
- specifies the scope of the commandosgi.command.function
- specifies the commands provided by this service;
this is a string array containing the names of public methods in the implementing class
that can be executed as commandsGogo commands also have the notion of converters and formatters.
A converter is a class which converts the arguments passed at the OSGi console prompt,
to the actual arguments that the command accepts. For example, the command may have one
argument of type Bundle
. A converter might accept a long integer and finds the
bundle with this ID. Then the command may be called with the ID of the bundle as an argument,
the converter will convert it to the corresponding Bundle
object and the command
method will be called with this object as an argument.
A formatter is a class which displays a result returned by a command method.
For more information on Gogo commands, see the Gogo documentation.
The Equinox console provides tab completion and allows implementors to provide their own custom completion providers. This feature is available only when connecting through a Telnet or SSH session. Completion is available for:
When the tab
key is typed, all possible candidates for completion for the current
word are searched. If there is only one possible completion, the current word is automatically
completed. If there is more than one option, all are displayed. The user can then cycle through the
possible completions by hitting tab
multiple times, until the desired completion
candidate is selected.
If longest common prefix of all available completion candidates is longer than the current word, then the current word is completed automatically to this prefix before choosing the final completion. For example, if the following completions are available for the word bun:
Then the current word is completed automatically to bundle and the user can continue
typing normally or, by hitting tab
again, they can cycle through the possible
completions.
A custom completer should implement the org.eclipse.equinox.console.common.Completer
interface provided by the Equinox console bundle. It has the single method getCandidates
,
which take as parameters the whole command line and the current cursor position within it, and returns
a map of completion candidates to positions in the command line at which the completion begins.