我正在嘗試編寫一個Ruby腳本,它在後臺運行mount
命令以交互方式運行。問題是,如果我將mount命令的輸入和輸出重定向到管道,它不起作用。不知何故,mount似乎意識到它不是直接與stdin/stdout交談,而是摔倒了。要麼是這樣,要麼是影響所有交互命令的更廣泛的問題;我不知道。如何從(Ruby)腳本交互地運行mount命令?
我希望能夠逐行解析輸出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
和其他解決方案的主機 - 基本上,如果它是在谷歌,我我試過了。看來如果我沒有通過它真正的殼,並故意阻止,登上知道。參見:
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.
我甚至嘗試產卵一個真實殼(例如bash中),並通過輸入管發送mount命令給它。同樣的問題。
請忽略上述任何明顯的錯誤:今晚我已經嘗試了幾種解決方案,所以實際的代碼已被多次重寫。我從記憶中寫下了上述內容。
我想是這樣的:有爭論
- 運行mount命令,獲取它的輸入和輸出管道流
- 等待輸出管
- 回答具體問題,首先具體問題寫入輸入管
- 等待輸出管道上的第二個具體問題
- ...等...
依此類推。
我不知道'mount'是交互式的。但是如果你的系統提供了'mount'的交互式版本,那麼這可以很好地測試它的stdin/stdout是否是ttys(並且因此可能是交互式的),並且如果行爲不同的話。在這種情況下,你所能做的就是嘗試用一種不是交互式的命令行用法替換你的交互式用法(我寧願這樣做),或者你可以咬着酸蘋果並創建一個tty來與交互'mount'命令。 – Alfe 2014-09-29 23:53:49
@Alfe:嗯....我將如何創建一個tty?我甚至不確定什麼是tty!是的,mount.ecryptfs是交互式的。非交互式方法是可能的,但無法非交互式地驗證密碼。 – 2014-09-30 00:59:40
對於任何未來絆倒這個問題的人,請查看'PTY.spawn'和'IO.select'。感謝Alfe的提示。 – 2014-10-03 22:11:52