0

Note: I'm new to Ruby and so the terminology and/or syntax below may be wrong.

Is there a way to watch STDOUT my ruby process without blocking the rest of my code? Something like:

$stdout.read_lines {|line| // This block is executed on each line logged via `puts`
    do_something() if line == 'some interesting string'
}

puts 'Hello world'
puts 'some interesting string' // This would cause the `do_something` line to be executed

I have seen examples where a new process can be created and watched in a similar fashion, but none where the current process's stdout was being watched.

Many thanks.

Edit:

Specifically I am looking to execute some code when this line is executed in my Vagrant setup: https://github.com/cogitatio/vagrant-hostsupdater/blob/master/lib/vagrant-hostsupdater/HostsUpdater.rb#L103

It looks like the message is logged to @ui which I believe is an instance this module https://github.com/hashicorp/vagrant/blob/master/lib/vagrant/ui.rb

Richard Walton
  • 4,789
  • 3
  • 38
  • 49
  • Possible duplicate -- are you looking for something like [this](https://stackoverflow.com/a/22777806/1954610)? – Tom Lord Oct 02 '17 at 11:30
  • It is similar. But, unless I'm misunderstanding the code, that captures the stdout and only makes it accessible after the block has executed. I need to continually listen for input without blocking the process. Also my code has threads which write to stdout that I don't think would get logged by the linked method. Then again, I could be completely wrong :) – Richard Walton Oct 02 '17 at 11:35
  • Listen for **input**? I thought we were only talking about **output**? – Tom Lord Oct 02 '17 at 11:45
  • Also, could there not be a cleaner solution for this, e.g. Tell your code two write to a logger - in which you encapsulate all of this logic? Rather than trying to modify the global `$stdout` behaviour? – Tom Lord Oct 02 '17 at 11:50
  • Indeed. Perhaps I should be more specific with my problem... Please see the edit – Richard Walton Oct 02 '17 at 11:58
  • Hmm, interesting... I wonder if you could figure out where `Vagrant:: UI::Interface` gets initialised, then change the value of `@stdout` to use your own `IOStream` that intercepts the behaviour as described above. – Tom Lord Oct 02 '17 at 13:34
  • I don't have control over the `Vagrant` or `vagrant-hostsupdater` plugin code base. My code runs within the `Vagrantfile` (https://www.vagrantup.com/docs/vagrantfile/version.html). Perhaps changing `$stdout` to myown very early on in the VagrantFile will work... but I'm not sure _how_ I can do this? – Richard Walton Oct 02 '17 at 14:22
  • Why specifically do you need to run some code at that point in Vagrant? I can't imagine a solution this hacky being the right way to solve your problem. – Max Oct 02 '17 at 17:00
  • You need to work on your imagination! :) I want to show a notification (a.k.a growl) on my machine when this occurs. It is often the case I boot my vagrant machine, only to come back to the terminal a few mins later to discover that it's waiting for me to enter my password. I would like to avoid this painful disappointment as I fear I might hurt myself/others. – Richard Walton Oct 03 '17 at 08:57

0 Answers0