1. Introduction
Kotlin’s scripting capabilities through .kts files present an efficient way to run Kotlin code. Consequently, this makes scripting a valuable tool for automation, prototyping, and embedding dynamic execution within larger applications.
Furthermore, Kotlin scripts can be seamlessly integrated into Kotlin applications, which offers enhanced flexibility in program execution.
In this tutorial, we’ll explore multiple approaches to running Kotlin scripts, including from within a Kotlin application. Each method comes with its advantages and limitations, providing various levels of control over script execution.
2. Using ProcessBuilder
The first option for executing Kotlin scripts involves using the ProcessBuilder class. This approach directly invokes the Kotlin compiler (kotlinc) as an external process. The advantage of this method is that it allows more direct control over the system process, although it requires proper configuration of the Kotlin compiler environment:
fun runScriptUsingProcess(scriptPath: String) {
val processBuilder = ProcessBuilder("kotlinc", "-script", scriptPath)
val process = processBuilder.start()
return process.inputStream.bufferedReader().use {
it.readText()
}
}
First, the runScriptUsingProcess() method constructs a ProcessBuilder to run the kotlinc command with the -script argument, specifying the script path. Subsequently, we capture the output by reading the process’s input stream through a buffered reader. Finally, once the script is complete, we return the output:
@Test
fun `run Kotlin script with ProcessBuilder`() {
val scriptFile = File.createTempFile("test", ".kts")
scriptFile.writeText("""
println("Hello, ProcessBuilder!")
""".trimIndent())
val output = runScriptUsingProcess(scriptFile.absolutePath).trim()
assertEquals("Hello, ProcessBuilder!", output)
}
The test writes a Kotlin script to a temporary file and executes it with ProcessBuilder. Finally, we assert that the output contains the expected string, confirming the script runs successfully.
3. Using ScriptEngine
Kotlin’s compatibility with Java’s ScriptEngine API provides another method for executing .kts scripts. This approach integrates seamlessly with the JVM’s built-in scripting framework, enhancing versatility in script execution within Java applications.
However, while this method allows for basic script execution, it may not offer the same level of advanced control and customization as other approaches:
fun runKotlinScriptWithEngine(scriptPath: String): String {
val engine = ScriptEngineManager().getEngineByExtension("kts")
val script = File(scriptPath).readText()
val outputStream = ByteArrayOutputStream()
val originalOut = System.out
System.setOut(PrintStream(outputStream))
try {
engine.eval(script)
} finally {
System.setOut(originalOut)
}
return outputStream.toString()
}
In this method, the ScriptEngineManager class actively retrieves an engine capable of executing Kotlin scripts. After that, we read the script from the file and then evaluate it using the engine.
To capture the output effectively, we temporarily redirect System.out to a ByteArrayOutputStream. Once the script runs, we restore the original System.out and subsequently return the captured output.
As usual, we need to unit-test our method for correctness:
@Test
fun `run Kotlin script using ScriptEngine`() {
val scriptFile = File.createTempFile("test", ".kts")
scriptFile.writeText("""
println("Hello from ScriptEngine!")
""".trimIndent())
val output = runKotlinScriptWithEngine(scriptFile.absolutePath).trim()
assertEquals("Hello from ScriptEngine!", output)
}
Similar to the previous test, this one writes a script to a file, runs it using the ScriptEngine, and verifies that the output matches the expected result.
4. Using kscript
Although the previous examples focus on running Kotlin scripts within a Kotlin or JVM application, in contrast, kscript offers a simpler and more convenient way to run standalone Kotlin scripts from the command line.
Specifically, kscript is a tool designed to facilitate the execution of Kotlin scripts directly from the terminal. It’s a great tool for running Kotlin scripts as if they were traditional shell scripts.
To install kscript, follow the instructions in the kscript GitHub repository. Once installed, we can use it to execute .kts files directly.
For example, let’s write a simple script my-script.kts that prints a message to the console:
println("Hello, KScript!")
Once the script is saved as my-script.kts, we can run it from the terminal with the kscript command:
kscript my-script.kts
Running this script will produce the output:
Hello, KScript!
This invokes kscript, which handles all necessary dependencies, compiles the script if needed, and runs it in one go.
5. Conclusion
In this article, we’ve explored multiple techniques to execute Kotlin scripts, ranging from invoking external processes with ProcessBuilder, to using ScriptEngine for embedding scripts in our applications, to leveraging the lightweight kscript tool for running standalone Kotlin scripts. Each approach provides different levels of control and flexibility, depending on the use case.