[RUBY] Différentes règles de mise en mémoire tampon et de vidage selon que la sortie standard est une console ou une autre commande

environnement

un événement

Lors de l'utilisation de la sortie standard dans Ruby, il semble que les règles de mise en mémoire tampon flash diffèrent selon que la destination de sortie standard est la console ou une autre commande.

--Si la sortie standard est connectée à une autre commande, mettez-la en mémoire tampon.

Vérifions cela brièvement. Code Ruby qui renvoie «true» si la sortie standard est connectée à la console, «false» si elle est connectée à la commande, puis renvoie les nombres de 0 à 4 sur la sortie standard toutes les secondes. est.

main.rb


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

Les commandes cmd.rb et console.rb suivantes exécutent la sortie standard de ruby main.rb en la connectant à un tube ou à une console, et ajoutent un horodatage au résultat de sortie.

cmd.rb


require 'open3'

#Lisez ligne par ligne à partir d'E / S en lecture seule, ajoutez l'horodatage et la sortie.
puts '*** main.Lorsque la sortie standard de rb est connectée à une autre commande***'
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'

#Lisez ligne par ligne à partir d'E / S en lecture seule, ajoutez l'horodatage et la sortie.
puts '*** main.Lorsque la sortie standard de rb est connectée à la console***'
PTY.spawn('ruby main.rb') do |read, write, pid|
  read.each do |line|
    timestamp = Time.now.strftime('%F %T')
    puts "#{timestamp} #{line}"
  end
end

Les résultats d'exécution de «cmd.rb» et «console.rb» sont les suivants.

$ ruby cmd.rb 2>/dev/null
*** main.Lorsque la sortie standard de rb est connectée à une autre commande***
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.Lorsque la sortie standard de rb est connectée à la console***
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

Si vous regardez les horodatages, vous pouvez voir que le main.rb, qui a une sortie standard connectée au tuyau, est mis en mémoire tampon, mais s'il est connecté à la console, il est vidé ligne par ligne.

Je ne veux pas mettre en mémoire tampon même si la sortie standard est connectée à une commande

Je pense qu'il y a plusieurs façons de le faire, mais est-ce celle qui me vient à l'esprit pour le moment?

--Set STDOUT.sync = true pour mettre la sortie standard en mode synchro --Appelez STDOUT.flush à tout moment.

Expérimentons avec le premier. Modifiez le main.rb ci-dessus comme suit.

main.rb


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

Si vous exécutez cmd.rb, qui connecte la sortie standard de main.rb à une autre commande, vous pouvez voir qu'elle n'est pas mise en mémoire tampon contrairement à avant.

$ ruby cmd.rb 2>/dev/null
*** main.Lorsque la sortie standard de rb est connectée à une autre commande***
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

Je ne veux pas qu'il clignote même si la sortie standard est connectée à la console

Il semble y avoir différentes façons de faire cela, mais pour autant que je sache, "Redirigez $ stdout vers StringIO et affichez le contenu stocké dans StringIO vers STDOUT à tout moment." Il y a quelque chose comme ça. Dans ce cas, main.rb devrait ressembler à ceci:

main.rb


require 'stringio'

StringIO.open do |io|
  #Rediriger la sortie standard vers StringIO
  $stdout = io

  #Ceci est le principal original.Identique à rb
  puts "STDOUT.isatty = #{STDOUT.isatty}"
  5.times do |x|
    sleep 1
    puts x
  end

  #Déchargez le contenu stocké dans StringIO vers STDOUT
  $stdout = STDOUT
  io.rewind
  puts io.read
end

Si vous exécutez console.rb et voyez ce qui se passe lorsque main.rb est connecté à la console, vous verrez qu'il est mis en mémoire tampon comme prévu.

$ ruby console.rb 2>/dev/null
*** main.Lorsque la sortie standard de rb est connectée à la console***
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

Différentes règles de mise en mémoire tampon et de vidage selon que la sortie standard est une console ou une autre commande
Le comportement de la classe # getClassLoader change selon qu'elle est exécutée dans l'EDI ou dans le fichier jar.