1

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

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

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

提前致谢 !

编辑:

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

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

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”模式。

4

3 回答 3

5

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

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

可以工作的最简单的事情似乎仍然是将档案发送到接收主机。在接收端,使用脚本过滤存档

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

所以你会这样做:

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焦油代替。添加选项以获得更多功能(-p例如保留权限)


要在单个逻辑连接上执行各种单独的步骤,您可以使用 ssh 主连接:

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

于 2011-12-01T12:15:03.640 回答
0

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

在libssh2/examples/sftp_append.c中有一个执行一个文件附加的示例,只需对您想要的多个文件重复它即可。

于 2011-12-01T23:20:31.323 回答
0

如果您从不同的战术角度看待问题,您可以从另一个主文件中收集所有文件。该主文件是一个 shell 脚本,其中包含嵌入文件内容的文档。然后在一个 ssh 会话中执行主 shell 脚本和 ls 文件。它既不漂亮也不优雅,但会成功。

于 2017-08-18T16:36:47.573 回答