How do I redirect stderr and stdout to file for a Ruby script?
How do I redirect stderr and stdout to file for a Ruby script?
Asked Answered
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
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 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")
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 def silence_stdout
$stdout = File.new( '/dev/null', 'w' )
yield
ensure
$stdout = STDOUT
end
Good, but this is better, in case STDOUT was something else. https://mcmap.net/q/354515/-how-do-i-temporarily-redirect-stderr-in-ruby –
Drive
./yourscript.rb 2>&1 > log.txt
will redirect stdout and stderr to the same file.
Assuming you are running on *nix –
Hallucinogen
@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 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"
© 2022 - 2024 — McMap. All rights reserved.