Execute an SBT command from a script
bash, sbt, scala, shell
Solution
In order to be able to execute a script and, after that script completes, proceed to execute another sbt command, one approach is to implement a custom sbt command which does the following:
- Executes an external process supplied as its first argument, passing any additional arguments to this process.
- Waits for the external process to finish.
- After the external process finishes, executes another sbt command.
This is demonstrated in this `Build.scala` file:
import sbt._
import Keys._
// imports standard command parsing functionality
import complete.DefaultParsers._
object CommandExample extends Build {
// Declare a project, adding new commands.
lazy override val projects = Seq(root)
lazy val root = Project("root", file(".")) settings(
commands ++= Seq(start, customStart)
)
// A fake "start" command.
def start = Command.command("start") { state =>
println("Fake start command executed.")
state
}
// A command that executes an external command before executing the "start" command.
// The name of the external command is the first parameter.
// Any additional parameters are passed along to the external command.
def customStart = Command.args("customStart", "<name>") { (state, args) =>
if (args.length > 0) {
val externalCommand = args.mkString(" ")
println(s"Executing '$externalCommand'")
externalCommand !
}
"start" :: state
}
}
This is a sample execution:
$ sbt
[info] Loading project definition from /home/fernando/work/github/fernandoacorreia/so24565469/project
[info] Set current project to hello (in build file:/home/fernando/work/github/fernandoacorreia/so24565469/)
> customStart ls -la
Executing 'ls -la'
total 40
drwxr-xr-x 6 fernando fernando 4096 Jul 8 10:52 .
drwxr-xr-x 27 fernando fernando 4096 Jul 8 08:51 ..
-rw-r--r-- 1 fernando fernando 95 Jul 8 10:47 build.sbt
drwxr-xr-x 8 fernando fernando 4096 Jul 8 08:58 .git
-rw-r--r-- 1 fernando fernando 203 Jul 8 09:04 .gitignore
-rw-r--r-- 1 fernando fernando 1082 Jul 8 08:51 LICENSE
drwxr-xr-x 3 fernando fernando 4096 Jul 8 10:51 project
-rw-r--r-- 1 fernando fernando 111 Jul 8 08:51 README.md
drwxr-xr-x 3 fernando fernando 4096 Jul 8 08:57 src
drwxr-xr-x 2 fernando fernando 4096 Jul 8 10:52 target
Fake start command executed.
>
The external command passed as a parameter to `customStart` may be any executable command, e.g. a binary file or a shell script.
To learn more about creating commands, refer to the Commands documentation page.
To learn more about executing external processes, refer to the External Processes documentation page.
The complete example is available for download at this GitHub repository.
Since sbt executes the script (as a child process), that script can't execute commands on the original (parent) sbt process.
It would be possible to capture the script's output, either to `stdout` or to a file, and have the sbt command execute an arbitrary command generated by the script, but that's somewhat convoluted.
Another approach would be to invert the order of execution. Instead of having `sbt` execut the script, the script would be executed first, directly from the shell, and the script would execute the sbt command.
For instance, this script:
#!/bin/bash
echo "Running custom script"
# Insert commands here
sbt start
Produces this output:
$ ./script
Running custom script
[info] Loading project definition from /home/fernando/work/github/fernandoacorreia/so24565469/project
[info] Set current project to hello (in build file:/home/fernando/work/github/fernandoacorreia/so24565469/)
Fake start command executed.
Problem
*decided to start a bounty & edited out information not needed I would like to run a script inside the SBT console that would run an SBT command at the end. How can this be done I wrote a script that allows me to execute shell commands. Typing in `sbt` then `path/to/my-script start` gives me this error: `/bin/sh: start command not found` But `path/to/my-script sbt start` works fine Reason why sbt plugins (such as these) or a custom task won't work in this case: - The script is not written in scala quick edit *I would prefer to execute `start` from a script instead of using custom task/command to run my script More info below I'll explain step by step what I'd like to do (what I'm doing may sound silly to you but please read my response to Etan): Type sbt in my console which will invoke the SBT console Instead of typing `start`, I'd like to run a script which will perform something else that doesn't directly have anything to do with the project and then invoke `start` for me when it's done. Being not too familiar with scripting, script can invoke `#!/bin/sh` commands, so I guess what I'm trying to do is invoke a `#!/bin/sh/<*this-sbt-console*>` command if that's possible Even a workaround like if I can get the script to just print `start` on the terminal and invoke the `enter/return` key after it's done, would suffice other info: - Not using any specific framework - SBT Version = 0.13+