从脚本执行SBT命令

时间:2014-07-04 01:22:44

标签: bash shell scala sbt

* 决定开始赏金&编辑出不需要的信息

我想在SBT控制台内部运行一个脚本,该脚本最后会运行SBT命令。如何做到这一点

我编写了一个允许我执行shell命令的脚本。输入sbt然后path/to/my-script start会输入错误:/bin/sh: start command not found

但是path/to/my-script sbt start工作正常

sbt插件(例如these)或自定义任务在这种情况下不起作用的原因

  • 脚本不是用scala编写的

快速修改

*我更喜欢从脚本执行start而不是使用自定义任务/命令来运行我的脚本

以下更多信息


我会一步一步解释我想做什么(我正在做的事对你来说可能听起来很傻,但请阅读我对Etan的回应):

  1. 在我的控制台中键入sbt,它将调用SBT控制台

  2. 我不想输入start,而是要运行一个脚本,该脚本将执行与项目无直接关系的其他内容,然后为我调用start什么时候完成。

  3. 对脚本不太熟悉,脚本可以调用#!/bin/sh命令,所以我想我想要做的是调用#!/bin/sh/<*this-sbt-console*>命令(如果可能的话)

    即使是一种解决方法,如果我可以让脚本只在终端上打印start并在完成后调用enter/return键就足够了

    其他信息:

    • 不使用任何特定框架
    • SBT Version = 0.13 +

2 个答案:

答案 0 :(得分:11)

为了能够执行脚本,并在该脚本完成后继续执行另一个sbt命令,一种方法是实现自定义sbt命令,该命令执行以下操作:

  1. 执行作为其第一个参数提供的外部进程,将任何其他参数传递给此进程。
  2. 等待外部流程完成。
  3. 外部进程完成后,执行另一个sbt命令。
  4. 这在Build.scala文件中进行了演示:

    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
      }
    }
    

    这是一个示例执行:

    $ 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.
    > 
    

    作为参数传递给customStart的外部命令可以是任何可执行命令,例如,二进制文件或shell脚本。

    要了解有关创建命令的更多信息,请参阅Commands documentation page

    要了解有关执行外部流程的更多信息,请参阅External Processes documentation page

    完整示例可在this GitHub repository下载。

    由于sbt执行脚本(作为子进程),该脚本无法在原始(父)sbt进程上执行命令。

    可以将脚本的输出捕获到stdout或文件,并让sbt命令执行脚本生成的任意命令,但这有点回旋。

    另一种方法是颠倒执行顺序。而不是让sbt执行脚本,脚本将首先直接从shell执行,脚本将执行sbt命令。

    例如,这个脚本:

    #!/bin/bash
    echo "Running custom script"
    # Insert commands here
    sbt start
    

    生成此输出:

    $ ./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.
    

答案 1 :(得分:2)

如你所说“有没有办法告诉脚本在终端上写东西并按回车/输入?”

是的 - 稍微苛刻但非常有效的解决方案是一个名为 expect 的小程序。

http://www.thegeekstuff.com/2010/10/expect-examples/

http://www.admin-magazine.com/Articles/Automating-with-Expect-Scripts

它会让您通过键盘执行任何操作,但会自动执行。它就像UNIX命令提示符的宏播放引擎。