如何在捕获输出的同时在 Crystal 中执行 shell 脚本



我想在处理标准输出和标准输出时执行一个shell脚本。目前,我使用 Process.run 执行命令,shell=false和三个管道分别用于 stdin、stdout 和 stderr。我生成光纤以从标准输出和标准输出读取并记录(或以其他方式处理)输出。这对于单个命令非常有效,但对于脚本来说却失败得很糟糕。

我可以在调用Process.run时简单地设置shell=true,但查看 Crystal 源代码,似乎只是在命令行前面加上"sh"。我尝试过在"bash"前面加上前缀,但没有帮助。

诸如重定向(>file)和管道(例如 curl something | bash )似乎不适用于Process.run

例如,要下载一个 shell 脚本并执行它,我尝试了:

cmd = %{bash -c "curl http://dist.crystal-lang.org/apt/setup.sh" | bash}

Process.run(cmd, ...)

添加最初的bash是希望它能使管道操作员能够使用。这似乎没有帮助。我还尝试分别执行每个命令:

script.split("").reject(/^#/, ").each { Process.run(...) }

但是,当然,当命令使用重定向或管道时,这仍然会失败。例如,命令echo "deb http://dist.crystal-lang.org/apt crystal main" >/etc/apt/sources.list.d/crystal.list仅输出:

"Deb http://dist.crystal-lang.org/apt crystal main">/etc/apt/sources.list.d/crystal.list'

如果我使用 `` 反引号执行方法,它可能会起作用;但这样我就无法实时捕获输出。

问题是 UNIX 问题。父进程必须能够访问子进程的 STDOUT。使用管道,您必须启动一个 shell 进程,该进程将运行整个命令,包括| bash而不仅仅是curl $URL。在水晶中,这是:

command = "curl http://dist.crystal-lang.org/apt/setup.sh | bash"
io = MemoryIO.new
Process.run(command, shell: true, output: io)
output = io.to_s

或者,如果您想复制 Crystal 为您所做的工作:

Process.run("sh", {"-c", command}, output: io)

我的理解是基于阅读run.cr文件的源代码。该行为在处理命令和参数的方式上与其他语言非常相似。

如果没有shell=trueProcess.run的默认行为是使用该命令作为可执行文件来运行。这意味着字符串必须是程序名称,没有任何参数,例如 uname将是一个有效名称,因为我的系统上有一个名为 uname 的程序 in /usr/bin .

如果你曾经有过成功使用%{bash -c "echo hello world"}的行为,那么shell=false,那么就有问题了 - 默认行为应该是尝试运行一个名为bash -c "echo hello world"的程序,它不太可能存在于任何系统上。

一旦你传入了'shell=true',那么它就会sh -c <command>,这将允许像echo hello world这样的字符串作为命令工作;这也将允许重定向和管道工作。

shell=true行为通常可以解释为执行以下操作:

cmd = "sh"
args = [] of String
args << "-c" << "curl http://dist.crystal-lang.org/apt/setup.sh | bash"
Process.run(cmd, args, …)

请注意,我在这里使用了一个参数数组 - 如果没有参数数组,您将无法控制如何将参数传递到 shell 中。

第一个版本(带或不带shell=true)不起作用的原因是管道在-c之外,这是您要发送到 bash 的命令。

或者如果你想调用一个shell脚本并获得我刚刚用Crystal 0.23.1尝试的输出,它就可以工作了!

def screen
    output = IO::Memory.new
     Process.run("bash", args: {"lib/bash_scripts/installation.sh"}, output: output)
     output.close
    output.to_s
end

相关内容

  • 没有找到相关文章

最新更新