How do I redirect stderr and stdout to file for a Ruby script?
Asked Answered
L

5

48

How do I redirect stderr and stdout to file for a Ruby script?

Leffen answered 10/6, 2010 at 21:17 Comment(1)
Related question: #4459830Ultimo
P
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
Palaeo answered 10/6, 2010 at 21:38 Comment(4)
How can normal $stdout be restored again afterwards?Lottery
why should we use reopen method ? it's mean that if "out.txt" is not exists, it will be created?Belletrist
Take a look at this answer on how to restore $stdout afterwards.Guidepost
You'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.Oneil
M
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")
Manvil answered 13/4, 2011 at 17:26 Comment(3)
What do you mean by "helping a process become a daemon"?Omni
In 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?Manvil
Note: If using built-in Process.daemon it can do this for you. See docs here.Unset
F
10
def silence_stdout
  $stdout = File.new( '/dev/null', 'w' )
  yield
ensure
  $stdout = STDOUT
end
Fosse answered 29/5, 2012 at 23:51 Comment(1)
Good, but this is better, in case STDOUT was something else. https://mcmap.net/q/354515/-how-do-i-temporarily-redirect-stderr-in-rubyDrive
Y
4
./yourscript.rb 2>&1 > log.txt

will redirect stdout and stderr to the same file.

Yiddish answered 10/6, 2010 at 21:19 Comment(4)
Assuming you are running on *nixHallucinogen
@Steve: I think > works on Windows - I'm not sure about 2> though.Ultimo
This 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.Lumberman
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)Almaraz
D
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"
Dullard answered 20/10, 2020 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.