【问题标题】:Run a shell script from ruby从 ruby​​ 运行 shell 脚本
【发布时间】:2013-07-29 17:42:25
【问题描述】:

我正在使用 Frank 进行 iOS 测试。它也是一种使用黄瓜的红宝石。我有一个“给定”步骤来检查应用程序是否正在运行或是否已崩溃。如果我的步骤发现它已经崩溃,我想再次启动该应用程序。我使用存储在黄瓜 .feature 文件附近某处的 shell 脚本启动应用程序。

如何从该步骤定义中调用脚本?

【问题讨论】:

    标签: iphone ios ruby shell frank


    【解决方案1】:

    你可以通过几种不同的方式做到这一点

    Kernel.system "command"
    %x[command]
    `command`
    

    【讨论】:

    • 顺便说一句,你不需要Kernel.;默认情况下,该模块已包含在 Object 中。或类似的东西。
    • 是的,除非您有同名的本地方法,否则 Kernel 前缀是多余的,但它与查找文档相关。那些随处可见的神奇方法,通常都在 Kernel 中。
    • 命名空间总是好的,正如@tadman所说的确切原因。
    【解决方案2】:

    正如其他答案所建议的那样,有很多方法可以从 Ruby 执行 shell 脚本,但它们的创建方式并不相同。我将尝试更详细地解释我所知道的所有方法。

    反引号

    `command arg1 arg2`
    %x(command arg1 arg2)
    

    在子 shell 中运行命令并返回命令的输出。命令及其参数以反引号分隔的字符串形式提供。另一种语法是%x(...),用于避免转义问题,例如当您要执行包含反引号的命令时。括号可以替换为其他分隔符,例如[]{}!!,......以便能够解决任何转义问题。

    Stderr 正常打印,Stdout 被抑制。返回命令的标准输出。这意味着您可以使用反引号将命令的输出放入变量中以供进一步处理。

    内核.exec

    exec("command arg1 arg2")
    exec("command", "arg1", "arg2")
    

    通过运行命令替换当前进程。命令及其参数以普通字符串或以逗号分隔的字符串列表的形式提供。如果您已经有一个参数列表作为数组,这可能会很有用。输出保持原样,即会像直接运行命令一样打印到控制台。

    内核系统

    system("command arg1 arg2")
    system("command","arg1 arg2")
    

    类似于Kernel.exec,但再次在子shell 中运行。如果进程正确退出(状态 0),则返回 true,否则返回 false。这在if-statements 中很有效。

    内核.spawn

    pid = spawn("command")
    # do other stuff
    Process.wait(pid)
    

    类似于Kernel.system,但会产生一个子进程来运行指定的命令。因此,除非使用Process.wait,否则父进程不会等待命令完成执行。返回值是衍生进程的 PID。

    IO.popen

    io = IO.popen("command")
    IO.popen("command") {|io| ... }
    

    再次在子进程中运行命令,但允许对 IO 进行更大的控制。子进程的 stdout 和 stdin 连接到一个 IO 对象,该对象可以作为返回值或块参数访问。如果通过返回值获取,IO对象在使用io.close后需要关闭。

    【讨论】:

      【解决方案3】:

      打开3

      对于比systemIO.popen 更高级的用例,您可以使用Ruby 标准库中的Open3。它的popen3 方法允许您手动与子进程的标准输入、标准输出和标准错误进行交互。 Open3 的 popen2 方法是一样的,只是它没有给你 stderr。一个使用popen2的例子:

      require 'open3'
      
      Open3.popen2("wc -c") do |stdin, stdout, status_thread|
        stdin.print "answer to life the universe and everything"
        stdin.close
        p stdout.gets #=> "42\n"
      end
      

      【讨论】:

        【解决方案4】:

        Here are some nice ways。反引号可能是侵入性最小的。但请注意:正如 tadman 所指出的,exec 会终止调用进程,这可以通过创建子进程或使用 system 来避免。

        【讨论】:

        • 很好的链接!你护目镜.. :)
        • 请记住,exec 有效地终止了调用进程,因此您永远不会得到响应,因此它可能是该列表中的最后一个。为什么它最“可读”?
        • 我没有意识到它会这样做......至于可读性,不熟悉 Ruby 的人可能会很快弄清楚它的作用,而不是反引号。
        • 他们想不通的是它会终止你的进程并且永远不会返回任何东西,所以真的应该避免它。反引号是 Ruby 与 Perl 的共同点,所以这并不完全出乎意料。
        • 好的,我已更新答案以反映此信息。感谢您的输入! :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-28
        • 2010-12-08
        • 2015-05-15
        相关资源
        最近更新 更多