简体   繁体   English

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

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

I have an access to some server where there is a lot of data. 我可以访问一些数据很多的服务器。 I can't copy the whole of data on my computer. 我无法在计算机上复制全部数据。

I can't compile on the server the program I want because the server doesn't have all libs I need. 我无法在服务器上编译我想要的程序,因为服务器没有我需要的所有库。

I don't think that the server admin would be very happy to see me coming and asking to him to install some libs just for me... 我不认为服务器管理员会很高兴看到我过来并要求他为我安装一些库...

So, I try to figure if there is a way to open a file like with, 因此,我尝试找出是否有一种方法可以像这样打开文件,

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

or 要么

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

but over a SSH connection. 但通过SSH连接。 Then reading the file like I do for usual program. 然后像读取普通程序一样读取文件。

both computer and server are running linux 计算机和服务器都在运行linux

I assume you are working on your Linux laptop and the remote machine is some supercomputer. 我假设您正在使用Linux笔记本电脑,并且远程计算机是一些超级计算机。

First non-technical advice: ask permission first to access the data remotely. 首要的非技术建议:首先征得许可,以远程访问数据。 In some workplaces you are not allowed to do that, even if it technically possible. 在某些工作场所,即使在技术上可行,您也不允许这样做。

You could sort-of use libssh for that purpose, but you'll need some coding and read its documentation. 您可以为此目的使用libssh ,但是您需要一些编码并阅读其文档。

You could consider using some FUSE file system (on your laptop), eg some sshfs ; 您可以考虑使用某些FUSE文件系统(在笔记本电脑上),例如某些sshfs you would then be able to access some supercomputer files as /sshfilesystem/foo.bar ). 这样您就可以访问一些超级计算机文件,例如/sshfilesystem/foo.bar )。 It is probably the slowest solution, and probably not a very reliable one. 这可能是最慢的解决方案,并且可能不是非常可靠的解决方案。 I don't really recommend it. 我真的不推荐它。

You could ask permission to use NFS mounts. 您可以要求使用NFS挂载的权限。

Maybe you might consider some HTTPS access (if the remote computer has it for your files) using some HTTP/HTTPS client library like libcurl (or the other way round, some HTTP/HTTPS server library like libonion ) 也许您可能会考虑使用某些HTTP / HTTPS客户端库(例如libcurl) (或者反过来使用某些HTTP / HTTPS服务器库(例如libonion ))来进行HTTPS访问(如果远程计算机上有您的文件)。

And you might (but ask permission first!) use some TLS connection (eg start manually a server like program on the remote supercomputer) perhaps thru OpenSSL or libgnutls 你可能(但请允许第一!)使用一些TLS连接(例如,手动启动像远程超级计算机程序的服务器)也许直通OpenSSL的libgnutls

At last, you should consider installing (ie asking politely the installation on the remote supercomputer) or using some database software (eg a PostgreSQL or MariaDB or Redis or MongoDB server) on the remote computer and make your program become a database client application ... 最后,您应该考虑在远程计算机上安装(即礼貌地要求在远程超级计算机上进行安装)或使用某些数据库软件(例如PostgreSQLMariaDBRedisMongoDB服务器),并使您的程序成为数据库客户端应用程序。 。

BTW, things might be different if you access a few dozen of terabyte sized files in a random access (each run reading a few kilobytes inside them), or a million files, of which a given run access only a dozen of them with sequential reads, each file of a reasonable size (a few megabytes). 顺便说一句,如果您以随机访问方式访问数十个TB级文件(每个运行时读取其中的几千字节),或者访问一百万个文件,则可能有所不同,其中给定运行时只能按顺序读取其中的十几个文件,每个文件大小合理(几兆字节)。 In other words, DNA data, video films, HTML documents, source code, ... are all different cases! 换句话说,DNA数据,视频电影,HTML文档,源代码……都是不同的情况!

Well, the answer to your question is no , as already stated several times (unless you think about implementing ssh yourself which is out of scope of sanity). 好吧,您的问题的答案是“ 否” ,正如已经多次说明的那样(除非您考虑自己实施ssh ,这超出了理智的范围)。

But as you also describe your real problem, it's probably just asking the wrong question, so -- looking for alternatives: 但是,正如您还描述您的实际问题时,可能只是问错了问题,所以-寻找替代方案:

Alternative 1 选择1

Link the library you want to use statically to your binary. 将要静态使用的库链接到二进制文件。 Say you want to link libfoo statically: 假设您要静态链接libfoo

  • Make sure you have libfoo.a (the object archive of your library) in your library search path. 确保在库搜索路径中有libfoo.a (库的对象档案库)。 Often, development packages for a library provided by your distribution already contain it, if not, compile the library yourself with options to enable the creation of the static library 通常,您的发行版提供的库的开发包中已经包含了该库,如果没有,请使用选项自行编译该库以启用静态库的创建

  • Assuming the GNU toolchain, build your program with the following flags: -Wl,-Bstatic -lfoo -Wl,-Bdynamic (instead of just -lfoo ) 假设使用GNU工具链,请使用以下标志构建程序: -Wl,-Bstatic -lfoo -Wl,-Bdynamic (而不是-lfoo

Alternative 2 选择2

Create your binary as usual (linked against the dynamic library) and put that library ( libfoo.so ) eg in ~/lib on the server. 照常创建二进制文件(与动态库链接),然后将该库( libfoo.so )放在服务器上的~/lib Then run your binary there with LD_LIBRARY_PATH=~/lib ./a.out . 然后使用LD_LIBRARY_PATH=~/lib ./a.out运行二进制文件。

You can copy parts of file to your computer over SSH connection: 您可以通过SSH连接将文件的一部分复制到计算机上:

  • copy part of source file using dd command to temporary file 使用dd命令将部分源文件复制到临时文件
  • copy temporary file to your local box using scp or rsync 使用scprsync将临时文件复制到本地盒中

You can create a shell script to automate this if you need to do that multiple times. 如果需要多次执行此操作,则可以创建一个Shell脚本来自动执行此操作。

Instead of fopen on a path, you can use popen on an ssh command. 可以在ssh命令上使用popen代替在路径上使用fopen (Don't forget that FILE * streams obtained from popen are closed with pclose and not fclose ). (不要忘记,从popen获得的FILE *流是用pclose而不是fclose关闭的)。

You can simplify the interface by writing a function which wraps popen . 您可以通过编写包装popen的函数来简化接口。 The function accepts just the remote file name, and then generates the ssh command to fetch that file, properly escaping everything, like spaces in the file name, shell meta-characters and whatnot. 该函数仅接受远程文件名,然后生成ssh命令以获取该文件,并正确转义所有内容,例如文件名中的空格,shell元字符和诸如此类。

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

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

popen has some drawbacks because it processes a shell command. popen有一些缺点,因为它处理shell命令。 Because the argument to ssh is also a shell command that is processed on the remote end, it raises issues of double escaping: passing a command through as a shell command. 由于ssh的参数也是在远程端处理的shell命令,因此会引起双重转义的问题:将命令作为shell命令传递。

To do something more robust, you can create a pipe using pipe , then fork and exec* the ssh process, installing the write end of the pipe as its stdout, and use fdopen to create a FILE * stream on the reading end of the pipe in the parent process. 为了做得更健壮,可以使用pipe创建一个管道,然后forkexec* ssh进程,将管道的写端安装为stdout,然后使用fdopen在管道的读取端创建FILE *流在父进程中。 This way, there is accurate control over the arguments which are handed to the process: at least locally, you're not running a shell command. 这样,可以精确控制传递给进程的参数:至少在本地,您没有运行shell命令。

You can't directly(1) open a file over ssh with fopen() or ifstream::open. 您不能直接(1)使用fopen()或ifstream :: open通过ssh打开文件。 But you can leverage the existing ssh binary. 但是您可以利用现有的ssh二进制文件。 Simply have your program read from stdin, and pipe the file to it via ssh: 只需让您的程序从stdin中读取,然后通过ssh将文件通过管道传递到它:

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

(1) Well, if you mount the remote system using sshfs you can access the files over ssh as if they were local. (1)好吧,如果使用sshfs挂载远程系统,则可以通过ssh访问文件,就好像它们是本地文件一样。

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

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