Reputation: 257
I am using RStudio on Windows 10. Please help me get the output of the R System function to be included in my output document when I knit the markdown file. I have tried many combinations of chunk options that I found in the official reference.
In the Console, the output of:
system('java -version')
is:
java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)
However, when I put it into an RMardown document:
---
title: "Code Chunk Not Displaying Output"
output: html_document
---
```{r test}
system('java -version')
```
Unfortunately, instead of showing my java version, the formatted output for the chunk is:
## [1] 0
Upvotes: 0
Views: 1489
Reputation: 160407
system2("java", "-version", stderr = TRUE)
(If you want to make sure that any command called, not just java
, then (1) assume it accepts -version
, and (2) also add stdout = TRUE
. If there is no stdout
to capture, then it does not harm.)
This is a (quick) discussion about file descriptors (fd). When a program runs, it may accept data (or something) on file descriptor 0, which is typically known as standard input or stdin
. It can emit (send text/values/data) out on any number of file descriptors, but typically most programs use at least fd1 (standard output, stdout
) and often but not always fd2 (standard error, stderr
). The reason is so that command-line utilities can capture intended output on stdout
and capture errors/warnings on stderr
. In shell-speak:
# /-- this is redirecting stdout
# | /-- this is redirecting stderr
# v v
$ somecommand -arg1 -arg2 > output.log 2> error.log
Will send the intended (normal) output to the file output.log
, and anything non-standard (or out-of-band or warnings or debugging or ...) to error.log
. In many circumstances, an empty error.log
is a good thing and "expected".
During my initial testing, since I don't have java, I was using ls --version
, and /bin/ls
sends its version information out on stdout
. Apparently, java
uses stderr
.
(I finally verified with by switching to a command which should use stderr
: the easiest way to reproduce without java
around was:
---
title: "Code Chunk Not Displaying Output"
output: html_document
---
```{r test}
system("ls --versiommmmm", intern = TRUE)
```
which (1) did not have the expected ls: unknown option -- versiommmmm
output, and (2) returned ## [1] 2
instead, indicating an exit status of 2. (Most utilities use an exit status of 0 to mean "all good", and anything else as an error. Some utilities go so far as the emit a specific exit status for specific errors, but it's generally safe to assume "not 0
means some error condition".)
In order to get R to do a system call and catch the stderr, I switched to system2
, which allows one to capture stderr=
(as well as stdout=
separately).
Notes:
system2
takes the command to run as its first argument, and then all subsequent arguments as a character vector, so something like:
system2("java", c("Echo", "Drink Hot Java"))
would call java
with two arguments, "Echo"
and the string. (Actually, that's not quite right ... see the next bullet.)
both system
and system2
do really poor jobs of quoting things. If any of your arguments have embedded spaces, such as the call in the previous bullet, then the command will actually seem individual arguments. So the previous bullet's command actually calls java
with four arguments, and is equivalent to c("Echo", "Drink", "Hot", "Java")
. (I and many people consider this a significant problem with system2
. The workarounds include using shQuote
yourself or using the processx
package, which does things right.)
different arguments, where the equivalent of system(..., intern=TRUE)
is system2(..., stdout=TRUE)
... and you gain the ability to use stderr=
.
Upvotes: 1