2016-04-04 11 views
3

Ich habe eine Anwendung mit Shiny (eine Anleitung, wo ui.R und server.R werden von hier genommen: http://shiny.rstudio.com/tutorial/lesson1/) gebaut ‚konnte nicht Funktion‚httpdPort‘finden‘. Ich habe diese beiden Dateien in shiny-frontend Ordner, und wenn ich runApp("shiny-frontend") lokal in RStudio - alles funktioniert gut und ich sehe das Tutorial in meinem Browser.Eingesetzte R App mit glänzendem Absturz mit

Jetzt möchte ich die gleiche App über Cloudfoundry in Bluemix einfügen. Ich benutze dies: http://www.ibm.com/developerworks/library/ba-rtwitter-app/ als ein Tutorial, aber mit einem Fehler kämpfen.

Ich habe eine start.r Datei, die ich als R -f ./start.r --gui-none --no-save ausführen. Ich verwende https://github.com/virtualstaticvoid/heroku-buildpack-r Buildpack.

Mein start.r sieht wie folgt aus (aus dem Bluemix Tutorial mit einer sehr geringen Modifikationen gemacht):

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) 
} 

Und mein init.r, sieht wie folgt aus:

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

Dann, wenn ich laufe, alles wird korrekt bereitgestellt, aber dann, wenn ich versuche, nach der Route zu gehen, sehe ich einen Fehler im Protokoll:

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

Ich habe auch bemerkt, dass der zugewiesene Port jedes Mal anders ist, was seltsam ist und die Route im bluemix-Dashboard nicht erwähnt. Aber ich gebe den Port zum Protokoll aus und benutze diese Nummer.

Auch die Art, wie ich es tue scheint ein bisschen zu kompliziert, so dass, wenn jemand eine einfachere Möglichkeit vorschlägt, konnte ich es

Antwort

2

schätzen würde es dauerte eine Weile zu verstehen, dass dieser Fehler durch R geworfen weil es die Funktion (nicht den Wert) httpdPort nicht finden kann. Anstatt httpdPort an eine Funktion zu binden, binden Sie sie an einen Wert. Die Linie s$stop() verursacht Probleme. Es ruft startDynamicHelp auf, das davon ausgeht, dass httpdPort eine in der Umgebung tools definierte Funktion ist.

Um dieses Problem zu beheben, können Sie den Block if (status == 0){...} in Ihrem Code ändern:

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() 
}