我有一个应用程序可以读取$stdin
数据并对其进行一些处理。我想放入一个信号处理程序来捕获 SIGINT/SIGTERM 并正常关闭(意味着完成数据处理并在完成后退出)。棘手的部分是我希望它停止从 STDIN 读取但能够处理任何缓冲数据。这样就可以启动另一个应用程序并通过相同的 STDIN 管道并在前一个应用程序停止的地方继续处理。
问题是,如果我关闭 STDIN,缓冲的任何内容都会丢失,或者至少无法访问。
基本上我正在尝试这个:
#!/usr/bin/ruby
Signal.trap('INT') do
$stdin.close
end
f = File.open('/tmp/out', 'a')
while (data = $stdin.read(4096)) != "" do
f.write(data)
end
即使我知道它读取了一些数据(strace 显示它),它也会立即在调用中给出IOError
异常。$stdin.read
(我不需要关闭管道,我只是为了打破while
循环。如果有更优雅的方式来打破循环并获取缓冲数据,我很乐意接受。)
我知道这种方法适用于操作系统级别(传递给另一个应用程序时会保留管道缓冲区),因为我可以进行以下测试并且不会丢失任何数据:
# source.rb
i = 0
loop do
puts "%08d" % (i += 1)
end
.
# reader.rb
$stdout.write($stdin.read(9))
$stdin.close
.
ruby /tmp/source.rb | while true; do ruby reader.rb; sleep 1; done
00000001
00000002
00000003
00000004
00000005