【发布时间】: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]
我已经尝试过subprocess、pty 和许多其他解决方案 - 基本上,如果它在 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.spawn和IO.select。感谢 Alfe 的提示。 -
很抱歉没有更快地再次出现以提供更多提示(但我必须承认我对 Ruby 库并不熟悉,所以我可能不会提供太多帮助),恭喜自己解决,感谢分享解决方案(或至少第二个提示)。
-
阅读您的评论时,我想到了另外两件事:①您的问题非常特别,所以很可能这里没有多少读者最不熟悉任何解决它的方法(所以这里对无用的用户没有什么不好的感觉;可能只是没有人知道)。 ② 如果您自己解决了问题,可以在 StackOverflow 中自己给出答案并接受它。这样其他有类似问题的人就可以在这里找到解决方案,甚至为您的解决方案投票。
标签: ruby linux shell interactive mount