2016-07-05 3 views
6

Als Teil meines R-Workflows für eines meiner Projekte lade ich Daten aus einer postgreSQL-Tabelle auf einem Remote-Server ein.Machen Sie einen SSH-Tunnel zu einem anderen Computer über R, um auf die postgreSQL-Tabelle zuzugreifen

Mein Code sieht so aus (anonymisierte Anmeldeinformationen).

I zunächst eine SSH-Verbindung zum entfernten Server im Terminal öffnen.

ssh -p Port -L LocalPort:IP:RemotePort servername" 

verbinde ich dann an die Postgres-Datenbank in R.

# Load the RPostgreSQL package 
library("RPostgreSQL") 

# Create a connection 
Driver <- dbDriver("PostgreSQL") # Establish database driver 
Connection <- dbConnect(Driver, dbname = "DBName", host = "localhost", port = LocalPort, user = "User") 

# Download the data 
Data<-dbGetQuery(Connection,"SELECT * FROM remote_postgres_table") 

Dieser Ansatz funktioniert gut, und ich bin in der Lage, die Daten ohne Probleme herunterladen.

Allerdings möchte ich den ersten Schritt - d. H. Die Erstellung der SSH-Verbindung - in R statt im Terminal machen. Hier ist mein Versuch, dies zu tun, mit begleitendem Fehler. ganz in R

# Open the ssh connection in R 
system("ssh -T -p Port -L LocalPort:IP:RemotePort servername") 

# Load the RPostgreSQL package 
library("RPostgreSQL") 

# Create a connection 
Driver <- dbDriver("PostgreSQL") # Establish database driver 
Connection <- dbConnect(Driver, dbname = "DBName", host = "localhost", port = LocalPort, user = "User") 

# Download the data 
Data<-dbGetQuery(Connection,"SELECT * FROM remote_postgres_table") 

Error in postgresqlExecStatement(conn, statement, ...) : 
RS-DBI driver: (could not Retrieve the result : server closed the connection unexpectedly 
This probably means the server terminated abnormally 
before or while processing the request. 

meine Frage Um zu klären, ich diesen gesamten Workflow durchführen möchten (postgreSQL Daten, die eine Verbindung herstellen, laden) ohne Stufen in Terminal.

+2

'system2 ("ssh", c (verwenden "- L8080: localhost: 80", "N", "-T", "otherhost"), wait = FALSE) 'hat für mich auf Linux funktioniert. Funktioniert jedoch nicht unter Windows, wahrscheinlich weil 'fork' nicht vorhanden ist, also könnten Sie etwas im Hintergrund benötigen (zB' parallel' oder ['future'] (https://github.com/HenrikBengtsson/future)) um eine weitere R Sitzung zu starten). Stoppen könnte es mit 'tools :: pskill' funktionieren, nicht getestet. – r2evans

+0

@ r2evans Arbeitete für mich, danke. – Andy

Antwort

2

Gemäß @ r2evans Vorschläge.

##### Starting the Connection ##### 
# Start the ssh connection to server "otherhost" 
system2("ssh", c("-L8080:localhost:80", "-N", "-T", "otherhost"), wait=FALSE) 

Sie können den Prozess beenden, indem Sie die PID manuell suchen und eingeben oder automatisch alle PIDs, die Ihrem Servernamen entsprechen, löschen. Seien Sie gewarnt, dass Sie diese letztere Version nur verwenden möchten, wenn Sie einen relativ eindeutigen Servernamen verwenden, der in anderen Prozessen wahrscheinlich nicht doppelt vorhanden ist.

##### Killing the Connection: Manually ##### 
# To end the connection, find the pid of the process 
system2("ps",c("ax | grep otherhost")) 
# Kill pid (x) identified by the previous grep. 
tools::pskill(x) 

##### Killing the Connection: Automatically ##### 
# To end the connection, find the pid of the process 
GrepResults<-system2("ps",c("ax | grep otherhost"),stdout=TRUE) 
# Parse the pids from your grep into a numeric vector 
Processes<-as.numeric(sub(" .*","",GrepResults)) 
# Kill all pids identified in the grep 
tools::pskill(Processes) 
0

Als Alternative Sie plink mit shell

library(RPostgreSQL) 
drv <- dbDriver("PostgreSQL") 

cmd<- paste0(
    "plink ", 
    # use key and run in background process 
    " -i ../.ssh/id_rsa -N -batch -ssh", 
    # port forwarding 
    " -L 5432:127.0.0.1:5432", 
    # location of db 
    " [email protected]" 
) 

shell(cmd, wait=FALSE) 
# sleep a while before the the connection been established. 
Sys.sleep(5) 

conn <- dbConnect(
    drv, 
    host = "127.0.0.1", 
    port=5432, 
    dbname="mydb", 
    password = "pass" 
) 

dbListTables(conn) 
Verwandte Themen