Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Side effects of redefining $stdout and $stderr in a Rails app

I'd like to temporarily redirect $stdout and $stderr to a file in a script that will be run by script/runner in a Rails app. Are there any potential side effects to doing so? Will changing the global variable cause the output streams to be redirected in other parts of the Rails application during the duration of my script? What about other libraries or threads used by the script?

like image 895
jrdioko Avatar asked Oct 10 '22 13:10

jrdioko


2 Answers

The standard output and standard error streams are generally accessible in two ways each:

  • $stdout and STDOUT
  • $stderr and STDERR

A sufficiently clever person could also open their own copies using IO.new with a file descriptor argument:

sneaky = IO.new(2, 'w')

And now you have writable access to the standard error stream through sneaky without having anything to do with $stderr or STDERR.

Reassigning $stderr and $stdout should work fine unless something in your code, your gems, or Ruby itself is using the constants (STDOUT, STDERR) or is accessing the streams directly through C's stdio, unix's low level read/write with numeric file descriptors or is opening their own access to the streams using IO.new. I haven't dug into the source but I doubt assigning to $stdout will do anything to stdout in C-land or file descriptor 1 in Unix-land.

If you really need to trap the standard output and error streams then you're probably better off writing a wrapper shell script to redirect the streams for you.


UPDATE: If you're mostly (only?) concerned about changing $stdout and $stderr inside your script/runner bleeding into the rest of your Rails app then you don't have to worry about that. Each process — your script/runner process and however many server processes your main application has running — gets its own set of globals so you can change them all you want in your script without making a mess of your main application. Of course, you still have to worry about gems using STDOUT instead of $stderr or using IO.new to get their own private standard out.

like image 197
mu is too short Avatar answered Oct 20 '22 05:10

mu is too short


I typically run all my cron jobs through a wrapper script which saves stdout/err and prints it all iff the subprocess exits with a non-zero error code (so I get an email from cron on failure).

like image 38
wr0ngway Avatar answered Oct 20 '22 06:10

wr0ngway