Stephen Williams
Stephen Williams

Reputation: 631

Return system console output to user interface

I have a bash script that i'm running using shiny and system. It takes a long time to run so I'd like to provide feedback to the user about progress. In the bash script I have messages that periodically updates the user and I'm trying to find a way to have them printed in the UI.

Here is a minimal working example for which I'd like to have "Output 1" and "Output 2" returned to the user as they appear in the console.

Any help is greatly appreciated.

library(shiny)

ui <- fluidPage(
  actionButton("run", "Print to Console")
)

server <- function(input, output, session) {
  observeEvent(input$run,{
    system(c("echo output 1; sleep 2; echo output 2"))
  })
}

shinyApp(ui, server)

Upvotes: 3

Views: 485

Answers (1)

ismirsehregal
ismirsehregal

Reputation: 33580

I'd suggest to run your system command asynchronously and redirect the output to a log file. In parallel you can continuously read in the logfile via reactiveFileReader.

In contrast, when intern = TRUE the R session (and shiny) is blocked while the command is executed.

Please check the following:

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)

result

PS: As an alternative you might want to check AsyncProgress from library(ipc).

Upvotes: 2

Related Questions