Развернутое 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()
}