[RUBY] Unterschiedliche Puffer- und Löschregeln, je nachdem, ob die Standardausgabe eine Konsole oder ein anderer Befehl ist

Umgebung

Veranstaltung

Bei Verwendung der Standardausgabe in Ruby scheinen sich die Regeln für das Puffern von Flash zu unterscheiden, je nachdem, ob das Standardausgabeziel die Konsole oder ein anderer Befehl ist.

Lassen Sie uns dies kurz überprüfen. Ruby-Code, der "true" ausgibt, wenn die Standardausgabe mit der Konsole verbunden ist, "false", wenn sie mit dem Befehl verbunden ist, und dann jede Sekunde die Zahlen von 0 bis 4 an die Standardausgabe ausgibt. ist.

main.rb


puts "STDOUT.isatty = #{STDOUT.isatty}"
5.times do |x|
  sleep 1
  puts x
end

Die folgenden "cmd.rb" und "console.rb" führen die Standardausgabe von "ruby main.rb" aus, indem sie an eine Pipe oder Konsole angeschlossen werden, und fügen dem Ausgabeergebnis einen Zeitstempel hinzu.

cmd.rb


require 'open3'

#Zeile für Zeile von schreibgeschützten E / A lesen, Zeitstempel hinzufügen und ausgeben.
puts '*** main.Wenn der Standardausgang von rb mit einem anderen Befehl verbunden ist***'
Open3.popen3('ruby main.rb') do |stdin, stdout, stderr, wait_thr|
  stdout.each do |line|
    timestamp = Time.now.strftime('%F %T')
    puts "#{timestamp} #{line}"
  end
end

console.rb


require 'pty'

#Zeile für Zeile von schreibgeschützten E / A lesen, Zeitstempel hinzufügen und ausgeben.
puts '*** main.Wenn der Standardausgang von rb mit der Konsole verbunden ist***'
PTY.spawn('ruby main.rb') do |read, write, pid|
  read.each do |line|
    timestamp = Time.now.strftime('%F %T')
    puts "#{timestamp} #{line}"
  end
end

Die Ausführungsergebnisse von "cmd.rb" und "console.rb" sind wie folgt.

$ ruby cmd.rb 2>/dev/null
*** main.Wenn der Standardausgang von rb mit einem anderen Befehl verbunden ist***
2020-07-05 16:45:09 STDOUT.isatty = false
2020-07-05 16:45:09 0
2020-07-05 16:45:09 1
2020-07-05 16:45:09 2
2020-07-05 16:45:09 3
2020-07-05 16:45:09 4
$ ruby console.rb 2>/dev/null
*** main.Wenn der Standardausgang von rb mit der Konsole verbunden ist***
2020-07-05 16:45:11 STDOUT.isatty = true
2020-07-05 16:45:12 0
2020-07-05 16:45:13 1
2020-07-05 16:45:14 2
2020-07-05 16:45:15 3
2020-07-05 16:45:16 4

Wenn Sie sich die Zeitstempel ansehen, können Sie sehen, dass die main.rb, deren Standardausgang an die Pipe angeschlossen ist, gepuffert ist. Wenn sie jedoch an die Konsole angeschlossen ist, wird sie Zeile für Zeile gespült.

Ich möchte nicht puffern, auch wenn die Standardausgabe mit einem Befehl verbunden ist

Ich denke, es gibt verschiedene Möglichkeiten, aber ist dies die, die mir vorerst in den Sinn kommt?

--Stellen Sie "STDOUT.sync = true" ein, um die Standardausgabe in den Synchronisationsmodus zu versetzen

Experimentieren wir mit dem ersteren. Ändern Sie die obige main.rb wie folgt.

main.rb


$stdout.sync = true
puts "STDOUT.isatty = #{STDOUT.isatty}"
5.times do |x|
  sleep 1
  puts x
end

Wenn Sie cmd.rb ausführen, das die Standardausgabe von main.rb mit einem anderen Befehl verbindet, können Sie sehen, dass es nicht anders als zuvor gepuffert ist.

$ ruby cmd.rb 2>/dev/null
*** main.Wenn der Standardausgang von rb mit einem anderen Befehl verbunden ist***
2020-07-05 16:51:33 STDOUT.isatty = false
2020-07-05 16:51:34 0
2020-07-05 16:51:35 1
2020-07-05 16:51:36 2
2020-07-05 16:51:37 3
2020-07-05 16:51:38 4

Ich möchte nicht, dass es blinkt, auch wenn der Standardausgang mit der Konsole verbunden ist

Es scheint verschiedene Möglichkeiten zu geben, dies zu tun, aber soweit ich mir vorstellen kann, leiten Sie "$ stdout" zu "StringIO" um und geben Sie die in "StringIO" gespeicherten Inhalte jederzeit an "STDOUT" aus. Da ist so etwas. In diesem Fall sollte main.rb folgendermaßen aussehen:

main.rb


require 'stringio'

StringIO.open do |io|
  #Leiten Sie die Standardausgabe an StringIO um
  $stdout = io

  #Dies ist die ursprüngliche Hauptleitung.Gleich wie rb
  puts "STDOUT.isatty = #{STDOUT.isatty}"
  5.times do |x|
    sleep 1
    puts x
  end

  #Entladen Sie den in StringIO gespeicherten Inhalt an STDOUT
  $stdout = STDOUT
  io.rewind
  puts io.read
end

Wenn Sie console.rb ausführen und sehen, was passiert, wenn main.rb mit der Konsole verbunden ist, werden Sie feststellen, dass die Pufferung wie erwartet erfolgt.

$ ruby console.rb 2>/dev/null
*** main.Wenn der Standardausgang von rb mit der Konsole verbunden ist***
2020-07-05 16:56:38 STDOUT.isatty = true
2020-07-05 16:56:38 0
2020-07-05 16:56:38 1
2020-07-05 16:56:38 2
2020-07-05 16:56:38 3
2020-07-05 16:56:38 4

Recommended Posts

Unterschiedliche Puffer- und Löschregeln, je nachdem, ob die Standardausgabe eine Konsole oder ein anderer Befehl ist
Das Verhalten der Klasse # getClassLoader ändert sich abhängig davon, ob sie in der IDE oder in der JAR ausgeführt wird.