Создайте туннель SSH к другому компьютеру через R для доступа к таблице postgreSQL

Как часть моего рабочего процесса R для одного из моих проектов, я загружаю данные из таблицы postgreSQL, расположенной на удаленном сервере.

Мой код выглядит так (анонимные учетные данные).

Сначала я открываю соединение SSH с удаленным серверомв терминале.

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

Затем я подключаюсь к базе данных postgres в 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")

Этот подход работает отлично, и я могу загрузить данные без проблем.

Однако я бы хотел сделать первый шаг - создать соединение ssh - в 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.

Чтобы прояснить мой вопрос, я хотел бы выполнить весь этот рабочий процесс (установить соединение, загрузить данные postgreSQL) полностью в R без каких-либо шагов в терминале.

 Andy05 июл. 2016 г., 23:43
@ r2evans Работал на меня, спасибо.
 r2evans05 июл. 2016 г., 23:35
system2("ssh", c("-L8080:localhost:80", "-N", "-T", "otherhost"), wait=FALSE) работал для меня на Linux. Не работает на окнах, хотя, вероятно, из-за отсутствияforkтак что вам может понадобиться что-то в фоновом режиме (например,parallel или жеfuture запустить еще один сеанс R). Остановка может работать сtools::pskillне проверял

Ответы на вопрос(2)

В качестве альтернативы вы можете использоватьпалить с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)
Решение Вопроса

Согласно предложениям @ r2evans.

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

Вы можете убить процесс, вручную найдя и введя pid или автоматически, убив все pids, соответствующие вашему имени сервера. Имейте в виду, что вы хотите использовать эту последнюю версию, только если вы используете относительно уникальное имя сервера, которое вряд ли будет дублироваться в других процессах.

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

Ваш ответ на вопрос