有没有办法通过SSH连接打开和读取文件?

时间:2015-09-18 17:43:17

标签: c++ c linux ssh

我可以访问一些有大量数据的服务器。我无法在计算机上复制整个数据。

我无法在服务器上编译我想要的程序,因为服务器没有我需要的所有库。

我认为服务器管理员不会很高兴看到我来找他并为他安装一些库...

所以,我试着想办法是否有办法打开像

这样的文件
FILE *fopen(const char *filename, const char *mode);

void std::ifstream::open(const char* filename,  ios_base::openmode mode = ios_base::in);

但通过SSH连接。然后像平常程序那样读取文件。

计算机和服务器都在运行linux

5 个答案:

答案 0 :(得分:3)

我假设你正在使用你的Linux笔记本电脑而远程机器是一台超级计算机。

首先是非技术性建议:首先请求权限远程访问数据。在某些工作场所,即使技术上可行,也不允许这样做。

您可以为此目的使用libssh,但是您需要一些编码并阅读其文档。

你可以考虑使用一些FUSE文件系统(在你的笔记本电脑上),例如:一些sshfs;然后,您就可以访问一些超级计算机文件/sshfilesystem/foo.bar)。它可能是最慢的解决方案,可能不是一个非常可靠的解决方案。我不是真的推荐它。

您可以请求使用NFS坐骑的权限。

使用某些HTTP / HTTPS客户端库(如HTTPS(或者反过来,某些HTTP / HTTPS服务器),也许您可​​能会考虑使用某些libcurl访问权限(如果远程计算机将其用于您的文件)库像libonion

你可能(但首先请求权限!)使用一些TLS连接(例如,手动启动远程超级计算机上的程序之类的服务器)或许通过OpenSSLlibgnutls

最后,您应该考虑安装(即礼貌地询问远程超级计算机上的安装)或使用某些database软件(例如PostgreSQLMariaDBRedis或远程计算机上的MongoDB服务器),使您的程序成为数据库客户端应用程序......

顺便说一下,如果您在随机访问中访问几十个TB级文件(每个内部读取几​​千字节)或一百万个文件,其中一个给定的运行只能访问十几个文件,情况可能会有所不同顺序读取,每个文件的大小合理(几兆字节)。换句话说,DNA数据,视频电影,HTML文档,源代码......都是不同的情况!

答案 1 :(得分:1)

好吧,你的问题的答案是 no ,正如已经多次说过的那样(除非你考虑自己实施 ssh ,这超出了理智范围)。 / p>

但是,当你还描述你的真正的问题时,它可能只是提出错误的问题,所以 - 寻找替代方案:

备选方案1

将要使用静态的库链接到二进制文件。假设您要静态链接 libfoo

  • 确保您的图书馆搜索路径中有libfoo.a(图书馆的对象存档)。通常,您的发行版提供的库的开发包已包含它,如果没有,请自行编译库以使用选项来启用静态库的创建

  • 假设使用GNU工具链,使用以下标志构建程序:-Wl,-Bstatic -lfoo -Wl,-Bdynamic(而不仅仅是-lfoo

备选方案2

像往常一样创建二进制文件(链接到动态库)并放置该库(libfoo.so),例如在服务器上的~/lib中。然后使用LD_LIBRARY_PATH=~/lib ./a.out运行您的二进制文件。

答案 2 :(得分:1)

您可以通过SSH连接将部分文件复制到您的计算机:

  • 使用dd命令将源文件的一部分复制到临时文件
  • 使用scprsync
  • 将临时文件复制到您的本地方框

如果需要多次执行此操作,可以创建一个shell脚本来自动执行此操作。

答案 3 :(得分:1)

而不是路径上的fopen,您可以在ssh命令上使用popen。 (不要忘记从FILE *获得的popen流已被pclose而不是fclose关闭。

您可以通过编写包裹popen的函数来简化界面。该函数只接受远程文件名,然后生成ssh命令以获取该文件,正确转义所有内容,如文件名中的空格,shell元字符等等。

FILE *stream = popen("ssh user@host cat /path/to/remote/file", "r");

if (stream != 0) {
   /* ... */
  pclose(stream);
}

popen有一些缺点,因为它处理shell命令。因为ssh的参数也是在远程端处理的shell命令,所以会引发双重转义问题:将命令作为shell命令传递。

要执行更强大的功能,您可以使用pipe创建管道,然后forkexec* ssh进程创建管道,安装管道的写入端作为其stdout,并使用fdopen在父进程中管道的读取端创建FILE *流。通过这种方式,可以准确控制传递给进程的参数:至少在本地,您没有运行shell命令。

答案 4 :(得分:0)

你不能直接(1)用fopen()或ifstream :: open在ssh上打开文件。但您可以利用现有的ssh二进制文件。只需从stdin读取程序,然后通过ssh将文件传递给它:

ssh that_server cat /path/to/largefile | ./yourprogram

(1)好吧,如果使用sshfs挂载远程系统,则可以通过ssh访问文件,就像它们是本地文件一样。