Развернутое R-приложение с аварийным завершением Shiny с "не удалось найти функцию"httpdPort""

У меня есть приложение, созданное с Shiny (учебник, где ui.R а также server.R взяты отсюда: http://shiny.rstudio.com/tutorial/lesson1/). У меня есть эти два файла в shiny-frontend папка, и если я runApp("shiny-frontend") локально в RStudio - все отлично работает, и я вижу учебник в своем браузере.

Теперь я хочу, чтобы это же приложение было добавлено в Bluemix через cloudfoundry. Я использую это: http://www.ibm.com/developerworks/library/ba-rtwitter-app/ в качестве учебного пособия, но борюсь с ошибкой.

у меня есть start.r файл, который я запускаю как R -f ./start.r --gui-none --no-save, Я использую https://github.com/virtualstaticvoid/heroku-buildpack-r buildpack.

мой start.r выглядит так (взято из руководства по bluemix с очень незначительными изменениями):

library(shiny)

if (Sys.getenv('VCAP_APP_PORT') == "") {
  print("Running Shiny")
  runApp("shiny-frontend")
} else {
  # In case we're on Cloudfoundry, run this:
  print('running on CF')

  # Starting Rook server during CF startup phase - after 60 seconds start the actual Shiny server
  library(Rook)
  myPort <- as.numeric(Sys.getenv('VCAP_APP_PORT'))
  myInterface <- Sys.getenv('VCAP_APP_HOST')
  status <- -1

  # R 2.15.1 uses .Internal, but the next release of R will use a .Call.
  # Either way it starts the web server.
  if (as.integer(R.version[["svn rev"]]) > 59600) {
    status <- .Call(tools:::startHTTPD, myInterface, myPort)
  } else {
    status <- .Internal(startHTTPD(myInterface, myPort))
  }

  if (status == 0) {
    unlockBinding("httpdPort", environment(tools:::startDynamicHelp))
    assign("httpdPort", myPort, environment(tools:::startDynamicHelp))

    s <- Rhttpd$new()
    s$listenAddr <- myInterface
    s$listenPort <- myPort

    s$print()
    Sys.sleep(60)
    s$stop()
  }


  # run shiny server
  sink(stderr())
  options(bitmapType='cairo')
  getOption("bitmapType")
  print("test")
  write("prints to stderr", stderr())
  write("prints to stdout", stdout())
  write(port, stdout())
  runApp('shiny-frontend',port=myPort,host="0.0.0.0",launch.browser=F)
}

И мой init.rвыглядит так:

install.packages("shiny", clean=T)
install.packages("Rook", clean=T)

Затем, когда я бегу, все развернуто правильно, но затем, когда я пытаюсь идти по маршруту, я вижу ошибку в журнале:

* ERR Calls: <Anonymous> -> startDynamicHelp
* ERR Execution halted
* ERR Error in startDynamicHelp(FALSE) : could not find function "httpdPort"

Я также заметил, что назначенный порт каждый раз отличается, что странно, и маршрут в сводной панели bluemix не упоминает об этом. Но я вывожу порт в журнал и использую этот номер.

Кроме того, то, как я это делаю, кажется слишком сложным, поэтому, если кто-нибудь может предложить более простой способ, я был бы признателен

1 ответ

Решение

Мне потребовалось некоторое время, чтобы понять, что эта ошибка выдается R, потому что она не может найти функцию (не значение) httpdPort, Вместо привязки httpdPort для функции вы привязываете его к значению. Линия s$stop() тот, который вызывает проблемы. Это вызывает startDynamicHelp что предполагает, что httpdPort является функцией, определенной в среде tools,

Чтобы исправить эту проблему, вы можете изменить блок if (status == 0){...} в вашем коде:

if (status == 0) {
    getSettable <- function(default){
                       function(obj = NA){if(!is.na(obj)){default <<- obj};
                                  default}
                   }
    myHttpdPort <- getSettable(myPort)
    unlockBinding("httpdPort", environment(tools:::startDynamicHelp))
    assign("httpdPort", myHttpdPort, environment(tools:::startDynamicHelp))

    s <- Rhttpd$new()
    s$listenAddr <- myInterface
    s$listenPort <- myPort

    s$print()
    Sys.sleep(60)
    s$stop()
}
Другие вопросы по тегам