Looking for an options which let me to redirect R diagnostic messages (produces by message()
) to stdout
, not stderr
as it is by default.
message
manual states:
The default handler sends the message to the stderr() connection.
So the question is how can I change this default behavior? still leaving redirection of warning()
and stop()
intact.
Already tried sink type='message'
but it redirects all (messages, warnings, errors).
If anyone is willing to test, this is sample script exec_test.R
:
print("using print")
cat("using cat\n")
message("using message")
warning("using warning")
stop("using stop")
q("no")
which then will be executed by:
Rscript exec_test.R 1>> exec_test.Rout 2>> exec_test_error.Rout
I don't what to use 2>&1
because my script produce tons of message
s and very rarely the real errors so I need to store those logs in separate files.
Warning logs are not errors. None of these should go to stderr by default. Only error logs should go to stderr.
Understanding the concept of redirections and file descriptors is very important when working on the command line. To redirect stderr and stdout , use the 2>&1 or &> constructs.
To display ( or print) a text with R, use either the R-command cat() or print(). Note that in each case, the text is considered by R as a script, so it should be in quotes. Note there is subtle difference between the two commands so type on your prompt help(cat) and help(print) to see the difference.
The regular output is sent to Standard Out (STDOUT) and the error messages are sent to Standard Error (STDERR). When you redirect console output using the > symbol, you are only redirecting STDOUT. In order to redirect STDERR, you have to specify 2> for the redirection symbol.
Using sink
. Here's a modification of your code:
sink(stdout(), type = "message") # sink messages to stdout
print("using print")
cat("using cat\n")
message("using message")
warning("using warning")
sink(NULL, type="message") # close the sink
warning("after ending sink") # this will be the only thing in your err file
q("no")
The OP showed the execution happening via the Rscript command and using some I/O redirection. If you want to use redirection to log everything and only show to console on error, the best method I've found is to use ||
to check if the script had non-zero exit status before printing to screen:
Rscript myrscript.R > temp.log 2>&1 || cat temp.log
This method relies strictly on the exit code for printing, which only partly gets around message()
going to stderr, but I thought this example helpful to mention since messages won't necessarily trigger a non-zero exit status and you can continue to log quietly with this method.
If you'd like to go one step further and keep appending to a single log file, then this will work:
Rscript myrscript.R > temp.log 2>&1 || cat temp.log && cat temp.log >> persistent.log && rm temp.log
The pseudocode for this command is:
stderr
and stdout
into temp.logWhile this is very likely not a best practice, you could override message
with a version that writes to stdout()
by default, right?
message <- function (..., domain = NULL, appendLF = TRUE)
{
args <- list(...)
cond <- if (length(args) == 1L && inherits(args[[1L]], "condition")) {
if (nargs() > 1L)
warning("additional arguments ignored in message()")
args[[1L]]
}
else {
msg <- .makeMessage(..., domain = domain, appendLF = appendLF)
call <- sys.call()
simpleMessage(msg, call)
}
defaultHandler <- function(c) {
cat(conditionMessage(c), file = stdout(), sep = "")
}
withRestarts({
signalCondition(cond)
defaultHandler(cond)
}, muffleMessage = function() NULL)
invisible()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With