Table of Contents
List of Examples
The Common Reusable SHell (CRaSH) deploys in a Java runtime and provides interactions with the JVM. Commands are written in Groovy and can be developped at runtime making the extension of the shell very easy with fast development cycle.
Table of Contents
There are several ways to run CRaSH.
CRaSH provides has various ways to be started, it can also be easily embedded.
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 directory 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.0.0-cr2-SNAPSHOT Follow and support the project on http://vietj.github.com/crash Welcome to jerry + ! It is Thu Apr 12 21:19:35 CEST 2012 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 proerties 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
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 works thanks to the standalone mode, the main difference is when you run the command line you can specify a process id of a JVM and CRaSH will hook into the targetted JVM, let's see quickly an example of how to use it
> jps 3165 RemoteMavenServer 20650 Test 20651 Jps > crash.sh 20650 ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.0.0-cr2-SNAPSHOT Follow and support the project on http://vietj.github.com/crash Welcome to jerry + ! It is Thu Apr 12 22:09:23 CEST 2012 now %
In this example we will attach 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.
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:
Example 1.1. Embedding CRaSH in a web application
<web-app> <listener> <listener-class>org.crsh.plugin.WebPluginLifeCycle</listener-class> </listener> </web-app>
CRaSH can be easily embedded and configured in a Spring configuration, here is an example of embedding crash:
Example 1.2. Embedding CRaSH in SPring with the Telnet plugin
<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> <prop key="crash.telnet.port">4000</prop> </props> </property> </bean> <bean class="org.crsh.telnet.TelnetPlugin"> </bean> </beans>
In this mode, the plugins are not discovered using the classpath, instead each plugin must be declared as a Spring bean.
The configuration properties can be also set as properties with the config property of the SpringBootstrap
bean.
Table of Contents
You need to connect using telnet, SSH to use the shell, there is a third special mode using the JVM input and output.
Telnet connection is done on port 5000:
(! 520)-> telnet localhost 5000 Trying ::1... Connected to localhost. Escape character is '^]'. ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.1.0-cr1 Follow and support the project on http://vietj.github.com/crash Welcome to julien.local + ! It is Fri Dec 03 16:20:40 CET 2010 now
The bye
command disconnect from the shell.
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 1.1.0-cr1 (http://vietj.github.com/crash) Welcome to juliens-macbook-pro.local! It is Fri Jan 08 21:12:53 CET 2010 now. %
The bye
command disconnect from the shell.
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" or 'old boy'. One quote style can quote another, like "ol' boy".
Completion: an advanced completion system is available
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
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.
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
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 consumer 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.
Example 2.2. Update the security of all nt:unstructed nodes
% select * from nt:unstructured | setperm -i any -a read + setperm -i any -a write
NAME sleep - sleep for some time SYNOPSIS sleep [-h | --help] time PARAMETERS [-h | --help] Provides command usage time sleep time in seconds
NAME man - format and display the on-line manual pages SYNOPSIS man [-h | --help] command PARAMETERS [-h | --help] Provides command usage command the command
NAME log add - create one or several loggers SYNOPSIS log [-h | --help] add ... name PARAMETERS [-h | --help] Provides command usage ... name The name of the logger
NAME log set - configures the level of one of several loggers SYNOPSIS log [-h | --help] set [-l | --level] [-p | --plugin] ... 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] Provides command usage [-l | --level] The logger level to assign among {trace, debug, info, warn, error} [-p | --plugin] Force the plugin implementation to use ... name The name of the logger
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] Provides command usage [-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
NAME log info - display info about a logger SYNOPSIS log [-h | --help] info ... name DESCRIPTION The loginfo command displays information about one or several loggers. % loginfo javax.management.modelmbean javax.management.modelmbean<INFO> The loginfo command is a <Logger,Void> command and it can consumed logger produced by the logls command: % logls -f javax.* | loginfo javax.management.mbeanserver<INFO> javax.management.modelmbean<INFO> PARAMETERS [-h | --help] Provides command usage ... name The name of the logger
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] Provides command usage [-f | --filter] A regular expressions used to filter the loggers
NAME thread stop - stop vm threads SYNOPSIS thread [-h | --help] stop ... ids DESCRIPTION Stop VM threads. PARAMETERS [-h | --help] Provides command usage ... ids the thread ids to stop
NAME thread interrupt - interrupt vm threads SYNOPSIS thread [-h | --help] interrupt ... ids DESCRIPTION Interrup VM threads. PARAMETERS [-h | --help] Provides command usage ... ids the thread ids to interrupt
NAME thread ls - list the vm threads SYNOPSIS thread [-h | --help] ls [-n | --name] [-f | --filter] [-s | --state] PARAMETERS [-h | --help] Provides command usage [-n | --name] Retain the thread with the specified name [-f | --filter] Filter the threads with a regular expression on their name [-s | --state] Filter the threads by their status (new,runnable,blocked,waiting,timed_waiting,terminated)
NAME thread dump - dump vm threads SYNOPSIS thread [-h | --help] dump ... ids DESCRIPTION Dump VM threads. PARAMETERS [-h | --help] Provides command usage ... ids the thread ids to dump
NAME system gc - call garbage collector SYNOPSIS system [-h | --help] gc PARAMETERS [-h | --help] Provides command usage
NAME system propls - list the vm system properties SYNOPSIS system [-h | --help] propls [-f | --filter] PARAMETERS [-h | --help] Provides command usage [-f | --filter] filter the property with a regular expression on their name
NAME system propset - set a system property SYNOPSIS system [-h | --help] propset name value PARAMETERS [-h | --help] Provides command usage name The name of the property value The value of the property
NAME system propget - get a system property SYNOPSIS system [-h | --help] propget name PARAMETERS [-h | --help] Provides command usage name The name of the property
NAME system proprm - remove a system property SYNOPSIS system [-h | --help] proprm name PARAMETERS [-h | --help] Provides command usage name The name of the property
NAME system freemem - show free memory SYNOPSIS system [-h | --help] freemem [-u | --unit] [-d | --decimal] PARAMETERS [-h | --help] Provides command usage [-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)
NAME system totalmem - show total memory SYNOPSIS system [-h | --help] totalmem [-u | --unit] [-d | --decimal] PARAMETERS [-h | --help] Provides command usage [-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)
NAME jdbc close - close the current connection SYNOPSIS jdbc [-h | --help] close PARAMETERS [-h | --help] Provides command usage
NAME jdbc open - open a connection from JNDI bound datasource SYNOPSIS jdbc [-h | --help] open globalName PARAMETERS [-h | --help] Provides command usage globalName The datasource JNDI name
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] Provides command usage [-u | --username] The username [-p | --password] The password [--properties] The extra properties connectionString The connection string
NAME jdbc info - describe the database SYNOPSIS jdbc [-h | --help] info ... tableNames PARAMETERS [-h | --help] Provides command usage ... tableNames the table names
NAME jdbc execute - execute SQL statement SYNOPSIS jdbc [-h | --help] execute ... statement PARAMETERS [-h | --help] Provides command usage ... statement The statement
Table of Contents
The CRaSH JCR extension allow to connect and interract with Java Content Repository implementations.
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] Provides command usage
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] Provides command usage
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] Provides command usage parameters The parameters used to instantiate the repository to be used in this session
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] Provides command usage [-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
NAME ws logout - logout from a workspace SYNOPSIS ws [-h | --help] logout DESCRIPTION This command logout from the currently connected JCR workspace PARAMETERS [-h | --help] Provides command usage
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] Provides command usage path The new path that will change the current node navigation
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] Provides command usage
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] Provides command usage [-d | --depth] The depth of the printed tree path The path of the node content to list
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] Provides command usage source The path of the source node to copy target The path of the target node to be copied
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] Provides command usage source The path of the source node to move, absolute or relative target The destination path absolute or relative
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] Provides command usage ... paths The paths of the node to remove
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] Provides command usage [-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.
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] Provides command usage [-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
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] Provides command usage source The path of the imported nt:file node target The path of the parent imported node
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] Provides command usage source The path of the exported node target The path of the exported nt:file node
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] Provides command usage mixin the mixin name to add ... paths the paths of the node receiving the mixin
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] Provides command usage mixin the mixin name to remove ... paths the paths of the node receiving the mixin
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 * from nt:base -o 10 -l 20 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 * from nt:base -a The query matched 1114 nodes ... select is a <Void,Node> command producing all the matched nodes. PARAMETERS [-h | --help] Provides command usage [-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
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] Provides command usage [-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
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] Provides command usage path The path of the node to commit
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] Provides command usage path the path to rollback
NAME version checkin - checkin a node SYNOPSIS version [-h | --help] checkin path DESCRIPTION Perform a node checkin PARAMETERS [-h | --help] Provides command usage path The node path to checkin
NAME version checkout - checkout a node SYNOPSIS version [-h | --help] checkout path DESCRIPTION Perform a node checkout PARAMETERS [-h | --help] Provides command usage path The node path to checkout
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.
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.
Table of Contents
CRaSH is configured by a set of properties, these properties are defined in a configuration file. 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.
CRaSH properties are always prefixed by the crash. value
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
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
to remove the telnet access, remove the jar file in the WEB-INF/lib/crsh.shell.telnet-1.1.0-cr1.jar .
to remove the SSH access, remove the jar file in the WEB-INF/lib/crsh.shell.ssh-1.1.0-cr1.jar .
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.
Authentication is used by the SSH server when a user authenticates. Authentication interface is pluggable and has default implementations. The the section called “Pluggable authentication ” 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
CRaSH comes out of the box with two authentication plugins.
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
Table of Contents
Creating a custom 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 to integrate CRaSH with an authentication mechanism:
public interface AuthenticationPlugin { /** * Returns the authentication plugin name. * * @return the plugin name */ String getName(); /** * Returns true if the user is authentified by its username and password. * * @param username the username * @param password the password * @return true if authentication succeeded * @throws Exception any exception that would prevent authentication to happen */ boolean authenticate(String username, String password) 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 { public String getName() { return "simple"; } @Override public AuthenticationPlugin getImplementation() { return this; } ... }
The getName()
method returns the simple value that matchs the crash.auth configuration property
The getImplementation()
method returns the object that implements the AuthenticationPlugin
class, this method is implemented from the CRaSHPlugin
abstract class, in our case it simply returns this
as the plugin and the implementation of AuthentionPlugin
are the same 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 { public static final PropertyDescriptor<String> SIMPLE_USERNAME = PropertyDescriptor.create( "auth.simple.username", "admin", "The username"); public static final PropertyDescriptor<String> SIMPLE_PASSWORD = PropertyDescriptor.create( "auth.simple.password", "admin", "The password"); @Override protected Iterable<PropertyDescriptor<?>> createConfigurationCapabilities() { return Arrays.<PropertyDescriptor<?>>asList( SIMPLE_USERNAME, SIMPLE_PASSWORD); } private String username; private String 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 constants SIMPLE_USERNAME
and SIMPLE_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 method getContext()
available in the CRaSHPlugin
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 package 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
Table of Contents
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 it
Groovy is dynamic and expressive
Each command has a corresponding Groovy file that contains a command class that will be invoked by the shell. The files are located in
In the standalone distribution the cmd directory
In a web archive deployment the /WEB-INF/crash/commands directory
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.
The simplest command can be a simple script that returns a string
return "Hello World";
It is possible to use also the out
implicit variable to send a message to the console:
out.println("Hello World");
Class can also be used to defined a command, it provides significant advantages over scripts:
Commands can declare options and arguments for the command
Commands can use annotations to describe the command behavior and parameters
When the user types a command in the sell, the command line is parsed by the cmdline framework and injected in the command class. Previously the args4j framework was used but this framework does not support natively code completion and could not be extended to support it. The support of command line completion is the main motivation of the development of such a framework.
Let's study a simple class command example:
class date extends CRaSHCommand { @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 undertand:
The @Command
annotation declares the main
method as a command
The command takes one optional format
option
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 humand description of the command
% date -h usage: date [-h | --help] [-f | --format] [-h | --help] command usage [-f | --format] the time format
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 extends CRaSHCommand { @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"]) Value.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
During the execution of a command, CRaSH provides a context for interacting with the context of execution of the current command: the property context is resolve 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:
Example 6.1. The command context
/** * The context of a command. * * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> * @version $Revision$ */ public interface CommandContext { /** * Returns the current shell session. * * @return the session map */ Map<String, Object> getSession(); /** * Returns the current shell attributes. * * @return the attributes map */ Map<String, Object> getAttributes(); }
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:
Example 6.2. Using shell session
context.session["foo"] = "bar"; out.println(bar);
Bind the session attribute foo with the value bar |
|
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: attributes resolve to Spring beans.
When attached to a virtual machine, the context attributes has only a single instrumentation
entry that is the java.lang.instrument.Instrumentation
instance obtained when attaching to a virtual machine.
Now let's examine the InvocationContext
that extends the CommandContext
:
Example 6.4. The invocation context
/** * The invocation context provided to a command during the invocation phase. * It provides the various interactions that a command can perform with * its context during its invocation. * * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> * @version $Revision$ */ public interface InvocationContext<C, P> extends CommandContext { /** * Returns the term width in chars. When the value is not positive it means * the value could not be determined. * * @return the term width */ int getWidth(); /** * Returns a generic property, usually this property is resolved by the * shell client. * * @param propertyName the property name * @return the property value */ String getProperty(String propertyName); /** * Display a message and read a line on the console. If no line can be read * then null is returned. * * @param msg the message to display before reading a line * @param echo wether or not the line read should be echoed when typing * @return the line read */ String readLine(String msg, boolean echo); /** * Returns the writer for the output. * * @return the writer */ ShellPrintWriter getWriter(); /** * Returns true if the command is involved in a pipe operation and receives * a stream. * * @return true if the command is involved in a pipe */ boolean isPiped(); /** * Returns an iterator over the stream of consumed items. * * @return the consumed items * @throws IllegalStateException if the command is not involved in a * pipe operation */ Iterable<C> consume() throws IllegalStateException; /** * Produce an item. * * @param product the item product */ void produce(P product); }
The PrintWriter
object is the command output, it can be used also via the out property in Groovy scripts:
Example 6.5. Printing on the shell
context.writer.print("Hello"); out.print("hello");
Printing using the context writer |
|
Printing using the out |
The readLine
method can be used to get interactive information from the user during the execution of a command.
Finally the isPiped
, consume
and produce
methods are used when writing commands that exchange objects via the pipe mechanism.
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: black, red, green, yellow, blue, magenta, cyan, white.
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.
Example 6.7. Decorating and coloring text
out.println("hello", red); out.println("hello", red, blue); out.println("hello", underline, red, blue);
Print hello in red color |
|
Print hello in red with a red blue |
|
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:
Example 6.8. Printing styled text
out.println("hello", style(red)); out.println("hello", style(red, blue)); out.println("hello", style(underline, red, blue));
Print hello in red color |
|
Print hello in red with a red blue |
|
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:
Example 6.9. Styling with the leftshift operator
out << red out << underline out << "hello" out << reset;
Set red foreground color |
|
Set underline |
|
Print hello in underlined red |
|
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.
In this section we study how a command can reuse existing commands, here is an example
Example 6.10. dbscript.groovy
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
and password
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