运行 的安全方法是使用 `sudo` 启动 sbt 任务启动子进程

Secure way to run have sbt task launch subprocess with `sudo`

我正在使用 SBT 编写一些 DevOps 脚本,我需要一个任务来通过 sudo 启动一个子进程,用户可以在 sudo 提示符下安全地输入他们的密码。 sbt 中有没有办法允许子进程暂时但完全捕获控制台的 stdin,将密码击键传递给 sudo

我还没有在 SBT 中看到这样做,但我可以建议在 sudoers 列表中添加用户(或用户组)和命令,这样它就不会提示输入密码。

我完全成功地做到了这一点 运行 来自 SBT 的一些 Docker 任务。

例如在 build.sbt:

docker := {
  (test in Test).value
  (stage in Docker).value
  "./docker-stuff.sh" !
}

...然后 docker-stuff.shsudo 命令。

简答

您可以在 build.sbtBuild.scala 中使用以下代码:

import sbt.Process

val sudo = taskKey[Unit]("Executes commands with sudo!")

sudo := {
  Process("sudo ls /", new File(".")).!<
}

您必须将 "sudo ls /" 更改为您想要 运行 的实际命令,并将 "." 更改为您想要 运行 该命令所在的目录。

这可能是最安全的选择,因为您将标准输入连接到分叉进程,但缺点是当前进程将被阻塞,直到新生成的进程终止。

这是如何运作的

Sbt Process and ProcessBuilder 有很多有用的实用程序来处理进程。

来自 !< 方法的 Scaladocs:

Starts the process represented by this builder, blocks until it exits, and returns the exit code. Standard output and error are sent to the console. The newly started process reads from standard input of the current process.

如果不想阻塞当前进程,那么任务会稍微困难一些。在那种情况下,您必须使用 ProcessIO 并向其输入流提供输入,但是没有安全的方法从标准输入中获取密码。

备选

另请注意,StringFileURL 类 将隐式转换为 ProcessBuilder,您可以从中 运行一个Process。所以你可以改用下面的代码:

sudo := "sudo ls /".!<

在这种情况下,运行ning Java 进程的当前工作目录将用作工作目录。