Kraken Core
Introduction
Kraken Core is an Apache Felix based OSGi application platform. You can dynamically install or uninstall OSGi bundles at runtime. If you are a Java developer then it will be easy to understand, because eclipse's plugin system is based on OSGi technology. Eclipse uses Equinox OSGi framework.
Kraken Core is packaged into a single JAR file (only 3MB), so you can copy and run OSGi container anywhere with one-line command: java -jar kraken-core-VERSION-package.jar Of course, you may need some other JVM specific options (max/min memory usage, garbage collection strategy, and so on)
You can run krakenapps modules in other OSGi container or use it as a library, but you cannot run kraken script in that case. Kraken Core provides very convenient telnet and ssh shell. Kraken shell support auto-completion via the tab key. ANSI escape code and/or precise telnet option control (e.g. echo off for password input) are also supported. You can read manual anytime if you pass invalid command arguments. But most important thing is that you can add custom commands very easily.
Installation
Latest development (trunk) version is kraken-core-1.9.2-package.jar. Download kraken-core-VERSION-package.jar file, and run it. JRE 6 is recommended.
$ java -Xmx500M -jar kraken-core-1.9.2-package.jar [2010-10-27 04:03:32,543] INFO (Kraken) - Default logging enabled. Configure log4j.properties file for custom logging. [2010-10-27 04:03:32,859] INFO (Kraken) - Booting Kraken. [2010-10-27 04:03:33,112] INFO (Kraken) - Console localhost/127.0.0.1:7004 opened. [2010-10-27 04:03:33,385] INFO (SecurityUtils) - Trying to register BouncyCastle as a JCE provider [2010-10-27 04:03:34,110] INFO (SecurityUtils) - Registration succeeded [2010-10-27 04:03:34,259] INFO (Kraken) - Kraken started. [2010-10-27 04:03:34,263] INFO (BundleManager) - Starting org.apache.felix.framework [0] bundle.
-Xmx500M means that JVM can allocate maximum 500MB of memory. If you have sufficient memory, you can reserve more memory space. There are also other JVM options, for example, -Xms (minimum memory), and so on.
Download and run, That's all.
Basic Commands
Connect to kraken shell using telnet or ssh:
telnet localhost 7004 ..or.. ssh localhost -p7022
Default SSH account/password is root/kraken. Telnet port is bound to localhost, so you cannot connect telnet server from remote machine. SSH don't have this limitation. Telnet connection does not require authentication, however it will be deprecated soon.
Anyway, welcome to kraken world!
Shutdown
Type shutdown at kraken shell:
kraken> shutdown ..or.. kraken> bundle.stop 0
bundle.stop 0 command will stop the system bundle, and it has exactly same effect.
If you use Oracle Sun JVM and Unix environment, you can shutdown kraken core gracefully using signal:
kill -SIGTERM [PID]
Account
List current accounts:
kraken> account.list Accounts ========== root
Create new account:
kraken> account.create
Description
create the account
Arguments
1. name: name of the account (required)
kraken> account.create xeraph
password:
confirm password:
kraken> account.list
Accounts
==========
root
xeraph
Change password:
kraken> account.passwd xeraph current password: new password: confirm password: password changed successfully kraken>
Delete account:
kraken> account.remove
Description
remove the account
Arguments
1. name: name of the account (required)
kraken> account.remove xeraph
Bundle
Maybe you already know about JAR file. Bundle is a JAR that contains also OSGi metadata in manifest. If you want to convert a library to bundle, see bnd pages. Kraken Core is an OSGi container ( Apache Felix based), so it can support dynamic bundle installation.
List all bundles:
kraken> bundle.list ..or.. kraken> bundle.list [filter text]
At first time, there is only system bundle like this:
kraken> bundle.list [ ID] Symbolic Name Version Status ================================================================== [ 0] org.apache.felix.framework 2.0.5 ACTIVE
List all bundle repositories:
kraken> bundle.repositories Maven Bundle Repository ====================================================================== [( 1) krakenapps] http://download.krakenapps.org/ [( 0) maven] http://repo1.maven.org/maven2/
Add new bundle repository configuration:
kraken> bundle.addRepository [repo alias] [url]
Delete bundle repository configuration:
kraken> bundle.removeRepository [repo alias]
Install bundle:
kraken> bundle.install [group id] [artifact id] [version]
For example:
kraken> bundle.install org.apache.felix org.apache.felix.ipojo 1.4.0 Resolving org.apache.felix/org.apache.felix.ipojo (1.4.0) -> trying to download from http://download.krakenapps.org/ bundle [1] loaded kraken> bundle.list [ ID] Symbolic Name Version Status ================================================================== [ 0] org.apache.felix.framework 2.0.5 ACTIVE [ 1] org.apache.felix.ipojo 1.4.0 INSTALLED
"bundle.install [group id] [artifact id] [version]" command finds bundles from bundle repositories, download it, and install it. But you may want to install from file system. At that time, type like this:
kraken> bundle.install file://[path]
For example:
In unix: kraken> bundle.install file:///root/kraken/kraken-ipojo-1.1.0.jar In windows: kraken> bundle.install file:///d:/kraken/kraken-ipojo/target/kraken-ipojo-1.1.0.jar
Note that one MORE slash needed in windows environment.
Uninstall bundle:
kraken> bundle.uninstall [bundle id]
You can uninstall multiple bundles at once, for example:
kraken> bundle.uninstall 2 3 4
Package
List all current installed packages:
kraken> pkg.list
List all current package repositories:
kraken> pkg.repositories Kraken Package Repository ========================= [krakenapps] http://krakenapps.org/mvn/kraken/
You can see default krakenapps package repository. You can also your own package repository. It will be explained as an advanced topic.
Add new kraken package repository configuration:
kraken> pkg.addRepository [repo alias] [url]
For example (default config again):
kraken> pkg.addRepository krakenapps http://krakenapps.org/mvn/kraken/
Delete package repository configuration:
kraken> pkg.removeRepository [repo alias]
For example (if you want to delete default package repository):
pkg.removeRepository krakenapps
Logging
Kraken Core writes all logs to log/ directory, and retains only 1 week logs by default. LogCleaner purges old log/kraken.log.yyyy-MM-dd files. You can find "Kraken Log Cleaner" thread using thread.list script. Logging can be done by using OSGi Log Service or SLF4J alternatively. I prefer SLF4J. :)
List all loggers:
kraken> logger.list [filter text] For example: kraken> logger.list Logger List ---------------- org.apache.felix.framework.Felix org.krakenapps.account.AccountManagerImpl org.krakenapps.bundle.BundleManager org.krakenapps.console.ScriptRunner org.krakenapps.console.ShellSession org.krakenapps.console.TelnetHandler org.krakenapps.console.TelnetStateMachine org.krakenapps.jpa.impl.HibernateJpaService org.krakenapps.jpa.impl.JpaConfig ..omitted.. kraken> logger.list jpa Logger List ---------------- org.krakenapps.jpa.impl.HibernateJpaService org.krakenapps.jpa.impl.JpaConfig
In general, Java developers use class name as a logger name. In other words, they create logger instance like this:
final Logger logger = LoggerFactory.getLogger(RpcAgentImpl.class.getName());
Switch Debug/Trace Logger:
Turn on debug/trace log: kraken> logger.on [logger name] Turn off debug/trace log: kraken> logger.off [logger name]
Log tracing in realtime:
kraken> logger.tail (press ctrl-c to stop)
Log level control:
kraken> logger.set [logger name] [log level] [on/off] For example: kraken> logger.set org.krakenapps.jpa.impl.HibernateJpaService trace on kraken> logger.set org.krakenapps.jpa.impl.HibernateJpaService info off
OSGi Service Monitoring
List all OSGi services:
kraken> osgi.services ========= OSGi Services ========= [ 1] org.apache.felix.framework.StartLevelImpl [ 2] org.apache.felix.framework.PackageAdminImpl [ 3] org.krakenapps.logger.KrakenLogService [ 4] org.apache.felix.prefs.impl.PreferencesServiceImpl ...omitted...
Inspect properties of an OSGi service:
kraken> osgi.properties [service.id]
For example:
kraken> osgi.properties 20 ====== OSGi Service Properties ====== alias: sunperf objectClass: [Ljava.lang.String;@71dc3d service.id: 20
Thread Monitoring and Control
List all threads:
kraken> thread.list [ 2] Reference Handler, Group: system, State: WAITING, Priority: 10 [ 3] Finalizer, Group: system, State: WAITING, Priority: 8 [ 4] Signal Dispatcher, Group: system, State: RUNNABLE, Priority: 9 [ 5] Attach Listener, Group: system, State: RUNNABLE, Priority: 5 [ 8] Kraken Log Cleaner, Group: main, State: TIMED_WAITING, Priority: 5 [ 10] FelixDispatchQueue, Group: main, State: WAITING, Priority: 5 [ 11] FelixStartLevel, Group: main, State: WAITING, Priority: 5 [ 12] FelixPackageAdmin, Group: main, State: WAITING, Priority: 5 [ 13] Thread-1, Group: main, State: TIMED_WAITING, Priority: 5 [ 14] NioSocketAcceptor-1, Group: main, State: RUNNABLE, Priority: 5 [ 15] NioSocketAcceptor-2, Group: main, State: RUNNABLE, Priority: 5 [ 16] DestroyJavaVM, Group: main, State: RUNNABLE, Priority: 5 [ 17] NioProcessor-2, Group: main, State: RUNNABLE, Priority: 5 [ 31] Thread-15, Group: main, State: RUNNABLE, Priority: 5
You can see all threads actively. There is log cleaner named 'Kraken Log Cleaner' for periodic log purging.
Check thread's stackframe:
kraken> thread.stacks [thread id] ..or.. kraken> thread.stacks [filter text for class name or methods]
For example:
kraken> thread.stacks 8
ID: 8, Name: Kraken Log Cleaner, State: TIMED_WAITING
java.lang.Thread.sleep
org.krakenapps.logger.LogCleaner.run (LogCleaner.java:58)
java.lang.Thread.run
Interrupt thread:
kraken> thread.interrupt [thread id]
Sometimes, buggy multithread logic raises deadlock condition or awaits infinitely. You can manually interrupt that kinds of threads. If you interrupt 'kraken Log Cleaner', it will wake up and work immediately.
Stop the thread:
kraken> thread.stop [thread id]
In production environment, you can stop malfunction thread using this command. However, it should be very careful, and not recommended.
Performance Monitoring
Force Garbage Collection:
kraken> perf.gc gc called pending object finalization count: 0
JVM memory monitoring:
kraken> perf.memory Free memory: 183,225,840 bytes Total memory: 755,433,472 bytes Maximum memory: 755,433,472 bytes
Count processors:
kraken> perf.processors Processors: 2
System information:
kraken> perf.system Architecture: i386 Operating system: Linux 2.6.27-11-server Load average: 0.8 System Uptime: 52155721 ms
System Resource Monitoring:
Oracle Sun JVM supports native system resource monitoring:
kraken> sunperf.system Process cpu time: 31,484,000,000,000 Free phys memory: 51,187,712/2,076,430,336 Free swap space: 3,682,578,432/3,997,442,048 Commited virtual memory: 1,116,377,088 open fd: 448/63536
Thread CPU usage monitoring:
Oracle Sun JVM supports thread cpu usage monitoring:
kraken> sunperf.topThreads
Thread CPU Usages
--------------------
TID 166: 10000000
java.net.PlainDatagramSocketImpl.receive0 (PlainDatagramSocketImpl.java)
java.net.PlainDatagramSocketImpl.receive (PlainDatagramSocketImpl.java:136)
java.net.DatagramSocket.receive (DatagramSocket.java:725)
org.snmp4j.transport.DefaultUdpTransportMapping$ListenThread.run
java.lang.Thread.run (Thread.java:619)
org.snmp4j.util.DefaultThreadFactory$WorkerThread.run
TID 76: 10000000
java.lang.Object.wait (Object.java)
java.lang.Object.wait (Object.java:485)
org.snmp4j.Snmp.send
org.snmp4j.Snmp.send
org.snmp4j.Snmp.getBulk
com.nchovy.baleen.monitor.snmp.AgentLogger.query (AgentLogger.java:427)
com.nchovy.baleen.monitor.snmp.AgentLogger.runOnce (AgentLogger.java:100)
org.krakenapps.log.api.AbstractLogger.run (AbstractLogger.java:207)
java.lang.Thread.run (Thread.java:619)
Idle threads are not listed, and sorted by cpu usage. This command is supported since kraken core 1.7.0.
Keystore Management
Kraken API exposes KeyStoreManager interface, and Kraken Core provides KeyStoreManager OSGi service. User can register arbitrary keystore file, and any OSGi services can get KeyStoreManager service reference and use it. In other words, keystore management is centralized. Kraken Package Manager also use KeyStoreManager service for HTTPS repository access.
KeyStoreManager interface:
public interface KeyStoreManager {
/**
* Return all key store names
*/
Collection<String> getKeyStoreNames();
/**
* Return all properties of the key store.
*/
Properties getKeyStoreProperties(String alias);
/**
* Find and return key store.
*/
KeyStore getKeyStore(String name);
/**
* Register file keystore. it is preserved permanently.
*/
void registerKeyStore(String name, String type, File file, char[] password) throws KeyStoreException,
FileNotFoundException, NoSuchAlgorithmException, CertificateException, IOException;
/**
* Register generic keystore. it is not preserved when kraken core reboots.
*/
void registerKeyStore(String name, String type, InputStream is, char[] password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException;
/**
* Unregister keystore.
*/
void unregisterKeyStore(String name);
/**
* Return new key manager factory using specified alias.
*/
KeyManagerFactory getKeyManagerFactory(String name, String algorithm) throws NoSuchAlgorithmException,
UnrecoverableKeyException, KeyStoreException;
/**
* Return new trust manager factory using specified alias.
*/
TrustManagerFactory getTrustManagerFactory(String name, String algorithm) throws KeyStoreException,
NoSuchAlgorithmException;
}
List all keystores:
kraken> keystore.list Key Stores =============
At first, there is no keystores.
Add new keystore config:
kraken> keystore.register test JKS d:/certs/server.jks PASSWORD [test] key store registered kraken> keystore.list Key Stores ============= [test] type: JKS, password: PASSWORD, path: d:\certs\server.jks
Delete keystore config:
kraken> keystore.unregister [name] For example: kraken> keystore.unregister test
List all key aliases in the keystore:
kraken> keystore.aliases test Aliases ============= server, cert=false, key=true
Print certificate details in the keystore:
kraken> keystore.cert test server
[
[
Version: V3
Subject: CN=IM00000001, OU=RND, O=NCHOVY, L=Guro, ST=Seoul, C=KR
Signature Algorithm: SHA1withDSA, OID = 1.2.840.10040.4.3
Key: Sun DSA Public Key
Parameters:DSA
p: fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669
455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7
6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb
83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7
q: 9760508f 15230bcc b292b982 a2eb840b f0581cf5
g: f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267
5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1
3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b
cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a
y:
42092f7a e375a3b6 538db1dc cae33cd1 18f34bb4 92651f47 559428ff 37650594
21795363 cb720b66 b5fdfd08 9d5b99b8 dd1bcd59 89ef5843 8db4123d 11582d68
b359e4f8 a0295d6f 20049c13 e96f4205 40dde85c d2c11673 c4c55066 c082ce0d
5a401aa2 1ad26edf a00cc882 49a61912 0338a1a4 bf46f9b8 468157ef befc3589
Validity: [From: Fri May 21 14:20:59 KST 2010,
To: Thu Aug 19 14:20:59 KST 2010]
Issuer: CN=IM00000001, OU=RND, O=NCHOVY, L=Guro, ST=Seoul, C=KR
SerialNumber: [ 4bf6183b]
]
Algorithm: [SHA1withDSA]
Signature:
0000: 30 2C 02 14 2D FC 5A D4 4E 25 6A 98 45 B2 50 E4 0,..-.Z.N%j.E.P.
0010: 27 17 E4 77 E8 65 3F D3 02 14 7A 68 A8 42 12 39 '..w.e?...zh.B.9
0020: 56 0B 46 E9 D3 FD B7 F3 B7 EF 40 A6 D6 E4 V.F.......@...
]
Batch Scripting
Miscellaneous
Advanced Topics
Custom Scripting
With extendable script system, you can provide interactive monitor and control. Is that true? Let's see an example:
public class HelloScriptFactory implements ScriptFactory {
@Override
public Script createScript() {
return new HelloScript();
}
}
public class HelloScript implements Script {
private ScriptContext context;
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
}
@ScriptUsage(description = "say hello",
arguments = {@ScriptArgument(name = "name", description = "to who?")})
public void say(String[] args) {
String name = args[0];
context.println("hello " + name);
}
// all other methods that have an String[] argument can be called as command.
}
and small iPOJO metadata.xml configuration (or you can use annotation)
<ipojo> ... <component classname="org.krakenapps.tutorial.HelloScriptFactory" name="hello-script-factory"> <provides> <property name="alias" type="string" value="hello" /> </provides> </component> <instance component="hello-script-factory" /> ... </ipojo>
That's all. Then if you type hello.say xeraph on kraken console, hello xeraph will be printed out. You already documented command with @ScriptUsage annotation (it is optional), so usage will be printed if you didn't set name argument.
It seems like an operating system because you can monitor and control all aspects of the system using the shell, and even more, you can build up your own applications or commands.
Kraken Package System
At this moment, you may think about OSGi bundle management problem. We all use package system or at least use installer in conventional operating system. No one manages countless executable binaries (dll or exe) by hands. Kraken Core provides own package system and you can install package by just one-line command. For example, pkg.install kraken-syslog will download and install syslog related bundles from package repository. Specified bundles are automatically started and provisioned. Of course, you can make your own package repository and use it. Refer package system? page for details.
Instrumentation Framework
- You can use Intrumentation framework introduced in Java 5.
- Support since kraken-core 1.3.4
- Start kraken core with -javaagent option.
java -javaagent:kraken-core-1.3.4-package.jar -jar kraken-core-1.3.4-package.jar
- Get IntrumentationService OSGi service using bundle context or iPOJO require configuration. (org.krakenapps.api.InstrumentationService)
ServiceReference ref = bundleContext.getServiceReference(InstrumentationService.class.getName()); InstrumentationService instService = bundleContext.getService(ref); .. or .. public class SampleScriptFactory implements ScriptFactory { @Requires // you can also use <requires field="instService" /> at component declaration in iPOJO metadata.xml private InstrumentationService instService; } - Use InstrumentationService object.
// inst can be null if you did not start with javaagent option // or JVM does not support instrumentation. Instrumentation inst = instService.getInstrumentation(); long size = inst.getObjectSize(obj);
Windows Installer Packaging
- See kraken.nsi script.
Run as a Windows Service
Materials
You must use latest kraken core 1.7.0 binary.
See following materials first.
Install
S:\srcs\kraken\kraken-core\target>
svc\amd64\prunsrv.exe
//IS//"Kraken_Core"
--Install=S:\srcs\kraken\kraken-core\target\svc\amd64\prunsrv.exe
--Description="Kraken core 1.7.0"
--Jvm=%JAVA_HOME%\jre\bin\server\jvm.dll
--StartMode=jvm
--Classpath=%CLASSPATH%;S:\srcs\kraken\kraken-core\target\kraken-core-1.7.0-package.jar
--StartClass=org.krakenapps.main.Kraken
--StartMethod=windowsService
--StartParams=start
--StopMode=jvm
--StopClass=org.krakenapps.main.Kraken
--StopMethod=windowsService
--StopParams=stop
--LogPath=S:\srcs\kraken\kraken-core\target\svc
--StdError=auto
--StdOutput=auto
--StartPath=S:\srcs\kraken\kraken-core\target
Major options:
- Path of prunsrv (check your machine architecture)
- --Install
- --Jvm
- --Classpath
- --LogPath
- --StartPath
You can also use --Startup option (see procrun manual)
Ensure you CANNOT use whitespace in service name (argument right after "IS"). (in commons-daemon 1.0.4)
Uninstall
svc\amd64\prunsrv //DS//"Kraken_Core"
See also
Authors
- xeraph [ xeraph@nchovy.com]
- stania [ stania@nchovy.com]
- delmitz [ delmitz@nchovy.com]
Release History
- 2.0.0 TODO
- add script argument auto-completion, and add path auto-completion helper
- add ssh port option (and change kraken.port to kraken.telnet.port)
- fix double-quote and backslash escape
- add os shell for linux and windows
- add full featured editor
- replace all prefsvc related code with confdb
- embed kraken-cron and remove separate log cleaner thread
- add bundle.update to support version upgrade (no bundle id change)
- add local/external auth system (with two-factor auth)
- add no-auth option and --help option (usage print)
- add external script execution (i.e. os shell scripting for kraken)
- automated rpm build and msi build
- full documentation
- 1.9.0
- added kraken-confdb and conf.* commands
- added "scp" (to) command
- added "set" command and environment variable support to keystore commands
- updated "bundle.update" command to download new version for bundle which is installed from remote maven repository
- 1.8.0
- upgraded apache felix to 3.2.2 (resolved zip file closed exception)
- 1.7.0 ~ 1.7.8
- Breaking Changes
- added ScriptContext.println(Object) and ScriptContext.print(Object)
- changed default parent directory of 'cache', 'download' to executing jar directory instead of 'user.home' or 'user.dir' working directory
- Minor Changes
- added thread cpu usage monitoring
- added FRAMEWORK_BOOTDELEGATION for JProfiler
- added interface for prunsrv (apache commons daemon)
- added "bundle.timestamp" and "bundle.manifest" command
- added "pkg.installables" command for package browsing
- added "pkg.export" command for package description generation
- added "bundle.downloadroot" command
- added local repository support to MavenMetadata resolving
- added "-d" start option for developers (update all local bundles before starting felix framework)
- added hostname to prompt
- added ls, cd, mv, cp, rm, wget, scp (from) commands
- added -Dkraken.dir option (change base directory of cache, log, download)
- added control key support (e.g. CTRL-S) and simple "edit" command
- Fixed Bugs
- fixed keystore file handle leak
- fixed infinite exception loop after disconnect ssh terminal
- fixed infinite input blocking caused by ESCAPE sequence
- Breaking Changes
- 1.6.0
- Breaking Changes
- added ScriptContext.printf instead of ScriptContext.println
- removed hsqldb dependency (incompatible with old kraken bundles)
- Major Changes
- support ssh shell and user authentication
- support http basic authentication and https for bundle/package management
- support local bundle/package repository ( file:// scheme)
- support keystore management
- support thread stack monitoring and performance monitoring
- support SIGTERM signal and shutdown command
- support automatic kraken log purging (retains 1week data)
- support window size changed event
- Minor Changes
- support bundle repository priority
- added bundle.restart and bundle.updateAll command
- added debug logging switch (logger.on and logger.off commands)
- added some embedded command (date, guid, color, ipconfig)
- updated felix framework version to 2.0.5
- added more system packages (org.w3c.dom.css, javax.xml.datatype)
- added ScriptContext.readPassword()
- chaged default log directory
- Breaking Changes
- 1.5.0 SNAPSHOT
- Added SSH console and login support
- Telnet console will be deprecated in a future release
- Added HTTP-Auth for package system
- Added bundle.restart command
- Added priority for bundle repository
- Removed maven bundle dependency resolver
- Added SSH console and login support
- 1.4.3
- 1.0.0
