The Common Reusable SHell (CRaSH) deploys in a Java runtime and provides interactions with the JVM. Commands are written in Groovy and can be developed at runtime making the extension of the shell very easy with fast development cycle.
Running CRaSH
There are several ways to run CRaSH, as a standalone application it controls its own JVM or as an embedded service in an existing runtime like a web application or a Spring application.
Standalone
Standalone mode
The standalone mode allows you to run CRaSH from the command line directly. It provides the same functionality as the war deployment but does not require a web container as it runs its own virtual machine. The crash directory in the application contains the standalone distribution.
The bin directory /crash/bin can be added to the system path, it contains the crash.sh script that will start the standalone mode, for instance you can set it up this way:
> export PATH=/.../crash/bin:$PATH > crash.sh ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.3.0-beta14 Follow and support the project on http://www.crashub.org Welcome to jerry + ! It is 2014-01-16 16:08:34 CET now
Let’s review quickly what you can find in standalone crash:
-
The bin directory contains the crash.sh script and the standalone crash jar file
-
The conf directory contains the configuration properties crash.properties and JVM logging configuration logging.properties
-
The cmd directory contains the commands that will be available in crash by default it contains a few example commands
-
The lib directory contains the various libraries used by crash, you should place additional jar files there
Attach mode
The attach mode allows you to attach CRaSH to a JVM located on the same host with the attach API provided by the Hotspot JVM. It is the standalone mode attached to a running JVM specified by a process id. CRaSH will hook into the targetted JVM instead of the JVM started by CRaSH. Let’s see quickly an example of how to use it:
> jps 3165 RemoteMavenServer 20650 Test 20651 Jps > crash.sh 20650 ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.3.0-beta14 Follow and support the project on http://vietj.github.com/crash Welcome to jerry + ! It is 2014-01-16 16:08:34 CET now %
In this example we attached crash to the Test JVM. We obtained the Test JVM PID thanks to the jps command that belongs to the Java Platform. During this mode the commands are executed in the target JVM.
Configuration
The standalone mode relies on the org.crsh.standalone.CRaSH
class main method to configure and run the shell. The startup scripts crash.sh and crash.bar configures this class. You can tweak those scripts to your environment, let’s review the options and arguments of CRaSH
:
--cmd option
The --cmd option specifies a directory containing command source files. Such directory contains commands as .groovy files, commands can be in directories for grouping purpose. Several folders can be specified by repeating the option.
--cmd-mode option
The standalone shell search commands in folders (specified with the --cmd option and in the classpath (under the /crash/commands/ folder). The --cmd-mode option defines how to handle the classpath commands:
-
The read option value uses commands from directories and classpath.
-
The copy option value scans the classpath during the startup and copies the commands in the first command folder, then commands are used from the folders. This value requires at least one command directory to be specified for extracting the commands.
--conf option
The --conf option specifies a directory containing configuration files. Several folders can be specified by repeating the option.
--conf-mode option
The standalone shell search configuration files in folders (specified with the --conf option and in the classpath (under the /crash/ folder). The --conf-mode option defines how to handle the classpath configuration:
-
The read option value uses configuration files from directories and classpath.
-
The copy option value scans the classpath during the startup and copies the files in the first configuration folder, then configuration are used from the folders. This value requires at least one conf directory to be specified for extracting the configuration files.
--property option
The --cmd option sets and overrides a shell configuration property, the value follows the pattern a=b, for instance:
crash.sh --property crash.telnet.port=3000
--non-interactive option
The --non-interactive option disable the usage of the JVM input and output.
crash.sh --non-interactive
pid arguments
The org.crsh.standalone.CRaSH
main has an optional list of arguments that are JVM process id. When one or several JVM process id are specified, CRaSH will dynamically attach to this virtual machine and will be executed in that machine. By default the two JVM will communicate with a socket unless the non-interactive option is set.
When more than one process id is specified, the non-interactive option must be set because CRaSH will not be able to aggregate two command lines in the same terminal. |
Resource extraction
When the options --cmd-mode or --conf-mode are set to the copy, CRaSH will scan the classpath and extract the resources in the corresponding directory.
The default value of these options is copy however no copy happens unless at least one directory for extracting the resources is specified, therefore
-
The
org.crsh.standalone.CRaSH
does nothing by default -
The crash.sh or crash.bat extracts the resources in the corresponding directory as the cmd and conf directories are specified
To prevent any resource copying the value read should be used.
Embedded mode
Embedding in a web app
CRaSH can use a standard web archive to be deployed in a web container. The war file is used for its packaging capabilities and triggering the CRaSH life cycle start/stop. In this mode CRaSH has two packaging available:
-
A core war file found under deploy/core/crash.war provides the base CRaSH functionnalities
-
A gatein war file found under deploy/gatein/crash.war provides additional Java Content Repository (JCR) features but deploys only in a GateIn server (Tomcat or JBoss). It extends the core packaging and adds:
-
JCR browsing and interactions
-
SCP support for JCR import and export
-
You have to copy the crash.war in the appropriate server, regardless of the packaging used.
If you want you can embed CRaSH in your own web.xml configuration:
<web-app>
<listener>
<listener-class>org.crsh.plugin.WebPluginLifeCycle</listener-class>
</listener>
</web-app>
Embedding in Spring
CRaSH can be easily embedded and configured in a Spring configuration.
Embedding as a Spring bean
Here is an example of embedding crash:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="org.crsh.spring.SpringBootstrap">
<property name="config">
<props>
<!-- VFS configuration -->
<prop key="crash.vfs.refresh_period">1</prop>
<!-- SSH configuration -->
<prop key="crash.ssh.port">2000</prop>
<!-- Telnet configuration -->
<prop key="crash.telnet.port">5000</prop>
<!-- Authentication configuration -->
<prop key="crash.auth">simple</prop>
<prop key="crash.auth.simple.username">admin</prop>
<prop key="crash.auth.simple.password">admin</prop>
</props>
</property>
</bean>
</beans>
The configuration properties are set as properties with the config property of the SpringBootstrap
bean.
Any Spring managed beans that extend org.crsh.plugin.CRaSHPlugin
will be automatically registered as plugins in addition to those declared in META-INF/services/org.crsh.plugin.CRaSHPlugin
.
For example, the following implements a CRaSH authentication plugin that uses a JDBC DataSource managed by Spring:
package example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.sql.DataSource;
import org.crsh.auth.AuthenticationPlugin;
import org.crsh.plugin.CRaSHPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("dbCrshAuth")
public class DbCrshAuthPlugin extends CRaSHPlugin<AuthenticationPlugin>
implements AuthenticationPlugin {
@Autowired
private DataSource dataSource;
@Override
public AuthenticationPlugin getImplementation() {
return this;
}
@Override
public boolean authenticate(String username, String password)
throws Exception {
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn
.prepareStatement("SELECT COUNT(*) FROM users WHERE username = ? AND password = ?");
statement.setString(1, username);
statement.setString(2, password);
ResultSet rs = statement.executeQuery();
return rs.getInt(1) >= 1;
}
@Override
public String getName() {
return "dbCrshAuth";
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
The above code uses Spring annotation driven beans, but this works the same with beans configured in XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="example.DbCrshAuthPlugin">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Embedding in a Spring web app
In case you are embedding CRaSH in a Spring application running with a servlet container, the bean org.crsh.spring.SpringWebBootstrap
can be used instead of org.crsh.spring.SpringBootstrap
. The SpringWebBootstrap
extends the SpringBootstrap
class and adds the WEB-INF/crash directory to the command path.
An example packaging comes with the CRaSH distribution, a spring war file found under deploy/spring/crash.war provides the base CRaSH functionnalities bootstrapped by the Spring Framework. It can be used as an example for embedding CRaSH in Spring.
This example is bundled with a spring command that shows how the Spring factory or beans can be accessed within a CRaSH command.
Interacting with the shell
Shell usage
Connection
You need to connect using telnet, SSH or directly to use the shell. The last method is a special mode using the JVM input and output.
Telnet access
Telnet connection is done on port 5000:
(! 520)-> telnet localhost 5000 Trying ::1... Connected to localhost. Escape character is '^]'. ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.3.0-beta14 Follow and support the project on http://vietj.github.com/crash Welcome to julien.local + ! It is 2014-01-16 16:08:34 CET now
The bye
command disconnect from the shell.
SSH access
SSH connection is done on port 2000 with the password crash:
juliens-macbook-pro:~ julien$ ssh -p 2000 -l root localhost root@localhost's password: CRaSH {crash-version} (http://vietj.github.com/crash) Welcome to juliens-macbook-pro.local! It is {localdatetime} now. %
The bye
command disconnect from the shell.
Features
-
Line edition: the current line can be edited via left and right arrow keys
-
History: the key up and key down enable history browsing
-
Quoting: simple quotes or double quotes allow to insert blanks in command options and arguments, for instance
"old boy"
orold boy
. One quote style can quote another, like"hi, it's me"
. -
Completion: an advanced completion system is available
Command usage
Getting basic help
The help
command will display the list of known commands by the shell.
[/]% help % help Try one of these commands with the -h or --help switch: cd changes the current node commit saves changes consume collects a set of nodes cp copy a node to another env display the term env exportworkspace Export a workspace on the file system (experimental) fail Fails help provides basic help importworkspace Import a workspace from the file system (experimental) invoke Invoke a static method log logging commands ls list the content of a node man format and display the on-line manual pages mixin mixin commands mv move a node node node commands produce produce a set of nodes pwd print the current node path rm remove one or several node or a property rollback rollback changes select execute a JCR sql query setperm modify the security permissions of a JCR node sleep sleep for some time thread vm thread commands version versioning commands wait Invoke a static method ws workspace commands xpath execute a JCR xpath query
Command line usage
The basic CRaSH usage is like any shell, you just type a command with its options and arguments. However it is possible to compose commands and create powerful combinations.
Command help display
Any command help can be displayed by using the -h argument:
% ls -h usage: ls [-h | --help] [-h | --help] [-d | --depth] path [-h | --help] command usage [-h | --help] command usage [-d | --depth] Print depth path the path of the node content to list
In addition of that, commands can have a complete manual that can be displayed thanks to the man
command:
% man ls NAME ls - list the content of a node SYNOPSIS ls [-h | --help] [-h | --help] [-d | --depth] [-d | --depth] path DESCRIPTION The ls command displays the content of a node. By default it lists the content of the current node, however it also accepts a path argument that can be absolute or relative. [/]% ls / +-properties | +-jcr:primaryType: nt:unstructured | +-jcr:mixinTypes: [exo:owneable,exo:privilegeable] | +-exo:owner: '__system' | +-exo:permissions: [any read,*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administrators set_property,*:/platform/administrators remove] +-children | +-/workspace | +-/contents | +-/Users | +-/gadgets | +-/folder PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage [-d | --depth] Print depth path the path of the node content to list
Advanced command usage
A CRaSH command is able to consume and produce a stream of object, allowing complex interactions between commands where they can exchange stream of compatible objets. Most of the time, JCR nodes are the objects exchanged by the commands but any command is free to produce or consume any type.
By default a command that does not support this feature does not consume or produce anything. Such commands usually inherits from the org.crsh.command.ClassCommand
class that does not care about it. If you look at this class you will see it extends the the org.crsh.command.BaseCommand
.
More advanced commands inherits from org.crsh.command.BaseCommand
class that specifies two generic types <C>
and <P>
:
-
<C>
is the type of the object that the command consumes -
<P>
is the type of the object that the command produces
The command composition provides two operators:
-
The pipe operator
|
allows to stream a command output stream to a command input stream -
The distribution operator
+
allows to distribute an input stream to several commands and to combine the output stream of several commands into a single stream.
Connecting a <Void,Node>
command to a <Node,Void>
command through a pipe
% select * from nt:unstructed | rm
Connecting a <Void,Node>
command to two <Node,Void>
commands through a pipe
% select * from nt:unstructured | setperm -i any -a read + setperm -i any -a write
Configuration
CRaSH is configured by a set of properties, the properties are configured differently according to the mode.
Configuring the standalone or attach mode
In standalone or attach mode configuration can be in the /conf/crash.properties file or via the command line directly.
The crash.properties file does not exist by default and it is created at the first run, so you should run CRaSH at least once to extract the file:
% crash
You can also specify properties as a CRaSH command line argument with the -p option:
% crash -p crash.property_name=property_value
Configuring the web application mode
In the war file packaging, the configuration file can be found under /WEB-INF/crash/crash.properties file of the archive. Configuration can be overriden by Java Virtual Machine system properties by using the same property name.
Configuration properties
Changing SSH server key
The key can be changed by replacing the file WEB-INF/sshd/hostkey.pem. Alternatively you can configure the server to use an external file by using the crash.ssh.keypath parameter in the crash.properties. Uncomment the corresponding property and change the path to the key file.
#crash.ssh.keypath=/path/to/the/key/file
If you specify an external file, you can also configure the server to generate it for you. In this case, the generation will take place when someone first connects through SSH. The default behavior is false, i.e. not to generate.
#crash.ssh.keygen=false
Changing telnet or SSH server ports
The ports of the server are parameterized by the crash.ssh.port and crash.telnet.port parameters in the crash.properties file
# SSH configuration crash.ssh.port=2000
# Telnet configuration crash.telnet.port=5000
Removing telnet or SSH access
-
to remove the telnet access, remove the jar file in the WEB-INF/lib/crsh.connectors.telnet-1.3.0-beta14.jar.
-
to remove the SSH access, remove the jar file in the WEB-INF/lib/crsh.connectors.ssh-1.3.0-beta14.jar.
Configuring shell default message
The /WEB-INF/crash/commands/base/login.groovy file contains two closures that are evaluated each time a message is required
-
The
prompt
closure returns the prompt message -
The
welcome
closure returns the welcome message
Those closure can be customized to return different messages.
Configuring authentication
Authentication is used by the SSH server when a user authenticates. Authentication interface is pluggable and has default implementations. The authentication chapter explains how to write a custom authentication plugin, in this section we cover the configuation of the authentication.
The configuration of the authentication plugin is done via property, this is necessary because several plugins can be detected by CRaSH, and the plugin is selected via the property crash.auth that must match the authentication plugin name:
crash.auth=simple
It can also take a comma-separated list of multiple authentication plugins, allowing to mix username/password and key authentication. In this case plugins are tested in the order which they were specified:
crash.auth=simple,key
CRaSH comes out of the box with two authentication plugins.
Simple authentication
Simple authentication provides a simple username/password authentication configured with the crash.auth.simple.username and crash.auth.simple.password properties:
# Authentication configuration crash.auth=simple crash.auth.simple.username=admin crash.auth.simple.password=admin
Jaas authentation
Jaas authentication uses jaas to perform authentication configured with the crash.auth.jaas.domain property to define the jaas domain to use when performing authentication:
# Authentication configuration crash.auth=jaas crash.auth.jaas.domain=my-domain
Key authentication
Key authentication relies on a set of authorized public keys to perform authentication configured with the crash.auth.key.path property to specify the path of the keys. The property should point to a valid .pem file. Obviously only a public key is required to be in the file, although it can also contain a private key (that will not be used).
# Authentication configuration crash.auth=key crash.auth.key.path=/Users/julien/.ssh/id_dsa.pem
Connectors
Connectors
Connectors manages the connection of the client to the shell.
Web connector
The websocket provides connectivity from a web browser through WebSockets based on:
-
The jQuery Terminal Emulator Plugin
-
a browser supporting WebSockets
-
a Java web server implementing the JSR 356 API
Client setup
CRaSH.js is the client side part of the connector, it is built on top of the jQuery Terminal Emulator Plugin and uses a client/server protocol for the shell connection.
The web page embedding CRaSH.js requires a few assets:
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/jquery.mousewheel-min.js"></script>
<script src="js/jquery.terminal-0.7.12.js"></script>
<script src="js/crash.js"></script>
<link href="css/jquery.terminal.css" rel="stylesheet"/>
It can be setup in a few lines of JavaScript:
// Create web socket url
var path = window.location.pathname;
var ctx = path.substring(0, path.indexOf('/', 1));
var protocol;
if (window.location.protocol == 'http:') {
protocol = 'ws';
} else {
protocol = 'wss';
}
var url = protocol + '://' + window.location.host + ctx + '/crash';
// Connect to the server
var crash = new CRaSH($('#term_demo'), 1024, 768);
crash.connect(url);
Server setup
Currently the WebSocket server uses the JSR 356 API, the connector is bootstrapped by the org.crashub:crash.connectors.web
jar that contains an annotation based endpoint bound to the /crash uri. Therefore the full uri is prefixed by the web application context path in which the connector is deployed.
The org.crashub:crash.connectors.web
jar contains also the assets for setting up the client side exposed automatically when the jar is in the WEB-INF/lib of the web application (they are located in the META-INF/resources entry of the jar). To activate the connector the property crash.web.enabled
must be set to true
.
Developers
Developping commands
A CRaSH command is written in the Groovy language. The Groovy language provides several signifiant advantages:
-
Commands can be bare scripts or can be a class
-
Java developers can write Groovy commands without learning much of it
-
Groovy is a dynamic language and can manipulate unknown types
Each command has a corresponding Groovy file that contains a command class that will be invoked by the shell. The files are located in:
-
cmd directory for the standalone distribution
-
/WEB-INF/crash/commands directory for the web archive deployment
New commands can directly be placed in the commands directory; however they can also be placed in a sub directory of the command directory, which is useful to group commands of the same kind.
In addition of that there are two special files called login.groovy and logout.groovy that are executed upon login and logout of a user. They are useful to setup and cleanup things related to the current user session.
Commands as a script
The simplest command can be a simple script that returns a string
return "Hello World";
The out
implicit variable can be used to send a message to the console:
out.println("Hello World");
It can be even Groovier:
out << "Hello World"
Commands as a class
Class can also be used for defining a command, it provides significant advantages over scripts:
-
A command can declare options and arguments for the command
-
Sub command style (git style) can be expressed easily
When the user types a command in the sell, the command line is parsed by the cmdline framework and injected in the command class.
Let’s study a simple class command example:
import org.crsh.cli.Command;
import org.crsh.cli.Usage;
import org.crsh.cli.Option;
class date {
@Usage("show the current time")
@Command
Object main(
@Usage("the time format")
@Option(names=["f","format"])
String format) {
if (format == null)
format = "EEE MMM d HH:mm:ss z yyyy";
def date = new Date();
return date.format(format);
}
}
The command is pretty straightforward to grasp:
-
The
@Command
annotation declares themain
method as a command -
The command takes one optional
format
option declared by the@Option
annotation -
The
@Usage
annotation describes the usage of the command and its parameters
% date Thu Apr 19 15:44:05 CEST 2012
The @Usage
annotation is important because it will give a decent human description of the command
% date -h usage: date [-h | --help] [-f | --format] [-h | --help] command usage [-f | --format] the time format
Sub commands
A class can hold several commands allowing a single file to group several commands, let’s study the JDBC command structure:
@Usage("JDBC connection")
class jdbc {
@Usage("connect to database with a JDBC connection string")
@Command
public String connect(
@Usage("The username")
@Option(names=["u","username"])
String user,
@Usage("The password")
@Option(names=["p","password"])
String password,
@Usage("The extra properties")
@Option(names=["properties"])
Properties properties,
@Usage("The connection string")
@Argument
String connectionString) {
...
}
@Usage("close the current connection")
@Command
public String close() {
...
}
}
We can see that the class declares two commands connect
and close
, they are invoked this way:
% jdbc connect jdbc:derby:memory:EmbeddedDB;create=true Connected to data base : jdbc:derby:memory:EmbeddedDB;create=true % jdbc close Connection closed
Command line annotations
Let’s review the various annotations for declaring a command.
@org.crsh.cli.Command
Defines a command method, when using a mono command the method should be named main
:
public class sample {
@Command
public void main() {
...
}
}
Using this annotation automatically turns a class into a class command.
Previous versions of CRaSH required command classes to extend the org.crsh.command.CRaSHCommand class, this is not necessary anymore as the @Command annotation is enough. |
Sub commands will simply declares several methods:
public class sample {
@Command
public void sub1() {
...
}
@Command
public void sub2() {
...
}
}
@org.crsh.cli.Option
Declares an option, the names member must be specified: single letter name are turned into posix style option (single hyphen) other names are turned into GNU style option (double hyphen). Several names can specified as aliases of the same option. Option can be declared as method parameters or a class fields.
public class sample {
@Option(names = ["o", "opt1"])
private String opt1;
@Command
public void sub1(@Option(names = ["opt2"]) String opt2) {
...
}
}
> sample foo > sample -o foo > sample --opt1 foo sub1 > sample sub1 --opt2 bar > sample --opt1 foo foo sub1 --opt2 bar
@org.crsh.cli.Argument
Declares an argument, this annotation should be declares as method parameters.
public class sample {
@Command
public void sub1(@Argument String arg) {
...
}
}
> sample sub1 > sample sub1 foo
@org.crsh.cli.Required
By default a parameter is optional, the @Required
annotation can be used to force the user to specify a parameter:
public class sample {
@Command
public void sub1(@Required @Argument String arg) {
...
}
}
@org.crsh.cli.Usage
and @org.crsh.cli.Man
Those annotations are useful for documenting commands help and manual:
@Usage("sample commands")
public class sample {
@Command
@Usage("command description, begins with lower case")
@Man("Verbose descrition of the argument, it should begin with an upper case")
public void sub1(
@Usage("argument description, begins with a lower case")
@Man("Verbose description of the argument, it should begin with an upper case")
@Argument String arg) {
...
}
}
-
@Usage
specifies the usage, rather a short description -
@Man
provides the manuel, rather a verbose description
Parameter types
Option and argument parameters are represented by simple types. The string type is universal and will work with any value provided by the user, other types will require parsing.
Builtin types
CRaSH provides supports a few builtin simple types other than string:
-
Integer
type -
Boolean
type -
java.util.Properties
type -
javax.management.ObjectName
type -
Enum
types
Boolean type is special because it does not need a value when combined with options. The option declaration is enough to set the value to true:
public class sample {
@Command
public void sub1(@Option(names = ["o"]) Boolean opt) {
...
}
}
The option will be true with:
> sample sub1 -o
Providing your own type
Providing a custom type is possible, CRaSH uses the ServiceLoader
discovery mechanism to discover custom types. Custom types are implemented by a org.crsh.cli.type.ValueType
subclass and implement its parse
method:
package my;
public class CustomValueType extends ValueType<Custom> {
public CustomValueType() {
super(Custom.class); // 1
}
@Override
public <S extends Custom> S parse(Class<S> type, String s) throws Exception {
return type.cast(new Custom(s)); // 2
}
}
1 | The custom type is passed to the super class |
2 | The parse method should reutrn an instance of the type |
The parse method uses the <S> generic type because the implementation of enum types has an effective type which is a subclass of the base enum type. |
In order to make the custom type discovered by CRaSH, a file named org.crsh.cli.type.ValueType should be placed in the /META-INF/services/ directory of the jar containing the custom value type:
my.CustomValueType
Parameter multiplicity
The multiplicity is the number of values expected by a parameter, the multiplicity with simple types is always 1. The arity can also be several when the java.util.List
type is used.
public class sample {
@Command
public void sub1(@Option(names = ["o"]) List<String> opts) {
...
}
}
The option can now accept several values:
> sample sub1 -o foo -o bar
Parameter annotations: Don’t Repeat Yourself
When one or several commands uses the same parameter (option or argument), there is the opportunity to avoid repetition and define a custom annotation that can be used for declaring the parameter:
@Retention(RetentionPolicy.RUNTIME)
@Usage("A color")
@Option(names = "c")
public @interface PathOption {
}
The annotation can then be used instead for declaring an option:
public class mycommand {
@Command
public void foo(@ColorOption String color) {
...
}
@Command
public void bar(@ColorOption String color) {
...
}
}
Command context
During the execution of a command, CRaSH provides a context for interacting with it:
-
the property context is resolved to an instance of
org.crsh.command.InvocationContext
-
the invocation context class extends the
org.crsh.command.CommandContext
.
Let’s have a look at those types:
/**
* The command context provides the services for invoking a command.
*
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
*/
public interface CommandContext<P> extends Consumer<P>, InteractionContext, RuntimeContext, Closeable {
boolean isPiped();
}
The CommandContext
provides access to the shell session as a Map<String, Object>
. Session attributes can be accessed using this map, but they are also accessible as Groovy script properties. It means that writing such code will be equivalent:
context.session["foo"] = "bar"; // 1
out.println(bar); // 2
1 | Bind the session attribute foo with the value bar |
2 | The bar is resolved as an session attribute by Groovy |
The CommandContext
provides also access to the shell attributes as a Map<String, Object>
. Context attributes are useful to interact with object shared globally by the CRaSH environment:
-
When embedded in a web application context, attributes resolves to servlet context attributes.
-
When embedded in Spring context, attributes resolve to Spring objects:
-
attributes.factory returns the Spring factory
-
attributes.beans returns Spring beans, for example attribute.beans.telnet returns the telnet bean
-
-
When attached to a virtual machine, the context attributes has only a single
instrumentation
entry that is thejava.lang.instrument.Instrumentation
instance obtained when attaching to a virtual machine.
def bean = context.attributes.beans["TheBean"];
Now let’s examine the InvocationContext
that extends the CommandContext
:
public interface InvocationContext<P> extends CommandContext<P> {
/**
* Returns the writer for the output.
*
* @return the writer
*/
RenderPrintWriter getWriter();
/**
* Resolve a command invoker for the specified command line.
*
* @param s the command line
* @return the command invoker
* @throws ScriptException any script exception
* @throws IOException any io exception
*/
CommandInvoker<?, ?> resolve(String s) throws ScriptException, IOException;
}
The PrintWriter
object is the command output, it can be used also via the out property in Groovy scripts:
context.writer.print("Hello"); // 1
out.print("hello"); // 2
1 | Printing using the context writer |
2 | Printing using the out |
The readLine
method can be used to get interactive information from the user during the execution of a command.
def age = context.readLine("How old are you?", false);
Finally the isPiped
, consume
and produce
methods are used when writing commands that exchange objects via the pipe mechanism.
Adding style
CRaSH adds (since version 1.1) the support for colored text and text decoration. Each portion of text printed has three style attributes:
-
Decoration: bold, underline or blink, as the
org.crsh.text.Decoration
enum. -
Foreground color.
-
Background color.
Available colors are grouped as the org.crsh.text.Color
enum:
|
|
Decoration and colors can be applied with overloaded print
and println
methods provided by the ShellPrinterWriter
. This printer is available as the implicit out attribute or thanks to the context.getWriter()
method.
out.println("hello", red); // 1
out.println("hello", red, blue); // 2
out.println("hello", underline, red, blue); // 3
1 | Print hello in red color |
2 | Print hello in red with a red blue |
3 | Print hello in red underlined with a red blue |
The combination of the decoration, background and foreground colors is a style represented by the org.crsh.text.Style
object. Styles can be used like decoration and colors:
out.println("hello", style(red)); // 1
out.println("hello", style(red, blue)); // 2
out.println("hello", style(underline, red, blue)); // 3
1 | Print hello in red color |
2 | Print hello in red with a red blue |
3 | Print hello in red underlined with a red blue |
When using the print methods, the style will be used for the currently printed object. It is possible to change the style permanently (until it is reset) using Groovy leftshift operator: <<
By default the <<
operator prints output on the console. The ShellPrintWriter
overrides the operator to work with color, decoration and styles:
out << red // 1
out << underline // 2
out << "hello" // 3
out << reset; // 4
1 | Set red foreground color |
2 | Set underline |
3 | Print hello in underlined red |
4 | Reset style |
Operators can also be combined on the same line providing a more compact syntax:
out << red << underline << "hello" << reset
out << style(underline, red, blue) << "hello" << reset
Throughout the examples we have used decoration, color and styles. CRaSH automatically imports those classes so they can be used out of the box in any CRaSH command without requiring prior import. |
Inter command API
In this section we study how a command can reuse existing commands. Here is an example
jdbc.connect username:root, password:crash, "jdbc:derby:memory:EmbeddedDB;create=true"
jdbc.execute "create table derbyDB(num int, addr varchar(40))"
jdbc.execute "insert into derbyDB values (1956,'Webster St.')"
jdbc.execute "insert into derbyDB values (1910,'Union St.')"
jdbc.execute "select * from derbyDb"
jdbc.close
This script is written in Groovy and use Groovy DSL capabilities, let’s study the first statement:
-
the
jdbc.connect
statement can be decomposed into two steps-
the
jdbc
is resolved as the command itself -
the
connect
invokes the connect command
-
-
the
username
andpassword
are considered as command options -
the SQL statement
"jdbc:derby:memory:EmbeddedDB;create=true"
is the main argument of the command
It is equivalent to the shell command:
% jdbc connect --username root --password crash jdbc:derby:memory:EmbeddedDB;create=true
The rest of the script is fairly easy to understand, here is the output of the script execution:
% dbscript Connected to data base : jdbc:derby:memory:EmbeddedDB;create=true Query executed successfully Query executed successfully Query executed successfully NUM ADDR 1956 Webster St. 1910 Union St. Connection closed
Groovy guide
This section teaches about advanced Groovy usage in CRaSH.
The Groovy REPL
The Read–eval–print loop known as REPL is the interactive evaluation of CRaSH. Since CRaSH 1.3, the REPL evaluation can be switch to the Groovy language.
The Groovy REPL is switched via the repl directive:
% repl groovy Using repl groovy
Evaluating commands
Simple commands are invoked by calling them just like a function:
% repl groovy Using repl groovy % help() Try one of these commands with the -h or --help switch: NAME DESCRIPTION cls clear screen egrep search file(s) for lines that match a pattern env display the term env ...
Typing a command name evalutes to a Groovy closure, allowing to call the command just like a function.
% cmd = help help % cmd()
Sub commands can be invoked by resolving a new closure from the initial command:
% thread.ls()
Which is equivalent to
% cmd = thread thread % cmd2 = cmd.ls thread.ls % cmd2() ...
Passing options and arguments
Command options and command arguments are passed as invocation parameters:
-
options are used as a map or named parameters
-
arguments are the other invocation parameters
% thread(h:true) usage: thread COMMAND [ARGS] The most commonly used thread commands are: stop stop vm threads interrupt interrupt vm threads top thread top ls list the vm threads dump dump vm threads % thread.ls(h:true) usage: thread ls [-n | --name] [-g | --group] [-s | --state] [-n | --name] Filter the threads with a glob expression on their name [-g | --group] Filter the threads with a glob expression on their group [-s | --state] Filter the threads by their status (new,runnable,blocked,waiting,timed_waiting,terminated)
% system.propget("file.encoding") UTF-8
Passing options and arguments at the same time is easy to do, however the options should be the first method parameters:
% log.send(m:"hello", "the.category") Aug 12, 2013 11:22:50 AM org.codehaus.groovy.reflection.CachedMethod invoke INFO: hello
Options and arguments binding
Options and arguments can also be bound on a closure:
% (thread.ls { h=true })() ... % cmd = thread.ls { h=true } thread.ls { h=true } % cmd(); ...
% (system.propget { "file.encoding" })() ... % cmd = system.propget { "file.encoding" } system.propget { ["file.encoding"] } % cmd(); ...
Of course it is possible to bind options and arguments too, the arguments needs to be passed as last parameters:
% (log.send { m="hello"; "the category" })() ... % cmd = log.send { m="hello"; "the category" } log.send { m="hello"; ["the category"] } % cmd() ...
Command pipeline
The object pipeline can be used in the Groovy REPL using the |
(pipe) operator. When a command closure is combined with a pipe, it returns a new closure that will invoke the pipeline construction.
% (system.propls | egrep { "java.*" })() java.runtime.name Java(TM) SE Runtime Environment java.vm.version 23.7-b01 java.vm.vendor Oracle Corporation ... % cmd = system.propls | egrep { "java.*" } system.propls | egrep { ["java.*"] } % cmd() ...
A pipeline can also contain Groovy closures in addition of the existing commands
% (thread.ls | { Thread thread -> [id:thread.id, name:thread.name] })() id name ------------------------------------ 2 Reference Handler 3 Finalizer ... % cmd = thread.ls | { Thread thread -> [id:thread.id, name:thread.name] } thread.ls | Script14$_run_closure1@47da4d19 % cmd() ...
In this example, the closure takes the threads argument and transforms them to a serie of maps that are displayed then as a table by CRaSH.
Extending CRaSH
Embedding CRaSH
The chapter Running CRaSH explains how to run CRaSH as a standalone or an embedded service. We will study in this section the technical aspect of running application and show how CRaSH can be embedded in specific environments.
The root class for reusing CRaSH is the org.crsh.plugin.PluginLifeCycle
class. This class is abstract and it cannot be used directly, instead it should be subclasses for providing specific behavior for running CRaSH. There are several subclasses using it:
-
The standalone bootstrap with the
org.crsh.standalone.Bootstrap
class : designed for using CRaSH with a real file system (i.ejava.io.File
). It defines a specific layout for locating resources (libraries, configuration and commands). -
The embedded approaches
-
org.crsh.plugin.WebPluginLifeCycle
: uses ajavax.servlet.ServletContext
-
org.crsh.spring.SpringBootstrap
: embeds CRaSH as a Spring bean -
org.crsh.spring.SpringWebBootstrap
: extends theSpringBootstrap
and uses the existingServletContext
-
Standalone bootstrap
The org.crsh.standalone.Bootstrap
class is a generic class that can be used to embed the shell in your Java programs Its usage is quite straighforward and configurable. The bootstrap is a coarse grained approach and it needs a bit of configuration for running:
-
The
baseLoader
properties is thejava.lang.ClassLoader
used by CRaSH for loading plugins, resources or command sources (under the /crash/commands/ path. This property is not modifiable and must be provided when the bootstrap is instantiated. -
The
config
properties provides the contextual properties used by CRaSH configuration such as crash.vfs.refresh_period -
The
attributes
property provides the contextual attributes used by CRaSH available at runtime via theorg.crsh.command.CommandContext
, it is useful for providing objects to commands in a similar fashion to servlet context attributes -
The
cmdPath
property is a list ofjava.io.File
scanned by CRaSH for loading additional commands -
The
confPath
property is a list ofjava.io.File
scanned by CRaSH for loading configuration files
Let’s see an example on how to use it
Standalone CRaSH
The standalone shell is a Java class configurable and runnable from the command line that is used by the standalone distribution. It is built upon the Standalone bootstrap.
Pluggable authentication
Creating a custom authentication mechanism is done by implementing a CRaSH plugin that provides an implementation of the AuthenticationPlugin
interface. Let’s study the simple authentication plugin implementation.
The AuthenticationPlugin
is the interface to implement in order to integrate CRaSH with an authentication mechanism:
import java.util.Collections;
import java.util.List;
/**
* The authentication plugin.
*
* @param <C> the credential parameter type
*/
public interface AuthenticationPlugin<C> {
/** The authentication plugin to use. */
PropertyDescriptor<List> AUTH = PropertyDescriptor.create("auth", Collections.emptyList(), "The authentication plugin");
/**
* The plugin that never authenticates, returns the name value <code>null</code>.
*/
AuthenticationPlugin<Object> NULL = new AuthenticationPlugin<Object>() {
public Class<Object> getCredentialType() {
return Object.class;
}
public String getName() {
return "null";
}
public boolean authenticate(String username, Object password) throws Exception {
return false;
}
};
/**
* Returns the authentication plugin name.
*
* @return the plugin name
*/
String getName();
/**
* Returns the credential type.
*
* @return the credential type
*/
Class<C> getCredentialType();
/**
* Returns true if the user is authentified by its username and credential.
*
* @param username the username
* @param credential the credential
* @return true if authentication succeeded
* @throws Exception any exception that would prevent authentication to happen
*/
boolean authenticate(String username, C credential) throws Exception;
}
The integration as a CRaSH plugin mandates to extend the class CRaSHPlugin
with the generic type AuthenticationPlugin
:
public class SimpleAuthenticationPlugin extends
CRaSHPlugin<AuthenticationPlugin> implements
AuthenticationPlugin {
@Override
public AuthenticationPlugin getImplementation() {
return this;
}
public String getName() {
return "simple";
}
...
}
-
The
getName()
method returns the simple value that matchs the crash.auth configuration property -
The
getImplementation()
method returns the object that implements theAuthenticationPlugin
class, this method is implemented from theCRaSHPlugin
abstract class, but in our case it simply returnsthis
becauseSimpleAuthenticationPlugin
is directly the implementation class.
Now let’s study how the plugin retrieves the configuration properties crash.auth.simple.username
and crash.auth.simple.password
:
public class SimpleAuthenticationPlugin extends
CRaSHPlugin<AuthenticationPlugin> implements
AuthenticationPlugin {
/** The username. */
public static final PropertyDescriptor<String> SIMPLE_USERNAME =
PropertyDescriptor.create(
"auth.simple.username",
"admin",
"The username");
/** The password. */
public static final PropertyDescriptor<String> SIMPLE_PASSWORD =
PropertyDescriptor.create(
"auth.simple.password",
"admin",
"The password",
true);
@Override
protected Iterable<PropertyDescriptor<?>> createConfigurationCapabilities() {
return Arrays.<PropertyDescriptor<?>>asList(
SIMPLE_USERNAME,
SIMPLE_PASSWORD);
}
@Override
public void init() {
PluginContext context = getContext();
this.username = context.getProperty(SIMPLE_USERNAME);
this.password = context.getProperty(SIMPLE_PASSWORD);
}
...
}
-
The
createConfigurationCapabilities()
method returns the constantsSIMPLE_USERNAME
andSIMPLE_PASSWORD
that defines the configuration properties that the plugin uses -
The
init()
method is invoked by CRaSH before the plugin will be used, at this moment, the configuration properties are retrieved from the plugin context with the methodgetContext()
available in theCRaSHPlugin
base class
Finally the plugin needs to provide the authenticate()
method that implement the authentication logic:
public boolean authenticate(String username, String password)
throws Exception {
return this.username != null &&
this.password != null &&
this.username.equals(username) &&
this.password.equals(password);
}
The logic is straightforward with an equality check of the username and password.
Last but not least we must declare our plugin to make it recognized by CRaSH, this is achieved thanks to the java.util.ServiceLoader
class. CRaSH uses the ServiceLoader
for loading plugins and the loader needs a file to be present in the jar file containing the class under the name META-INF/services/org.crsh.plugin.CRaSHPlugin
containing the class name of the plugin:
org.crsh.auth.SimpleAuthenticationPlugin
When all of this is done, the plugin and its service loader descriptor must be packaged in a jar file and available on the classpath of CRaSH.
You can learn more about the java.util.ServiceLoader by looking at the online javadoc. |
Mail plugin
The mail plugin configures an email client for CRaSH. This email client can be used as a service or via the mail
command.
Deployment
The plugin consist of two jars:
-
the JavaMail jar
mail-1.4.jar
-
the plugin jar
crash.plugins.mail-1.3.0-beta14.jar
when the two jars are present in the classpath of CRaSH, they will be detected and the plugin will be present.
Configuration
Configuration is done with CRaSH properties:
crash.mail.smtp.host=smtp.gmail.com crash.mail.smtp.port=587 crash.mail.smtp.secure=tls crash.mail.smtp.username=admin crash.mail.smtp.password=admin crash.mail.smtp.from=admin@mydomain.org crash.mail.debug=false
The configuration is pretty obvious and follow the usual JavaMail configuration properties.
Mail command
The mail command can be used to send emails. The command consumes a stream of objects and render them to text before sending the email.
% thread ls | thread dump | mail -s "The thread dump" admin@foo.com
Cron plugin
CRaSH provides a cron plugin for scheduling tasks, the plugin is a thin wrapper of the cron4j library.
Deployment
The plugin consist of two jars:
-
the cron4j jar
cron4j-2.2.5.jar
-
the plugin jar
crash.plugins.cron-1.3.0-beta14.jar
when the two jars are present in the classpath of CRaSH, they will be detected and the plugin will be present.
Configuration file
The plugin is configured mainly through the crontab
configuration file. This file looks pretty much like any other crontab configuration file it consists of two parts:
-
a scheduling pattern, for instance
* * * * *
, this is documented in the cron4j library -
a command line to execute
5 * * * * thread ls | thread dump | mail -s "the threads" -b admin@gmail.com
JCR plugin
The CRaSH JCR extension allow to connect and interract with Java Content Repository implementations.
SCP usage
Secure copy can be used to import or export content. The username/password prompted by the SSH server will be used for authentication against the repository when the import or the export is performed.
Export a JCR node
The following command will export the node /gadgets in the repository portal-system of the portal container portal:
scp -P 2000 root@localhost:portal:portal-system:/production/app:gadgets gadgets.xml
The node will be exported as app_gadgets.xml.
Note that the portal container name is used for GateIn. If you do omit it, then the root container will be used.
Hey, I want to contribute!
Drop me an email. You can find my email on http://www.julienviet.com. Any kind of help is welcome.
Appendix A: Commands reference
help
NAME help - provides basic help SYNOPSIS help [-h | --help] PARAMETERS [-h | --help] Display this help message
repl
NAME repl - list the repl or change the current repl SYNOPSIS repl [-h | --help] arg PARAMETERS [-h | --help] Display this help message arg the optional repl name
cd
NAME cd - changes the current node SYNOPSIS cd [-h | --help] path DESCRIPTION The cd command changes the current node path. The command used with no argument changes to the root node. A relative or absolute path argument can be provided to specify a new current node path. [/]% cd /gadgets [/gadgets]% cd /gadgets [/gadgets]% cd [/]% PARAMETERS [-h | --help] Display this help message path The new path that will change the current node navigation
commit
NAME commit - saves changes SYNOPSIS commit [-h | --help] path DESCRIPTION Saves the changes done to the current session. A node can be provided to save the state of the this nodes and its descendants only. PARAMETERS [-h | --help] Display this help message path The path of the node to commit
cp
NAME cp - copy a node to another SYNOPSIS cp [-h | --help] source target DESCRIPTION The cp command copies a node to a target location in the JCR tree. [/registry]% cp foo bar PARAMETERS [-h | --help] Display this help message source The path of the source node to copy target The path of the target node to be copied
dasboard
NAME dasboard - a monitoring dashboard SYNOPSIS dasboard [-h | --help] PARAMETERS [-h | --help] Display this help message
egrep
NAME egrep - search file(s) for lines that match a pattern SYNOPSIS egrep [-h | --help] pattern PARAMETERS [-h | --help] Display this help message pattern the search pattern
env
NAME env - display the term env SYNOPSIS env [-h | --help] PARAMETERS [-h | --help] Display this help message
filter
NAME filter - a filter for a stream of map SYNOPSIS filter [-h | --help] [-p | --pattern] PARAMETERS [-h | --help] Display this help message [-p | --pattern] format <key>:<value>
java
NAME java type - print information about a java type SYNOPSIS java [-h | --help] type name PARAMETERS [-h | --help] Display this help message name The full qualified type name
jdbc
jdbc props
NAME jdbc props - show the database properties SYNOPSIS jdbc [-h | --help] props PARAMETERS [-h | --help] Display this help message
jdbc close
NAME jdbc close - close the current connection SYNOPSIS jdbc [-h | --help] close PARAMETERS [-h | --help] Display this help message
jdbc table
NAME jdbc table - describe the tables SYNOPSIS jdbc [-h | --help] table ... tableNames PARAMETERS [-h | --help] Display this help message ... tableNames the table names
jdbc open
NAME jdbc open - open a connection from JNDI bound datasource SYNOPSIS jdbc [-h | --help] open globalName PARAMETERS [-h | --help] Display this help message globalName The datasource JNDI name
jdbc connect
NAME jdbc connect - connect to database with a JDBC connection string SYNOPSIS jdbc [-h | --help] connect [-u | --username] [-p | --password] [--properties] connectionString PARAMETERS [-h | --help] Display this help message [-u | --username] The username [-p | --password] The password [--properties] The extra properties connectionString The connection string
jdbc info
NAME jdbc info - describe the database SYNOPSIS jdbc [-h | --help] info PARAMETERS [-h | --help] Display this help message
jdbc select
NAME jdbc select - select SQL statement SYNOPSIS jdbc [-h | --help] select ... statement PARAMETERS [-h | --help] Display this help message ... statement The statement
jmx
jmx get
NAME jmx get - get attributes of an MBean SYNOPSIS jmx [-h | --help] get ... arg PARAMETERS [-h | --help] Display this help message ... arg
jndi
NAME jndi find - List JNDI resources SYNOPSIS jndi [-h | --help] find [-f | --filter] [-n | --name] [-v | --verbose] [-d | --datasources] [-e | --emf] [-m | --mail] PARAMETERS [-h | --help] Display this help message [-f | --filter] Filter displayed resources using FQN type' [-n | --name] Filter displayed resources using name' [-v | --verbose] Display resource type' [-d | --datasources] Apply a filter on 'javax.sql.DataSource' [-e | --emf] Apply a filter on 'javax.persistence.EntityManagerFactory' [-m | --mail] Apply a filter on 'javax.mail.Session'
jpa
jpa close
NAME jpa close - Close the current JPA session SYNOPSIS jpa [-h | --help] close PARAMETERS [-h | --help] Display this help message
jpa open
NAME jpa open - Open a JPA session SYNOPSIS jpa [-h | --help] open jndiName PARAMETERS [-h | --help] Display this help message jndiName
jpa entity
NAME jpa entity - Display JPA entity SYNOPSIS jpa [-h | --help] entity name PARAMETERS [-h | --help] Display this help message name
jvm
jvm gc
NAME jvm gc - Show JVM garbage collection SYNOPSIS jvm [-h | --help] gc PARAMETERS [-h | --help] Display this help message
jvm system
NAME jvm system - Show JVM operating system SYNOPSIS jvm [-h | --help] system PARAMETERS [-h | --help] Display this help message
jvm heap
NAME jvm heap - Show JVM memory heap SYNOPSIS jvm [-h | --help] heap PARAMETERS [-h | --help] Display this help message
jvm top
NAME jvm top SYNOPSIS jvm [-h | --help] top PARAMETERS [-h | --help] Display this help message
jvm pool
NAME jvm pool - Show JVM memory pool SYNOPSIS jvm [-h | --help] pool ... pools PARAMETERS [-h | --help] Display this help message ... pools
jvm runtime
NAME jvm runtime - Show JVM runtime SYNOPSIS jvm [-h | --help] runtime PARAMETERS [-h | --help] Display this help message
jvm classloading
NAME jvm classloading - Show JVM classloding SYNOPSIS jvm [-h | --help] classloading PARAMETERS [-h | --help] Display this help message
jvm compilation
NAME jvm compilation - Show JVM compilation SYNOPSIS jvm [-h | --help] compilation PARAMETERS [-h | --help] Display this help message
log
log add
NAME log add - create one or several loggers SYNOPSIS log [-h | --help] add ... name PARAMETERS [-h | --help] Display this help message ... name The name of the logger
log set
NAME log set - configures the level of one of several loggers SYNOPSIS log [-h | --help] set [-l | --level] ... name DESCRIPTION The set command sets the level of a logger. One or several logger names can be specified as arguments and the -l option specify the level among the trace, debug, info, warn and error levels. When no level is specified, the level is cleared and the level will be inherited from its ancestors. % logset -l trace foo % logset foo The logger name can be omitted and instead stream of logger can be consumed as it is a <Logger,Void> command. The following set the level warn on all the available loggers: % log ls | log set -l warn PARAMETERS [-h | --help] Display this help message [-l | --level] The logger level to assign among {trace, debug, info, warn, error} ... name The name of the logger
log ls
NAME log ls - list the available loggers SYNOPSIS log [-h | --help] ls [-f | --filter] DESCRIPTION The logls command list all the available loggers., for instance: % logls org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/].[default] org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/eXoGadgetServer].[concat] org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dashboard].[jsp] ... The -f switch provides filtering with a Java regular expression % logls -f javax.* javax.management.mbeanserver javax.management.modelmbean The logls command is a <Void,Logger> command, therefore any logger produced can be consumed. PARAMETERS [-h | --help] Display this help message [-f | --filter] A regular expressions used to filter the loggers
log send
NAME log send - send a message to a logger SYNOPSIS log [-h | --help] send [-m | --message] [-l | --level] name DESCRIPTION The send command log one or several loggers with a specified message. For instance the following impersonates the javax.management.mbeanserver class and send a message on its own logger. #% log send -m hello javax.management.mbeanserver Send is a <Logger, Void> command, it can log messages to consumed log objects: % log ls | log send -m hello -l warn PARAMETERS [-h | --help] Display this help message [-m | --message] The message to log [-l | --level] The logger level to assign among {trace, debug, info, warn, error} name The name of the logger
ls
NAME ls - list the content of a node SYNOPSIS ls [-h | --help] [-d | --depth] path DESCRIPTION The ls command displays the content of a node. By default it lists the content of the current node, however it also accepts a path argument that can be absolute or relative. [/]% ls / +-properties | +-jcr:primaryType: nt:unstructured | +-jcr:mixinTypes: [exo:owneable,exo:privilegeable] | +-exo:owner: '__system' | +-exo:permissions: [any read,*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administrators set_property,*:/platform/administrators remove] +-children | +-/workspace | +-/contents | +-/Users | +-/gadgets | +-/folder PARAMETERS [-h | --help] Display this help message [-d | --depth] The depth of the printed tree path The path of the node content to list
man
NAME man - format and display the on-line manual pages SYNOPSIS man [-h | --help] command PARAMETERS [-h | --help] Display this help message command the command
mixin
mixin add
NAME mixin add - add a mixin to one or several nodes SYNOPSIS mixin [-h | --help] add mixin ... paths DESCRIPTION The add command addds a mixin to one or several nodes, this command is a <Node,Void> command, and can add a mixin from an incoming node stream, for instance: [/]% select * from mynode | mixin add mix:versionable PARAMETERS [-h | --help] Display this help message mixin the mixin name to add ... paths the paths of the node receiving the mixin
mixin remove
NAME mixin remove - removes a mixin from one or several nodes SYNOPSIS mixin [-h | --help] remove mixin ... paths DESCRIPTION The remove command removes a mixin from one or several nodes, this command is a <Node,Void> command, and can remove a mixin from an incoming node stream, for instance: [/]% select * from mynode | mixin remove mix:versionable PARAMETERS [-h | --help] Display this help message mixin the mixin name to remove ... paths the paths of the node receiving the mixin
mv
NAME mv - move a node SYNOPSIS mv [-h | --help] source target DESCRIPTION The mv command can move a node to a target location in the JCR tree. It can be used also to rename a node. The mv command is a <Node,Node> command consuming a stream of node to move them and producing nodes that were moved. [/registry]% mv Registry Registry2 PARAMETERS [-h | --help] Display this help message source The path of the source node to move, absolute or relative target The destination path absolute or relative
node
node add
NAME node add - creates one or several nodes SYNOPSIS node [-h | --help] add [-t | --type] ... paths DESCRIPTION The addnode command creates one or several nodes. The command takes at least one node as argument, but it can take more. Each path can be either absolute or relative, relative path creates nodes relative to the current node. By default the node type is the default repository node type, but the option -t can be used to specify another one. [/registry]% addnode foo Node /foo created [/registry]% addnode -t nt:file bar juu Node /bar /juu created The addnode command is a <Void,Node> command that produces all the nodes that were created. PARAMETERS [-h | --help] Display this help message [-t | --type] The name of the primary node type to create. ... paths The paths of the new node to be created, the paths can either be absolute or relative.
node set
NAME node set - set a property on the current node SYNOPSIS node [-h | --help] set [-t | --type] propertyName propertyValue DESCRIPTION The set command updates the property of a node. Create or destroy property foo with the value bar on the root node: [/]% set foo bar Property created Update the existing foo property: [/]% set foo juu When a property is created and does not have a property descriptor that constraint its type, you can specify it with the -t option [/]% set -t LONG long_property 3 Remove a property [/]% set foo set is a <Node,Void> command updating the property of the consumed node stream. PARAMETERS [-h | --help] Display this help message [-t | --type] The property type to use when it cannot be inferred propertyName The name of the property to alter propertyValue The new value of the property
node import
NAME node import - imports a node from an nt file SYNOPSIS node [-h | --help] import source target DESCRIPTION Imports a node from an nt:file node located in the workspace: [/]% importnode /gadgets.xml / Node imported PARAMETERS [-h | --help] Display this help message source The path of the imported nt:file node target The path of the parent imported node
node export
NAME node export - export a node to an nt file SYNOPSIS node [-h | --help] export source target DESCRIPTION Exports a node as an nt file in the same workspace: [/]% node export gadgets /gadgets.xml The node has been exported PARAMETERS [-h | --help] Display this help message source The path of the exported node target The path of the exported nt:file node
pwd
NAME pwd - print the current node path SYNOPSIS pwd [-h | --help] DESCRIPTION The pwd command prints the current node path, the current node is produced by this command. [/gadgets]% pwd /gadgets PARAMETERS [-h | --help] Display this help message
repo
repo info
NAME repo info - show info about the current repository SYNOPSIS repo [-h | --help] info DESCRIPTION The info command print the descriptor of the current repository. PARAMETERS [-h | --help] Display this help message
repo ls
NAME repo ls - list the available repository plugins SYNOPSIS repo [-h | --help] ls DESCRIPTION The ls command print the available repository plugins. PARAMETERS [-h | --help] Display this help message
repo use
NAME repo use - changes the current repository SYNOPSIS repo [-h | --help] use parameters DESCRIPTION The use command changes the current repository used by for JCR commands. The command accepts a set of properties as main command argument that will be used to select a repository: % repo use parameterName=parameterValue;nextParameterName=nextParameterValue The parameters is specific to JCR plugin implementations, more details can be found thanks to the ls command. PARAMETERS [-h | --help] Display this help message parameters The parameters used to instantiate the repository to be used in this session
rm
NAME rm - remove one or several node or a property SYNOPSIS rm [-h | --help] ... paths DESCRIPTION The rm command removes a node or property specified by its path either absolute or relative. This operation is executed against the JCR session, meaning that it will not be effective until it is commited to the JCR server. [/]% rm foo Node /foo removed It is possible to specify several nodes. [/]% rm foo bar Node /foo /bar removed rm is a <Node,Void> command removing all the consumed nodes. PARAMETERS [-h | --help] Display this help message ... paths The paths of the node to remove
rollback
NAME rollback - rollback changes SYNOPSIS rollback [-h | --help] path DESCRIPTION Rollbacks the changes of the current session. A node can be provided to rollback the state of the this nodes and its descendants only. PARAMETERS [-h | --help] Display this help message path the path to rollback
select
NAME select - execute a JCR sql query SYNOPSIS select [-h | --help] [-o | --offset] [-l | --limit] [-a | --all] ... query DESCRIPTION Queries in SQL format are possible via the ##select## command. You can write a query with the same syntax defined by the specification and add options to control the number of results returned. By default the number of nodes is limited to 5 results: [/]% select * from nt:base The query matched 1114 nodes +-/ | +-properties | | +-jcr:primaryType: nt:unstructured | | +-jcr:mixinTypes: [exo:owneable,exo:privilegeable] | | +-exo:owner: '__system' | | +-exo:permissions: [any read,*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administratorsset_property,*:/platform/administrators remove] +-/workspace | +-properties | | +-jcr:primaryType: mop:workspace | | +-jcr:uuid: 'a69f226ec0a80002007ca83e5845cdac' ... Display 20 nodes from the offset 10: [/]% select -o 10 -l 20 * from nt:base The query matched 1114 nodes ... It is possible also to remove the limit of displayed nodes with the -a option (you should use this option with care) : [/]% select -a * from nt:base The query matched 1114 nodes ... select is a <Void,Node> command producing all the matched nodes. PARAMETERS [-h | --help] Display this help message [-o | --offset] The offset of the first node to display [-l | --limit] The number of nodes displayed, by default this value is equals to 5 [-a | --all] Display all the results by ignoring the limit argument, this should be used with care for large result set ... query The query, as is
setperm
NAME setperm - modify the security permissions of a JCR node SYNOPSIS setperm [-i | --identity] [-a | --add] [-r | --remove] [-h | --help] ... paths DESCRIPTION The setperm commands configures the security of a node based on (see eXo JCR access control at http://wiki.exoplatform.com/xwiki/bin/view/JCR/Access%20Control). When a node is protected by access control, it owns a mixin named exo:privilegeable that contains a exo:permissions property, for instance: [/production]% ls /production +-properties | +-jcr:primaryType: nt:unstructured | +-jcr:mixinTypes: [exo:privilegeable] | +-exo:permissions: [*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administrators set_property,*:/platform/administrators remove] +-children | +-/production/app:gadgets | +-/production/app:applications | +-/production/mop:workspace You can alter the node permission list with the setperm command: [/production]% setperm -i *:/platform/mygroup -a read -a add_node / Node /production updated to [read,add_node] You can also remove a permission by using the -r option. [/production]% setperm -i *:/platform/mygroup -r add_node / Node /production updated to [read] The setperm command will add automatically the exo:privilegeable mixin on the node when it is missing. The setperm is a <Node,Void> command altering the security of the consumed node stream. PARAMETERS [-i | --identity] the identity [-a | --add] the permissions to use [-r | --remove] the permissions to remove [-h | --help] Display this help message ... paths The node path list to secure
shell
sleep
NAME sleep - sleep for some time SYNOPSIS sleep [-h | --help] time PARAMETERS [-h | --help] Display this help message time sleep time in seconds
sort
NAME sort - sort a map SYNOPSIS sort [-h | --help] [-f | --fields] PARAMETERS [-h | --help] Display this help message [-f | --fields] Filed used to sort
system
system gc
NAME system gc - call garbage collector SYNOPSIS system [-h | --help] gc PARAMETERS [-h | --help] Display this help message
system propset
NAME system propset - set a system property SYNOPSIS system [-h | --help] propset name value PARAMETERS [-h | --help] Display this help message name The name of the property value The value of the property
system propls
NAME system propls - list the vm system properties SYNOPSIS system [-h | --help] propls [-f | --filter] PARAMETERS [-h | --help] Display this help message [-f | --filter] filter the property with a regular expression on their name
system propget
NAME system propget - get a system property SYNOPSIS system [-h | --help] propget name PARAMETERS [-h | --help] Display this help message name The name of the property
system proprm
NAME system proprm - remove a system property SYNOPSIS system [-h | --help] proprm name PARAMETERS [-h | --help] Display this help message name The name of the property
system freemem
NAME system freemem - show free memory SYNOPSIS system [-h | --help] freemem [-u | --unit] [-d | --decimal] PARAMETERS [-h | --help] Display this help message [-u | --unit] The unit of the memory space size {(B)yte, (O)ctet, (M)egaOctet, (G)igaOctet} [-d | --decimal] The number of decimal (default 0)
system totalmem
NAME system totalmem - show total memory SYNOPSIS system [-h | --help] totalmem [-u | --unit] [-d | --decimal] PARAMETERS [-h | --help] Display this help message [-u | --unit] The unit of the memory space size {(B)yte, (O)ctet, (M)egaOctet, (G)igaOctet} [-d | --decimal] The number of decimal (default 0)
thread
thread stop
NAME thread stop - stop vm threads SYNOPSIS thread [-h | --help] stop ... threads DESCRIPTION Stop VM threads. PARAMETERS [-h | --help] Display this help message ... threads the thread ids to stop
thread interrupt
NAME thread interrupt - interrupt vm threads SYNOPSIS thread [-h | --help] interrupt ... threads DESCRIPTION Interrup VM threads. PARAMETERS [-h | --help] Display this help message ... threads the thread ids to interrupt
thread ls
NAME thread ls - list the vm threads SYNOPSIS thread [-h | --help] ls [-n | --name] [-g | --group] [-s | --state] PARAMETERS [-h | --help] Display this help message [-n | --name] Filter the threads with a glob expression on their name [-g | --group] Filter the threads with a glob expression on their group [-s | --state] Filter the threads by their status (new,runnable,blocked,waiting,timed_waiting,terminated)
thread top
NAME thread top - thread top SYNOPSIS thread [-h | --help] top [-n | --name] [-g | --group] [-s | --state] PARAMETERS [-h | --help] Display this help message [-n | --name] Filter the threads with a glob expression on their name [-g | --group] Filter the threads with a glob expression on their group [-s | --state] Filter the threads by their status (new,runnable,blocked,waiting,timed_waiting,terminated)
version
ws
ws login
NAME ws login - login to a workspace SYNOPSIS ws [-h | --help] login [-u | --username] [-p | --password] [-c | --container] workspaceName DESCRIPTION This command login to a JCR workspace and establish a session with the repository. When you are connected the shell maintain a JCR session and allows you to interact with the session in a shell oriented fashion. The repository name must be specified and optionally you can specify a user name and password to have more privileges. Before performing a login operation, a repository must be first selected with the repo command, for instance: % repo use container=portal Once a repository is obtained the login operation can be done: % ws login portal-system Connected to workspace portal-system % ws login -u root -p gtn portal-system Connected to workspace portal-system PARAMETERS [-h | --help] Display this help message [-u | --username] The user name [-p | --password] The user password [-c | --container] The portal container name (eXo JCR specific) workspaceName The name of the workspace to connect to
xpath
NAME xpath - execute a JCR xpath query SYNOPSIS xpath [-h | --help] [-o | --offset] [-l | --limit] [-a | --all] query DESCRIPTION Executes a JCR query with the xpath dialect, by default results are limited to 5.All results matched by the query are produced by this command. PARAMETERS [-h | --help] Display this help message [-o | --offset] The offset of the first node to display [-l | --limit] The number of nodes displayed, by default this value is equals to 5 [-a | --all] Display all the results by ignoring the limit argument, this should be used with care for large result set query The query