让我们举一个简单的例子:
Process.run("ping", {"google.com"}) do |proc|
proc.output.each_line { |line| puts line }
end
运行一个进程,不断读取其输出并将输出打印到stdout。目前,当我按下一个键时,它会与正在运行的进程的输出一起出现,但是我希望进行某种键处理,因此我可以通过键盘来管理正在运行的进程:停止它,或使用修改后的参数重新启动它。该怎么做?
或者,为了缩小问题范围,如何使该输出-输入对彼此互不阻塞?当前,它需要迈出一步,然后等待其对应事件发生。
Process.run("ping", {"google.com"}) do |proc|
until proc.output.closed?
puts proc.output.gets
puts "Got key: #{STDIN.raw &.read_char}"
end
end
答案 0 :(得分:1)
使用终端进行交互式输入并不像看起来那样简单。您可以尝试使用STDIN.raw &.read_char
。但这是有限的,可能不会使您走得太远。
通常用于此目的的工具是readline
。 stdlib中有Crystal绑定(请参见Readline
)。它们目前没有文档,但应该可以使用。您也可以尝试https://github.com/Papierkorb/fancyline,它是readline
的纯Crystal实现。
答案 1 :(得分:1)
此示例显示如何处理STDIN和单个TCP会话。这通过将处理程序生成到纤维上来起作用。使用some lines more,您可以与多个客户端共享bash或REPL会话。
示例1:长时间运行的过程
#Long running Process, here an interactive shell for example
spawn do
begin
cmd = "bash -i"
Process.run(cmd, shell: true) do | p |
pp p
my.bashpid = p.pid
my.bashinputfd = p.input.dup #get copy of current fd
p.input.puts("exec 2>&1") #stderr > stdout
p.input.puts("echo connected to bash") #send to STDIN of bash
while line = p.output.read_line
puts line #send to STDOUT
#send output of shell process to all online clients
Mc.get_clients.each do |all|
all.puts (line) #send to Client
end
end
end
rescue exception
puts "Error: #{exception.message}"
puts "Shell process has ended, program exits"
exit
end
end
示例2:
require "socket"
#public vars
channel = Channel(String).new
csocket = Socket.tcp(Socket::Family::INET)
socket_conn=false
puts "Welcome:"
spawn do
server = TCPServer.new("0.0.0.0", 9090)
loop do #handle tcp client reconnects - do forever
socket = server.accept
csocket = socket.dup
socket_conn=true
p! socket_conn
print "\r"
while line = socket.gets
channel.send(line)
end
socket_conn=false
p! socket_conn
print "\r"
end
end
spawn do #handle stdin input char by char - do until ctrl-c pressed
while (char = STDIN.raw &.read_char) != '\u{3}' #ctrl-c
channel.send(char.to_s)
end
channel.send('\u{3}'.to_s)
end
loop do #do until cttrl-c
r = channel.receive
if r == "\u0003" #handle ctrl-c from channel
break
end
p! socket_conn
print "\r"
p! r
print "\r"
if socket_conn
csocket.puts "got: #{r}"
end
puts "got: #{r}"
print "\r"
end