Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Using Groovy for Bash (shell) Operations

DZone's Guide to

Using Groovy for Bash (shell) Operations

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

Recently I needed to create a groovy script that deletes some directories in a Linux machine.
Here’s why:
1.
We have a server for doing scheduled jobs.
Jobs such as ETL from one DB to another, File to DB etc.
The server activates clients, which are located in the machines we want to have action on them.
Most (almost all) of the jobs are written in groovy scripts.

2.
Part of our CI process is deploying a WAR into a dedicated server.
Then, we have a script that among other things uses soft-link to direct ‘webapps’ to the newly created directory.
This deployment happens once an hour, which fills up the dedicated server quickly.

So I needed to create a script that checks all directories in the correct location and deletes old ones.
I decided to keep the latest 4 directories.
It’s currently a magic number in the script. If I want / need I can make it as an input parameter. But I decided to start simple.

I decided to do it very simple:
1. List all directories with prefix webapp_ in a known location
2. Sort them by time, descending, and run delete on all starting index 4.

def numberOfDirectoriesToKeep = 4
def webappsDir = new File('/usr/local/tomcat/tomcat_aps')
def webDirectories = webappsDir.listFiles().grep(~/.*webapps_.*/)
def numberOfWeappsDirectories = webDirectories.size();
 
if (numberOfWeappsDirectories >= numberOfDirectoriesToKeep) {
  webDirectories.sort{it.lastModified() }.reverse()[numberOfDirectoriesToKeep..numberOfWeappsDirectories-1].each {
    logger.info("Deleteing ${it}");
    // here we'll delete the file. First try was doing a Java/groovy command of deleting directories
  }
} else {
  logger.info("Too few web directories")
}

It didn’t work.
Files were not deleted.
It happened that the agent runs as a different user than the one that runs tomcat.
The agent did not have permissions to remove the directories.

My solution was to run a shell command with sudo.

I found references at:
http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/
and
http://groovy.codehaus.org/Executing+External+Processes+From+Groovy

To make a long story short, here’s the full script:

import org.slf4j.Logger
import com.my.ProcessingJobResult

def Logger logger = jobLogger
//ProcessingJobResult is proprietary 
def ProcessingJobResult result = jobResult

try {
	logger.info("Deleting old webapps from CI - START")
	def numberOfDirectoriesToKeep = 4 // Can be externalized to input parameter
	def webappsDir = new File('/usr/local/tomcat/tomcat_aps')
	def webDirectories = webappsDir.listFiles().grep(~/.*webapps_.*/)
	def numberOfWeappsDirectories = webDirectories.size();

	if (numberOfWeappsDirectories >= numberOfDirectoriesToKeep) {
		webDirectories.sort{it.lastModified() }.reverse()[numberOfDirectoriesToKeep..numberOfWeappsDirectories-1].each {
			logger.info("Deleteing ${it}");
			def deleteCommand = "sudo -u tomcat rm -rf " + it.toString();
			deleteCommand.execute();
		}
	} else {
		logger.info("Too few web directories")
	}
	result.status = Boolean.TRUE
	result.resultDescription = "Deleting old webapps from CI ended"
	logger.info("Deleting old webapps from CI - DONE")
} catch (Exception e) {
	logger.error(e.message, e)
	result.status = Boolean.FALSE
	result.resultError = e.message
}

return result

BTW,
There’s a minor bug of indexes, which I decided not to fix (now), as we always have more directories.



Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Published at DZone with permission of Eyal Golan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}