How does one show stdout of an external program?

I am writing a graphical wrapper for a (heavy) external program. I want my Shiny program to pause while the program is running; the only thing to be updated should be what the external program sends to stdout and stderr. Is it possible?

Technically, I am calling the external program with processx::run(...), which is similar to system2(..., wait=T). I do not want to run the external program in the background, such as when using system2(..., wait=F)

I am diverting stdout (and stderr) to a log file, so I tried using a reactiveFileReader to display that file on the screen. However, this way does not work, as reactivity is paused when running the external program.

why ? I encourage you to say more about this as it would seem to contradict your desire to do other things in your R session (like monitor a log and show it to screen )

1 Like

It fits better with the logic of the program. I am writing a graphical wrapper for a linux program. Since it is a wrapper, it should receive parameters, and run the program with them (showing the log). Adding functionality would be an over-complication.

The main use will be running a single instance of the linux program. At the moment the Shiny app does not run multiple instances of it. So for now there is no benefit from running the linux program parallel to the Shiny app (as it could be if I were to run multiple instances of the program).

So unless I come to the conclusion that it is impossible to show the stdout/log in system2(wait=T) mode, that is just the natural thing to do.

One thing I've thought about is creating another Shiny application, designed just to show the log file. When I execute the linux program, I will also execute the Shiny program that will be in charge of showing the log (in a separate window). That's a very un-elegant solution however...

Ideally, I can perhaps show that other Shiny log program within the original graphical wrapper. My hope is that since it is another Shiny application within my own, it would update despite the fact that system() is run with wait=T parameter. Do you think it would work?

I have found out that it is indeed possible to
(1) Create an additional shiny program the only output of which would be the log
(2) inside an iframe, show that program

Even when system(wait=T) runs, the iframe works (not only that it refreshes, it is even responsive to clicks)

Hey Sam,

Regarding your initial question

How does one show stdout of an external program?

please check my answer here.

I'll repost the code:

library(shiny)

file.create("commands.sh", "output.log")
Sys.chmod("commands.sh", mode = "0777", use_umask = TRUE)
writeLines(c("#!/bin/bash", "echo output 1","sleep 2", "echo output 2"), con = "commands.sh")

ui <- fluidPage(
  actionButton("run_intern", "Run intern"),
  textOutput("myInternTextOutput"),
  hr(),
  actionButton("run_extern", "Run extern"),
  textOutput("myExternTextOutput")
)

server <- function(input, output, session) {
  systemOutputIntern <- eventReactive(input$run_intern,{
    system(command = "echo output 1; sleep 2; echo output 2", intern = TRUE)
  })
  
  output$myInternTextOutput <- renderText(systemOutputIntern())
  
  observeEvent(input$run_extern,{
    system(command = "./commands.sh 2>&1 | tee output.log", intern = FALSE, wait = FALSE)
  })
  
  log <- reactiveFileReader(200, session, filePath = "output.log", readLines)
  output$myExternTextOutput <- renderText(log())
}

shinyApp(ui, server)

The stdout can also be passed to R using processx::process via the stdout = "" argument (see ?process) as already shown in my answer to your SO post.

In my opinion hosting a second shiny app to display a log in an iframe is to use a sledge-hammer to crack a nut and in the end it also means running the external process asynchronously (+ wasting resources).

The above approach is using reactiveFilereader to do the same, when running the shell script asynchronously (as mentioned in your 1st post). In my eyes this is a reasonable approach.

PS: check shinyAce to display the reactive log.

Cheers

Just wanted to leave a note: you are absolutely right. I gave the same feeback here.