简体   繁体   English

通过一个ssh连接管理多个文件,并为每个文件获取返回值

[英]cat multiple files over one ssh connection and get return value for each

As said in the title, i'm trying to cat multiple files (content needs to be appended to existing files on host) over one ssh connection and get return value for each, ie if that cat for the particular file was successful or not. 如标题中所述,我正在尝试通过一个ssh连接管理多个文件(内容需要附加到主机上的现有文件),并为每个文件获取返回值,即,该猫是否适用于特定文件。 Up to now, i did this for each file individually, by just repeating the following command for each and checking the return value. 到目前为止,我仅对每个文件重复执行以下命令并检查返回值,从而分别对每个文件进行了此操作。

cat specific_file | ssh user@host -i /root/.ssh/id_rsa "cat >> result/specific_file"

I then just checked the return value for each transfer (automatically) and thereby could determine the status for each file. 然后,我只是自动检查了每次传输的返回值,从而可以确定每个文件的状态。 My question is: is it possible to to this over one single ssh connection, but to obtain a return value for every single file ? 我的问题是:是否可以通过单个ssh连接来实现此目的,但可以为每个文件获取返回值?

Thanks in advance ! 提前致谢 !

EDIT: 编辑:

(b) As you can see in the following, i generate a command for one specific file and then check the return code. (b)如下所示,我为一个特定文件生成了一条命令,然后检查了返回代码。 The method containing this part of the program is then called for the different types o 然后,针对不同类型的对象,调用包含程序这一部分的方法

If the file was successfully logged, it can be removed from the client, and that further logging to the type of file is (still) allowed. 如果文件已成功记录,则可以将其从客户端中删除,并且允许(仍然)进一步记录文件类型。 If the file is exceeding its limits, this bit is unset in another part of the program. 如果文件超出其限制,则该位在程序的另一部分中未设置。

sprintf(command,"/bin/cat /root/%s%s | /usr/bin/ssh log-bot@192.168.5.1 -i"
        " /root/.ssh/id_rsa \"/bin/cat >> result/%s%s\"", apmac,
        ending_str[source], apmac, ending_str[dest]);
rc = system(command);

if(rc != 0)
{
    sprintf(buffer, "[%i] - LOG ERROR from %s to %s CODE %i ", (int)time(0),
            ending_str[source], ending_str[dest], rc);
    sprintf(filename,"%s%s%s", LOCAL, apmac, ending_str[source]);
}
else
{
    sprintf(filename,"%s%s%s", LOCAL, apmac, ending_str[source]);
    remove(filename);
    sprintf(buffer, "[%i] - LOG process from %s to %s ok", (int)time(0),
            ending_str[source], ending_str[dest]);

    switch(source)
    {
    case PROBE_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_PROB);
        break;
    case LIST_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_LIST);
        break;
    case SCAN_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_SCAN);
        break;
    default:
        /* Other cases not YET considered */
        break;
    }
}

SECOND EDIT: 第二编辑:

I'm running this code on a router as a part of a program. 我正在路由器上将此代码作为程序的一部分运行。 Please note that i'm not allowed to add new libraries or non basic functions to the system. 请注意,我不允许向系统添加新库或非基本功能。 In addition, the ssh client on the system itself doesn't allow "-M" mode. 另外,系统本身的ssh客户端不允许使用“ -M”模式。

Edit in response to the added info (and code): 编辑响应添加信息(和代码):

To the code: I'd strongly consider writing a script/program on the receiving end to talk to the sending process over the ssh pipe . 对于代码:我强烈考虑在接收端编写一个脚本/程序,以通过ssh pipe与发送过程进行对话。 That way you have full flexibility. 这样,您就具有了充分的灵活性。

The simplest thing that could work, would still appear to be sending an archive over to the receiving host. 可能起作用的最简单的方法似乎仍然是将存档发送到接收主机。 On the receiving end, filter the archive with a script that 在接收端,使用以下脚本过滤归档文件

  • untars each file into a temporary location 将每个文件解压缩到一个临时位置
  • tries the appending operation cat >> specific_file 尝试追加操作cat >> specific_file
  • prints a 'result record' to stdout as feedback to the sender 将“结果记录”打印到标准输出,作为对发件人的反馈

So you'd do: 所以你会做:

tar c file1 file2 file3 |
   ssh log-bot@remote /home/log-bot/handle_logappends.sh |
   while read resultcode filename
   do
       echo "$filename" resulted in code "resultcode"
   done

To handle the feedback in C/C++ you'd look at popen , that will allow you to read the streaming feedback as if from a file, simple! 要处理C / C ++中的反馈,您可以查看popen ,它使您可以像读取文件一样读取流式反馈,非常简单!

An example of such a handle_logappends.sh script on the receiving end: 接收端的handle_logappends.sh脚本示例:

#!/bin/bash
set -e # bail on error

TEMPDIR="/tmp/.receiving_$RANDOM"
mkdir "$TEMPDIR"

trap "rm -rf '$TEMPDIR/'" INT ERR EXIT

tar x -v -C "$TEMPDIR/" | while read filename
do
    echo "unpacked file $filename" > /dev/stderr

    ## implement your file append logic here :)
    ## e.g. (?):
    cat "$TEMPDIR/$filename" >> "result/$filename"

    ## HERE COMES THE FEEDBACK PART: '<code> <filename>'
    echo "$?" "$filename"
done

The really neat part of this is, that since everything is in streaming mode , the feedback for the first file(s) may be arriving while the sending tar is still sending the later files to the receiving host. 真正整洁的部分是, 由于所有内容都处于流模式 ,因此在发送tar仍将后面的文件发送到接收主机的同时 ,可能会到达第一个文件的反馈。 No unnecessary delays! 没有不必要的延迟!

I included a tiny bit of sane error handling/cleanup but I would suggest 我包含了一些理智的错误处理/清理功能,但我建议

  • perhaps receiving the whole archive first, then iterating through the files? 也许先接收整个档案,然后遍历文件?
  • doing the appends in atomic fashion (ie on a copy, then move the copy into place only if the whole append operation succeeded; this prevents partially appended logs) 以原子方式进行追加(即在副本上,然后在整个追加操作成功后才将副本移到适当位置;这可防止部分追加日志)

Hope that helps! 希望有帮助!


Older answer: 较旧的答案:

You'd usually employ devious little tricks ( not ) like: 通常,您会使用一些狡猾的小技巧( 而非 ),例如:

tar c file1 file2 file3 | ssh user@host -i /root/.ssh/id_rsa "tar x -C result/ -"

Add a verbose flag to see progress details 添加详细标志以查看进度详细信息

tar c file1 file2 file3 | ssh user@host -i /root/.ssh/id_rsa "tar xvC result/ -"

If you want, you can substitute cpio for tar. 如果需要,可以用cpio代替tar。 Add options to get more functionality ( -p for preserve permissions, eg) 添加选项以获得更多功能(例如-p用于保留权限)


To do various separate steps over a single logical connection, you can use a ssh Master connection: 要在单个逻辑连接上执行各种单独的步骤,可以使用ssh Master连接:

ssh user@host -i /root/.ssh/id_rsa  -MNf  # login, master, background without a command

for specific_file in file1 file2 file3
do
     cat "$specific_file" |
         ssh user@host -Mi /root/.ssh/id_rsa "cat >> 'result/$specific_file'"
     # check/use error code
done

if you look at the problem from a different tactical view, you could cat all the files over from another master file. 如果您从不同的战术角度看问题,则可以从另一个主文件中查找所有文件。 That master file is a shell script that has here documents embedded with the files' contents. 该主文件是一个shell脚本,在此脚本中嵌入了文件内容。 Then exec the master shell script and ls the files - all in one ssh session. 然后执行主Shell脚本并执行ls文件-全部在一个ssh会话中进行。 It's not pretty or elegant but will be successful. 它不是漂亮或优雅,但会成功。

How about building on libssh2 instead of scripting ssh, and using the sftp subsystem instead of building your own file-transfer system in shell? 如何在libssh2构建而不是对ssh脚本编写脚本,以及如何使用sftp子系统而不是在shell中构建自己的文件传输系统呢?

There's an example of performing one file append in libssh2/examples/sftp_append.c , just repeat it for the multiple files you want. libssh2 / examples / sftp_append.c中有一个执行一个文件追加的示例 ,只需对所需的多个文件重复该操作即可。

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

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