通过一个ssh连接捕获多个文件并获取每个文件的返回值

时间:2011-12-01 12:12:31

标签: linux ssh cat

如标题中所述,我试图通过一个ssh连接捕获多个文件(内容需要附加到主机上的现有文件)并获取每个文件的返回值,即如果特定文件的cat成功或不。 到目前为止,我单独为每个文件执行此操作,只需对每个文件重复以下命令并检查返回值。

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

然后我只检查了每次传输的返回值(自动),从而可以确定每个文件的状态。我的问题是:是否可以通过一个单独的ssh连接,但是为每个文件获取一个返回值?

提前致谢!

编辑:

(b)正如您在下面所看到的,我为一个特定文件生成一个命令,然后检查返回代码。然后调用包含该部分程序的方法用于不同的类型o

如果文件已成功记录,则可以从客户端删除该文件,并且(仍)允许进一步记录到文件类型。如果文件超出其限制,则在程序的另一部分中取消设置该位。

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;
    }
}

第二次编辑:

我在路由器上运行此代码作为程序的一部分。请注意,我不允许向系统添加新库或非基本功能。此外,系统本身的ssh客户端不允许“-M”模式。

3 个答案:

答案 0 :(得分:5)

编辑以响应添加的信息(和代码):

代码:我强烈考虑在接收端编写脚本/程序,通过ssh 管道与发送过程进行通信。这样你就拥有了充分的灵活性。

最简单的方法仍然可能是将存档发送到接收主机。在接收端,filter the archive使用脚本

  • 将每个文件解压缩到临时位置
  • 尝试追加操作cat >> specific_file
  • 将“结果记录”打印到stdout,作为对发件人的反馈

所以你要这样做:

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

要处理C / C ++中的反馈,您需要查看popen,这样您就可以像在文件中一样阅读流式反馈,简单!

接收端上此类 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

真正的好处是,因为一切都处于流媒体模式,第一个文件的反馈可能会到达,而发送的tar是仍然将后来的文件发送到接收主机。 没有不必要的延迟!

我包含了一些理智的错误处理/清理,但我建议

  • 可能首先接收整个存档,然后遍历文件?
  • 以原子方式进行追加(即在副本上,如果整个追加操作成功,则将副本移动到;这可以防止部分追加的日志)

希望有所帮助!


旧答案:

<子> 你通常会采用狡猾的小技巧(),如:

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

添加详细标记以查看进度详情

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

如果需要,可以用cpio代替tar。添加选项以获得更多功能(-p用于保留权限,例如。)


要在单个逻辑连接上执行各种单独的步骤,您可以使用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

答案 1 :(得分:0)

如何构建libssh2而不是脚本ssh,并使用sftp子系统而不是在shell中构建自己的文件传输系统?

有一个例子是在libssh2/examples/sftp_append.c中执行一个附加文件,只需为你想要的多个文件重复它。

答案 2 :(得分:0)

如果从不同的战术视图中查看问题,可以将所有文件从另一个主文件中删除。该主文件是一个shell脚本,其中包含嵌入文件内容的文档。然后执行主shell脚本并使用文件 - 所有这些都在一个ssh会话中。它不漂亮或优雅但会成功。