How do I redirect stderr and stdout to file for a Ruby script?
Asked
Active
Viewed 3.7k times
5 Answers
70
From within a Ruby script, you can redirect stdout
and stderr
with the IO#reopen
method.
# a.rb
$stdout.reopen("out.txt", "w")
$stderr.reopen("err.txt", "w")
puts 'normal output'
warn 'something to stderr'
$ ls a.rb $ ruby a.rb $ ls a.rb err.txt out.txt $ cat err.txt something to stderr $ cat out.txt normal output

Andrew Grimm
- 78,473
- 57
- 200
- 338

Mark Rushakoff
- 249,864
- 45
- 407
- 398
-
2
-
why should we use reopen method ? it's mean that if "out.txt" is not exists, it will be created? – wind May 17 '16 at 03:43
-
Take a look at [this answer](http://stackoverflow.com/a/22777806/1287376) on how to restore $stdout afterwards. – Matheus Santana Jul 21 '16 at 16:07
-
7You'll need to `$stdout.sync = true` and `$stderr.sync = true` if you hope to, say, tail the file while lines are being written. Otherwise, the lines won't be written out until the process closes, or something else like that flushes the streams. – Pistos Mar 26 '17 at 00:44
13
Note: reopening of the standard streams to /dev/null is a good old method of helping a process to become a daemon. For example:
# daemon.rb
$stdout.reopen("/dev/null", "w")
$stderr.reopen("/dev/null", "w")

argent_smith
- 476
- 6
- 11
-
3
-
4In UNIX in order to make a program a daemon the programmer should not merely fork it into background but also redirect it's standard IO streams. Are you familiar with this? – argent_smith Apr 28 '11 at 17:20
-
Note: If using built-in `Process.daemon` it can do this for you. See [docs here](http://ruby-doc.org/core-2.2.2/Process.html#method-c-daemon). – captainpete Nov 19 '15 at 03:12
10
def silence_stdout
$stdout = File.new( '/dev/null', 'w' )
yield
ensure
$stdout = STDOUT
end

grosser
- 14,707
- 7
- 57
- 61
-
Good, but this is better, in case STDOUT was something else. http://stackoverflow.com/a/4459463/26604 – Kyle Heironimus Apr 24 '13 at 22:17
4
./yourscript.rb 2>&1 > log.txt
will redirect stdout and stderr to the same file.

Richard Fearn
- 25,073
- 7
- 56
- 55
-
4
-
@Steve: I think `>` works on Windows - I'm not sure about `2>` though. – Andrew Grimm Apr 07 '11 at 02:04
-
2This answer also makes assumptions about what shell the user is using, even within *nix. Some shells have different redirection styles, for instance the default behavior of zsh. – Daisy Sophia Hollman Jan 05 '12 at 16:10
-
It does not. Redirection order matters. It first redirects stderr to stdout, making stderr a COPY of the initial stdout, then redirect stdout to the file. Only stdout is redirected to a file. to redirect both stdout and stderr to the same file, use `./yourscript.rb > log.txt 2>&1`. As of 2022, some shells support `&>` or `>&` to redirect both descriptors at the same time (bash 5.2 or zsh 5.8 for example) – exore Oct 11 '22 at 01:15
3
A full example with $stdout and $stderr redirected to a file and how to restore the initial behavior.
#!/usr/bin/ruby
logfile = "/tmp/testruby.log"
@original_stdout = $stderr.dup
@original_stderr = $stderr.dup
$stdout.reopen(logfile, "w")
$stdout.sync = true
$stderr.reopen($stdout)
def restore_stdout
$stdout.reopen(@original_stdout)
$stderr.reopen(@original_stderr)
end
def fail_exit(msg)
puts "- #{msg}" # to the logfile
restore_stdout
$stderr.puts "+ #{msg}" # to standard error
exit!
end
def success_exit(msg)
puts "- #{msg}" # to the logfile
restore_stdout
$stdout.puts "+ #{msg}" # to standard output
exit
end
puts "This message goes to the file"
success_exit "A successful exit message"

Atika
- 1,560
- 18
- 18