Running a script from Groovy - groovy

In order to get my setup a bit closer to "one click deployment", I would like to use groovy scripts to start/stop other processes controlled by bat scripts, running in different parts of the filesystem and even on different machines.
How to execute these scripts and how to do it from their respective working directory?
I know Java's
java.lang.Runtime's exec()
However there are lots of issues with this and I wondered if Groovy had some kind of shorthand for this as well?
Thanks!

Groovy added an execute() method to plain old String, so try this:
println "ls -la".execute().text

The execute() method can be used to change directories if you prefix it with the "cmd /c" command, and then use ampersand (assuming Windows) to chain commands together.
Example, assuming you want to go to subdirectory subdir and run a couple of batch files from there:
println "cmd /c cd subdir & batch1.bat & batch2.bat".execute().text
Not sure if there isn't a better way, but this does work.

You can also use ProcessBuilder which is a surprisingly convienent Java class introduced in java 5.
ProcessBuilder lets you
determine the working directory
determine which environmental variables the process should have
See http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html for a brief example and more documentation.

If you aren't afraid to create some reusable code you could create an object that wraps an .execute() process. I created something like this and use it regularly.
Create a new process with:
def proc="cmd".execute()
After that you can use "consumeProcessOutput()" to manage the input and output of "proc". Anything you send to it will be acted on as though you typed it into a shell, and all the output of that shell will be available to you.
I wrapped all this up in a closure so that you could do this:
cmd("cd \\ \n dir ") {
if(it.contains("AUTOEXEC.BAT"))
println it;
return true;
}
To get a display that shows only the autoexec.bat line. Note that until you return true from the closure, the stdin of that process is available so you can send more lines of text and interact with it indefinitely.
I use it quite a bit because commands like "cd" and "Dir" don't work in windows with .execute(), so a simple:
def directoryListing=cmd("cd\\\ndir")
will get me a quick directory listing with ease.

Related

abas-ERP: Excecute a FO-Service-Program from a cronjob

I need to run a service program, written in FO for abas-ERP continuous.
I heard about some already existing scripts for calling service programs from the shell. If that is possible I could simply use a cronjob for starting this script.
But I don't know exactly where to find a template for these shell scripts, which conditions have to be complied and if there are any restrictions.
For Example: Is it possible to call several FO-programs successively (this might be important relating to blocking licences)?
You can use edpinfosys.sh and execute infosystem TEXTZEIGEN per cronjob.
You could also use batchlg.sh
batchlg.sh 'FOP-Name' [ -PASSARGS ] [Parameter ...]

Jenkins/Hudson Groovy Script Console: Flexibility

I really like being able to run Groovy scripts in Hudson (or Jenkins, but I use Hudson).
For example, see my question In Groovy, how do I get the list of parameter names for a given job? Hudson parameter names question][1]
The thing is, now I'd like use these Groovy scripts like a keyboard macro or utility. I want to be visiting one of my jobs, hit the special keystroke, and voila, the Groovy script is run. I leave it as an exercise for myself to pick up parameters from environment of current job.
Does anybody out there do this sort of thing, and if so, what strategy has been useful. So far, all I know how to do is bring up the script console, pasted in my code, edit the variable containing the name of the Hudson job, and hit "run". Kinda klunky. Suggestions appreciated.
You can use jenkins Remote access method to do this. The Jenkins wiki describes how to use Remote access:
User can execute groovy scripts remotely sending post request to
/script/ url or /scriptText/ to have response returned without the
html wrapping.
$ curl -d "script=<your_script_here>" http://jenkins/script
$ # or
$ curl -d "script=<your_script_here>" http://jenkins/scriptText
Also, Jenkins CLI offers the possibility to execute groovy
scripts remotely using groovy command or execute groovy interactivelly
via groovysh.

Is it possible to break out of a restricted (custom) shell?

Not sure if this is the right place to ask.
Say I write a shell that takes stdin input, filters this input so let's say only certain commands like
ls (list contents of binary directory and subdirectory)
update (git clone)
build (go build)
test (go test)
start (systemctl start this.service only)
stop (systemctl stop this.service only)
running (is the binary being executed and with how many GOMAXPROCS?)
usage (memory, cpu usage)
gensvc (generate .service file)
exit (leave shell/logout)
work, you guessed it, I'm trying to give a user only very limited maintenance access over ssh.
Say I'm careful with \0 (I'd write it in Go anyway using bufio.Scanner)
Is there any way to stop the running shell and execute /bin/sh or similar or any way to get around this shell?
The idea is a user should push their stuff via git to a bare repo, this repo is cloned to the filesystem to a certain directory, then go build is called and the binary is ran with a systemd .service file that is generated previously.
Thinking logically, if the user is only able to write certain strings that are accepted, no there is no way. But maybe you know of one, some ctrl+z witchcraft ;) or whatever.
The only attack surface is the input string or rather bytes. Of course the user could git push a program that builds its own shell or runs certain commands, but that's out of scope (I would remove capabilities with systemd and restrict device access and forbid anything but the connection to the database server, private tmp and all, namespace and subnamespace it TODO)
The only problem I see is git pushing but I'm sure I could work around that in a git only mode argv and adding it to ~/.ssh/authorized_keys. something like lish gitmode and execute stdin commands if they start with git or something like it.
Example:
https://gist.github.com/dalu/ce2ef43a2ef5c390a819
If you're only allowed certain commands, your "shell" will read the command, parse it and then execute it then you should be fine, unless I misunderstood it.
Go "memory" can't be executed, not without you doing some nasty hacks with assembly anyway, so you don't have to worry about shell injection.
Something along these lines should be safe:
func getAction() (name string, args []string) {
// read stdin to get the command of the user
}
func doAction() {
for {
action, args := getAction()
switch action {
case "update": //let's assume the full command is: update https://repo/path.git
if len(args) != 1 {
//error
}
out, err := exec.Command("/usr/bin/git", "clone", "--recursive", args[0]).CombinedOutput()
// do stuff with out and err
}
}
}
If you are implementing the shell yourself and directly executing the commands via exec() or implementing them internally, then it is certainly possible to produce a secure restricted shell. If you are just superficially checking a command line before passing it on to a real shell then there will probably be edge cases you might not expect.
With that said, I'd be a bit concerned about the test command you've listed. Is it intended to run the test suite of a Go package the user uploads? If so, I wouldn't even try to exploit the restricted shell if I was an attacker: I'd simply upload a package with tests that perform the actions I want. The same could be said for build/start.
Have it reviewed by a pentesting team.
People can be very creative when breaking out a sandbox of any type. Only if you never accept the user's input you can consider yourself rather safe on premises (but here any command is an input) - paper security assumptions are considered a weak to assess the software. They are similar to 'no-bug' assumptions for an algorithm on paper: as soon as you implement it, 99% of time a bug raises

How to change the current working directory in Groovy

Now, I am writting a Groovy script to invoke other's interface. But I need change my current working path when running the script. I know it is not possible in Java. Is it possible in Groovy?
If you can run other script as separate process, you can give ProcessBuilder parameter working dir:
def processBuilder=new ProcessBuilder(command)
processBuilder.directory(new File("Working dir"))
def process = processBuilder.start()
or
command.execute(null, new File("Working dir"))
so that process will switch to your new folder and execute it there.
As Groovy runs on JVM, the same restrictions apply. Unfortunately it is not possible.
Changing the current working directory in Java?
JDK bug
Java/groovy doesn't really "Have" a working directory as far as I can tell. The shell that launched groovy has one and any child "commands" inherit from that shell diretly.
Java also seems to read the current directory of the shell and store it in "user.dir". This is used as a base for the "File" object so if you System.setProperty("user.dir", "c:/windows") it will change future invocations of new File(".") but will not change the parent shell directory (and therefore not the child directories).
Here are three "Work-Arounds" that may work for different scenarios:
1) I KIND OF overcame this for a very specific task... I wanted to implement "cd" as a groovy script. It was only possible because all my scripts were already being "wrapped" in a batch file. I made it so that my script could create a file called "afterburner.cmd" that, if it existed, would be executed when the script exits. There was some batch file trickery to make this work.
A startup cmd file could also "Set" the current directory before invoking your groovy script/app.
By the way, Having a startup cmd has been much more helpful than I'd thought it would be--It makes your environment constant and allows you to more easily deploy your "Scripts" to other machines. I even have mine compile my scripts to .classes because it turned out to be faster to compile a .groovy to a .class and start the .class with "Java" than it was to just run the script with "groovy"--and usually you can skip the compile step which makes it a LOT faster!
2) For a few small commands, you might write a method like this:
def currentDir = "C:\\"
def exec(command, dir = null) {
"cmd /c cd /d ${dir?:currentDir} && $command".execute().text
}
// Default dir is currentDir
assert exec("dir").endsWith("C:\\>")
// different dir for this command only
assert exec("dir", "c:\\users").endsWith("C:\\users")
// Change default dir
currentDir = "C:\\windows"
assert exec("dir").endsWith("C:\\windows")
it will be slower than "".execute() if "cmd" is not required.
3) Code a small class that maintains an "Open" command shell (I did this once, there is a bit of complexity), but the idea is:
def process="cmd".execute()
def in=process.in
def out=process.out
def err=process.err
Now "in" is an input stream that you could spin off/read from and "out" is an output stream that you can write commands to, keep an eye on "err" to detect errors.
The class should write a command to the output, read the input until the command has completed then return the output to the user.
The problem is detecting when the output of any given command is complete. In general you can detect a "C:..." prompt and assume that this means that the command has finished executing. You could also use a timeout. Both are pretty fallible. You can set that shell's prompt to something unique to make it much less fallible.
The advantage is that this shell can remain open for the entire life of your app and can significantly increase speed since you aren't repeatedly creating "cmd" shells. If you create a class (let's call it "CommandShell") that wraps your Process object then it should be really easy to use:
def cmd=new CommandShell()
println cmd.execute("cd /d c:\\")
println cmd.execute("dir") // Will be the dir of c:\
I wrote a groovy class like this once, it's a lot of experimenting and your instance can be trashed by commands like "exit" but it's possible.
you can wrap it up in a dir block.
eg :
dir('yourdirectory') {
codeblock
}

Using GroovyShell as "expression evaluator/engine" (or: How to reuse GroovyShell)

I'm using GroovyShell as an "expression evaluator/engine" inside my program. It accepts two inputs: (a) one or more init scripts (b) user-defined script. Both are then concatenated at runtime as big chunk of script (text) and feed to the shell.
String initScripts = getFromDB()
String userScript = getFromUser()
def shell = new GroovyShell()
output = shell.evaluate(initScripts + userScript)
The above code will run in a loop, where the contents of userScript will vary.
So far, initScripts only contain variable definitions (e.g. def $yyyy = new Date().format('yyyy')) which might be referenced in userScript (e.g. print "$yyyy 001").
Is there any more efficient approach for this? (E.g. reusing the shell, how?) Because right now it's very slow.
Edit: Groovy is a must. Please don't recommend other scripting engine.
Edit: I'm thinking whether GroovyShell can do this (pseudo-code):
def shell = new GroovyShell()
shell.evaluate(initScripts)
for each userScript in DB {
shell.put(userScript )
def result = shell.evaluateThat()
println "Result is $result"
}
Is this possible? (Last time I googled it's not possible, but I'm hoping I'm wrong)
You can cache the GroovyShell, you don't need to create a new one always:
final static GroovyShell shell = new GroovyShell()
Also if you run one Script many times you may cache them too. You can create a Script with GroovyShell.parse(String scriptText), use Script.run() to run the script.
This section of the documentation might help too, instead of scripts you can also create groovy objects dynamically.
I guess you could avoid the weight of building a full groovy environment each time.
Since Java 6, there is a scripting API support in Java, which allows you to use lightweight scripting engines.
As an example, see this page in groovy website explaining how to start a groovy script in a Java application using GroovyScriptEngineImpl.
notice you may loose some groovy goodnesses, like maybe Groovy grape, but you'll be able to
reuse your script engine
ensure your script evals in application context (eventually benefitting from Java objects usage)
EDIT one important thing to notice is that neither GroovyScriptEngineImpl nor GroovyShell can guarantee you any kind of thread safety, as any groovy script is free to spawn any number of thread. In fact, the only way you could guarantte thread safety would be by installing a SecurityManager forbidding thread operations. In fact, even that wouldn't guarantee thread safety (as this thread safety could only be achieved by ensuring all your Java code base is thread safe).
I end up doing this:
def shell = new GroovyShell()
shell.evaluate(initScripts)
for( i in 1..count )
{
output = shell.evaluate(userScripts);
}
And just to be safe, you can put shell in ThreadLocal or pool.

Categories

Resources