【问题标题】:How to interactively run mount command from a (Ruby) script?如何从(Ruby)脚本交互式运行挂载命令?
【发布时间】:2014-11-24 11:10:02
【问题描述】:

我正在尝试编写一个在后台运行mount 命令交互式 的Ruby 脚本。问题是,如果我将 mount 命令的输入和输出重定向到管道,它就不起作用。不知何故,mount 似乎意识到它没有直接与 stdin/stdout 对话并摔倒了。要么是这样,要么是会影响所有交互式命令的更广泛的问题;我不知道。

我希望能够逐行解析mount 的输出,并在它提问时将答案推送到其输入管道中。这不应该是一个不合理的期望。有人可以帮忙吗?

例子:

def read_until(pipe, stop_at, timeoutsec = 10, verbose = false)
    lines = []; line = ""
    while result = IO.select([pipe], nil, nil, timeoutsec)
        next if result.empty?
        begin
            c = pipe.read(1) rescue c = nil
        end
        break if c.nil?

        line << c
        break if line =~ stop_at

        # Start a new line?
        if line[-1] == ?\n
            puts line if verbose
            lines << line.strip
            line = ""
        end
    end
    return lines, line.match(stop_at)
end
cmd = "mount.ecryptfs -f /tmp/1 /tmp/2"
status = Open3::popen2e(cmd) { |i,o,t|
    o.fcntl(3, 4)   # Set non-blocking (this doesn't make any difference)
    i.fcntl(3, 4)   # Set non-blocking (this doesn't make any difference)
    puts read_until(o, /some pattern/, 1, true)   # Outputs [[], nil]
}

我也试过spawn:

a, b = IO.pipe
c, d = IO.pipe
pid = spawn(cmd, :in=>a, :out=>d)
puts read_until(c, /some pattern/, 1, true)   # Outputs [[], nil]

我已经尝试过subprocesspty 和许多其他解决方案 - 基本上,如果它在 Google 上,我已经尝试过了。似乎 mount 只是 知道 如果我没有将它传递给一个真正的 shell,并故意阻止它。见:

pid = spawn(cmd, :in=>STDIN, :out=>STDOUT)             # Works
pid = spawn(cmd, :in=>somepipe, :out=>STDOUT)          # Blocks after first line of output, for no reason whatsoever. It's not expecting any input at this point.

我什至尝试生成一个真正的 shell(例如 bash)并通过输入管道将 mount 命令发送给它。同样的问题。

请忽略以上任何明显错误:我今晚尝试了几种解决方案,所以实际代码已经重写了很多次。以上是我凭记忆写的。

我想要的是以下内容:

  • 运行带参数的 mount 命令,为其输入和输出流获取管道
  • 等待输出管道上的第一个特定问题
  • 通过写入输入管道回答具体问题
  • 等待输出管道上的第二个特定问题
  • ...等...

等等。

【问题讨论】:

  • 我不知道mount 是交互式的。但是,如果您的系统提供了mount 的交互式版本,那么这可以很好地测试它的标准输入/标准输出是否是 ttys(因此可能是交互式的),如果不是则表现不同。在这种情况下,您所能做的就是尝试用非交互式的命令行用法替换您的交互式用法(无论如何我更喜欢),或者您可以咬一口酸苹果并创建一个 tty 来与交互式进行通信mount 命令。
  • @Alfe:嗯....我将如何创建一个 tty?我什至不确定 tty 是什么!是的,mount.ecryptfs 是交互式的。非交互式方法是可能的,但无法以非交互式方式验证密码。
  • 对于将来遇到此问题的任何人,请查看PTY.spawnIO.select。感谢 Alfe 的提示。
  • 很抱歉没有更快地再次出现以提供更多提示(但我必须承认我对 Ruby 库并不熟悉,所以我可能不会提供太多帮助),恭喜自己解决,感谢分享解决方案(或至少第二个提示)。
  • 阅读您的评论时,我想到了另外两件事:①您的问题非常特别,所以很可能这里没有多少读者最不熟悉任何解决它的方法(所以这里对无用的用户没有什么不好的感觉;可能只是没有人知道)。 ② 如果您自己解决了问题,可以在 StackOverflow 中自己给出答案并接受它。这样其他有类似问题的人就可以在这里找到解决方案,甚至为您的解决方案投票。

标签: ruby linux shell interactive mount


【解决方案1】:

您可能会发现Kernel#system 很有用。它会打开一个子shell,因此如果您可以与用户直接与mount 交互,这将使一切变得更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2011-02-25
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    相关资源
    最近更新 更多