Unleash the power of Gogo Shell

// The french version of this article can be found here: Libérez la puissance de Gogo Shell.

Gogo Shell opens huge opportunities but some obstacles limit the expression of its potential. Let's see in this post how to remove these barriers.

Few reminders: usual use of Gogo Shell

Apache Felix Gogo Shell is an interactive shell that allows you to interact with an OSGi container.

Gogo Shell can be accessed via telnet:

$ telnet localhost 11311
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
____________________________
Welcome to Apache Felix Gogo

g!

Warning ! Since version 7.1 of Liferay, access to Gogo Shell via telnet is no longer enabled by default. To enable it, you must add the following line in the portal-ext.properties file:

 
module.framework.properties.osgi.console=localhost:11311

Once the telnet connection is open, the Gogo Shell commands can be executed one after another without any restriction:

g! lb | grep search 
  438|Active     |   10|Liferay Portal Search Elasticsearch (2.1.8)
true
g! 

Beyond the commands dedicated to the management of the OSGi container, Gogo Shell offers a fairly complete language, including standard control structures such as loop or conditional:

g! each [1 2 3] { echo -- $it --  }
-- 1 --
-- 2 --
-- 3 --
null
null
null

Additionally, Gogo Shell allows you to call any method of any service deployed within the OSGi container:

g! ((($.context getService ($.context getServiceReference com.liferay.portal.kernel.service.UserLocalService)) getUserByScreenName 20116 'test') getFullName)
Test Test

Non-interactive mode

When you want to use Gogo Shell for task automation, typically within a bash script, the telnet connection poses difficulties.

Good news, as indicated in the official Liferay documentation, the Blade development tool can be used to overcome this obstacle:

$ blade sh 'lb | grep search'
lb | grep search
  438|Active     |   10|Liferay Portal Search Elasticsearch (2.1.8)
true

Unfortunately, using Blade on production environment is often impossible. Indeed, by the time these lines are written, the installation procedure of Blade is not adapted to a production context. Moreover, ops teams generally do not appreciate the installation of a tool dedicated to development on a production server.

Hopefully, there is another way to automate a telnet session. An Expect script, for example, does the job very well:

#!/usr/bin/expect -f
log_user 0
spawn telnet localhost 11311
expect "g!"
send -- "lb | grep search\n"
expect "g!"
send_user $expect_out(buffer)

myscript.sh

The Expect interpreter is a battle-tested command (created almost 30 years ago) that can be installed through standard tools of Linux distributions.

For a distro supporting APT:

sudo apt-get install expect

For a distro supporting YUM:

sudo yum install expect

Beyond OSGi: Groovy to the rescue!

In terms of executing portal components, Gogo Shell is confined to services exposed at the OSGi container level. Off, the portal Liferay offers many interesting Java classes that are not exposed in OSGi.

But luckily nothing is ever completely impossible with Liferay!

Indeed, as explained by Piotr Swiniarski in a post published on the blog of Mimacom, it is possible to invoke the Liferay Groovy script execution service from Gogo Shell.

Thus, it is possible to invoke any class of the portal. For example, using this principle, you can change the log level of a particular logger through an Expect script like this:

#!/usr/bin/expect -f
log_user 0
spawn telnet localhost 11311
expect "g!"

set groovy_script " \
	import static com.liferay.util.log4j.Log4JUtil.setLevel; \
	setLevel('com.company.mylogger','DEBUG',true); \
";

send -- " \
($.context getService (( \
  $.context getServiceReferences \
    com.liferay.portal.kernel.scripting.ScriptingExecutor \
    \"(scripting.language=groovy)\" \
) 0)) eval null null null \"$groovy_script\" \
\n"

expect "g!"
send_user $expect_out(buffer)

setloglevel.sh

Thanks to this brilliant idea of ​​Piotr, the possibilities become endless.

On the other hand it allows to use a language familiar to Java developers, much more convenient than Gogo Shell’s language.

Go to the next Level

At this point the possibilities are immense, but before your script is ready to go into production with confidence, there are still a lot of things to be done:

  • handle all error cases (telnet connection failure, exception in Groovy code, etc.)

  • manage the return status of the script

  • manage any buffer overflows from Expect interpreter

  • etc.

But don’t be afraid, you will not have to deal with it yourself, because the repository slemarchand/liferay-gogo-scripts on GitHub contains more than fifteen complete scripts that you can use as is or use as source of inspiration to write your own scripts.

You will find in this git repository, among others, the following scripts:

  • gogo-groovy-script directly execute a groovy script from a file,

  • gogo-bundle-get-state print the current state of a particular OSGi bundle,

  • gogo-bundle-start and gogo-bundle-stop respectively start and stop an OSGi bundle,

  • gogo-set-log-level set the log level of a particular logger,

  • gogo-reindex-all-search-indexes re-builds all search indexes,

  • et gogo-clear-all-caches clear all server caches.

Something to share ?

Have you ever encountered these obstacles with Gogo Shell? How did you overcome them? Have you encountered any other challenges?

Feel free to share your experiences in the comments of this post to make some contribution to the Liferay community!

 

Sébastien Le Marchand
Freelance Technical Consultant in Paris