Where does the output of Rscript go?

[This article was first published on Category R on Roel's R-tefacts, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

We often run R interactively, through Rstudio or in the terminal. But you can also run Rscripts without manual intervention. Using Rscript. But where does the output go?

Warning: This post is very linux/unix (macos) centred, I don’t know how this works in Windows.
Also I’m using the standard shell in linux ‘bash’ I believe there are some small nuances in the commands in other shells like zsh.

Why do I want to know this?

In my work we run a lot of periodic scripts, a lot of python but also R scripts. These scripts download data from a database, do calculations and write back to a database.
They are scheduled and run without supervision. But if something goes wrong we want to know what happened and so we look at the logs. If you know these tricks you can write good scripts that are easy to debug.

Testing the output streams

I created this file message_warning.R

#!/usr/bin/env Rscript
print("this is a print \n")
cat("this is a cat \n")
message("this is a message \n")
warning("this is a warning")
stop("this is a stop, or error!")

It contains print(), cat(), message(), warning() and stop().

Run in R interactively

When you run this interactively; source("message_warning.R"), they all show up in the R console.

Rscript interactively

If you execute this file with Rscript it also shows up in the terminal

Rscript message_warning.R

[1] "this is a print \n"
this is a cat
this is a message
Warning message:
this is a warning
Error: this is a stop, or error!
Execution halted

But when you run things in the terminal , you often want to do something with the output.
Maybe you want to search the logs while they are streaming with a grep command.

But what happens when you pipe the output into a file?

Pipe Rscript into a file

I’m using the > command to capture the output and write it to a text file (‘stuff.txt’).

Rscript message_warning.R > stuff.txt

The terminal returns:

this is a message
Warning message:
this is a warning
Error: this is a stop, or error!
Execution halted

And stuff.txt contains:

[1] "this is a print \n"
this is a cat

So print and cat are captured but message and warning are not.
This is because R writes to stdout and to stderr.

Why are there multiple outputs (stdin, stdout, stderr)?

This might not surprise some people, but it did surprise me. There is a long Unix^[And therefore inherited in Linux] tradition of ‘streams’. You read from an input stream ‘standard in’ (stdin) and write to an output stream ‘standard out’ (stdout). Extra warnings and diagnostics are written to a seperate steam ‘standard error. It is a stream independent of standard output and can be redirected separately. This makes it possible to ignore warnings and still work with the output of a program or capture errors in a different file and ignore all the normal messages.

Pipe standard error into a file

But we can also write the sterr to file.

Rscript message_warning.R 2> stuff.txt

Now the terminal outputs the print and cat:

[1] "this is a print \n"
this is a cat

and the stuff.txt file contains the message and error

this is a message
Warning message:
this is a warning
Error: this is a stop, or error!
Execution halted

Capturing both error and print statements

Rscript message_warning.R >& stuff.txt

Lessons learned

The output of message(), warning(), and stop() are written to stderr. You can use this to your advantage: if you only output useful information, like the result of a calculation, prediction, etc. Then you can chain multiple R scripts together to do your work.
If you use print() or cat() remember that this is returned to the user, so it is adviceable to make those results useful. As you can see in the results, print() returns a linenumber and the result ([1] "print"), so this is often not useful or hard to parse.

Print and cat also can’t be disabled! You can suppress messages with suppressMessages() and warnings with suppressWarnings() (you can’t suppress errors, because errors are unrecoverable by default, you can capture them with TryCatch).

Resources

To leave a comment for the author, please follow the link and comment on their blog: Category R on Roel's R-tefacts.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)