Looking for an options which let me to redirect R diagnostic messages (produces by message()
) to stdout
, not stderr
as it is by defaul
While 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()
}
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")
Combining @Thomas and @branch14's answers into one, this is what I came up with:
.stderr_message <- message
message <- function(...) {
sink(stdout(), type = "message")
.stderr_message(...)
sink(NULL, type = "message")
}
I verified this on the shell using this code
.stderr_message <- message
message <- function(...) {
sink(stdout(), type = "message")
.stderr_message(...)
sink(NULL, type = "message")
}
print(1)
message(1)
Without my message()
:
> Rscript bug.R 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stdout: [1] 1
stderr: 1
> Rscript bug.R 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stdout: [1] 1
stdout: 1
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.log