繁体   English   中英

有什么方法可以通过SSH连接打开和读取文件?

[英]there is any way to open and read a file over a SSH connection?

我可以访问一些数据很多的服务器。 我无法在计算机上复制全部数据。

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

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

因此,我尝试找出是否有一种方法可以像这样打开文件,

FILE *fopen(const char *filename, const char *mode);

要么

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

但通过SSH连接。 然后像读取普通程序一样读取文件。

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

我假设您正在使用Linux笔记本电脑,并且远程计算机是一些超级计算机。

首要的非技术建议:首先征得许可,以远程访问数据。 在某些工作场所,即使在技术上可行,您也不允许这样做。

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

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

您可以要求使用NFS挂载的权限。

也许您可能会考虑使用某些HTTP / HTTPS客户端库(例如libcurl) (或者反过来使用某些HTTP / HTTPS服务器库(例如libonion ))来进行HTTPS访问(如果远程计算机上有您的文件)。

你可能(但请允许第一!)使用一些TLS连接(例如,手动启动像远程超级计算机程序的服务器)也许直通OpenSSL的libgnutls

最后,您应该考虑在远程计算机上安装(即礼貌地要求在远程超级计算机上进行安装)或使用某些数据库软件(例如PostgreSQLMariaDBRedisMongoDB服务器),并使您的程序成为数据库客户端应用程序。 。

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

好吧,您的问题的答案是“ 否” ,正如已经多次说明的那样(除非您考虑自己实施ssh ,这超出了理智的范围)。

但是,正如您还描述您的实际问题时,可能只是问错了问题,所以-寻找替代方案:

选择1

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

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

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

选择2

照常创建二进制文件(与动态库链接),然后将该库( libfoo.so )放在服务器上的~/lib 然后使用LD_LIBRARY_PATH=~/lib ./a.out运行二进制文件。

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

  • 使用dd命令将部分源文件复制到临时文件
  • 使用scprsync将临时文件复制到本地盒中

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

可以在ssh命令上使用popen代替在路径上使用fopen (不要忘记,从popen获得的FILE *流是用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命令。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM