1

タイトルで述べたように、1 つの ssh 接続で複数のファイル (ホスト上の既存のファイルにコンテンツを追加する必要があります) を cat して、それぞれの戻り値を取得しようとしています。つまり、特定のファイルの cat が成功したかどうか。これまでは、ファイルごとに次のコマンドを繰り返して戻り値を確認するだけで、ファイルごとに個別にこれを行っていました。

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

次に、各転送の戻り値を(自動的に)チェックしただけで、各ファイルのステータスを判断できました。私の質問は次のとおりです。単一の ssh 接続を介してこれを行うことは可能ですが、単一のファイルごとに戻り値を取得することはできますか?

前もって感謝します !

編集:

(b)以下に示すように、特定の 1 つのファイルに対してコマンドを生成し、リターン コードを確認します。次に、プログラムのこの部分を含むメソッドが、さまざまな型に対して呼び出されます。

ファイルが正常にログに記録された場合は、クライアントから削除でき、そのファイル タイプへのさらなるログ記録は (引き続き) 許可されます。ファイルが制限を超えている場合、このビットはプログラムの別の部分で設定解除されます。

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

2番目の編集:

プログラムの一部としてルーターでこのコードを実行しています。システムに新しいライブラリや非基本機能を追加することは許可されていないことに注意してください。さらに、システム自体の ssh クライアントは「-M」モードを許可しません。

4

3 に答える 3

5

追加された情報(およびコード)に応じて編集します。

コードに対して:sshパイプを介して送信プロセスと通信するために、受信側でスクリプト/プログラムを作成することを強く検討します。そうすれば、完全な柔軟性が得られます。

動作する可能性のある最も単純なことは、アーカイブを受信ホストに送信することであるように見えます。受信側で、次のようなスクリプトを使用してアーカイブをフィルタリングします

  • 各ファイルを一時的な場所に解凍します
  • 追加操作を試みます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必要に応じて、タールの代わりに使用できます。より多くの機能を取得するためのオプションを追加します(-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

ssh をスクリプト化する代わりにlibssh2で構築し、シェルで独自のファイル転送システムを構築する代わりに sftp サブシステムを使用するのはどうですか?

libssh2/examples/sftp_append.cに1 つのファイルの追加を実行する例があります。必要な複数のファイルに対して繰り返すだけです。

于 2011-12-01T23:20:31.323 に答える
0

別の戦術的な観点から問題を見ると、別のマスター ファイルからすべてのファイルを cat することができます。そのマスター ファイルは、ファイルの内容が埋め込まれたドキュメントを含むシェル スクリプトです。次に、マスター シェル スクリプトを実行し、ファイルを ls します。すべて 1 つの ssh セッションで行います。きれいでもエレガントでもありませんが、成功するでしょう。

于 2017-08-18T16:36:47.573 に答える