5

パスワードの入力を求められることなく、phpスクリプト内からrsyncを使用してローカルフォルダーとリモートフォルダーを同期するにはどうすればよいですか?

ユーザーのリモートサーバーへのログインを自動化するための公開鍵をすでに設定しています。

したがって、これはcliから問題なく実行されています。

rsync -r -a -v -e "ssh -l user" --delete ~/local/file 111.111.11.111:~/remote/;

しかし、PHPスクリプトから(ローカルサーバーのWebページで)同じものを実行しようとすると、次のようになります。

$c='rsync -r -a -v -e "ssh -l user" --delete ~/local/file 111.111.11.111:~/remote/';
//exec($c,$data);
passthru($c,$data);
print_r($data);

これは私が受け取るものです:

255

また、ローカルサーバーからリモートサーバーにファイルがアップロードされることはありません。

ネットで検索すると、この手がかりが見つかりました:

「ここではBAShとExpectシェルコードを組み合わせて使用​​できますが、ルートログインが自動化されるため、あまり安全ではありません。または(Apacheが実行されているユーザーに関係なく)のキーを生成しますnobodyapacheまたは、phpSuExecをインストールします。 、Suhosin、またはsuPHPを使用して、スクリプトが呼び出されたユーザーとして実行されるようにします。」

さて、「apache」として実行されているPHPの「ルートログインを自動化」する方法がわかりません。たぶん、実際のユーザーとしてスクリプトを実行する方が良い考えです、私にはわかりません...ありがとう!

更新:-これは正常に機能するため:

passthru('ssh user@111.111.11.111 | ls',$data);

ホーム飼料のリストを返すと、自動ログインに問題はないと確信しています。これは、PHPスクリプトから実行されているrsyncを使用したものである必要があります。

  • 念のため、ローカルフォルダとリモートフォルダにchmod-R0777もあります。しかし、私はまだそれを取得していません。

アップデート:

すべての問題は、「コマンドラインで実行する場合、sshは$ HOME / .ssh /のキーファイルを使用しますが、PHPではApacheのユーザーを使用して実行されるため、$HOMEがない可能性があります。 HOME / .ssh / id_dsa。したがって、使用するキーファイルを具体的に指定するか、そのディレクトリとその内容を手動で作成します。」

rsyncを取得することはできませんが、これがファイルをローカルからリモートに転送する方法です。

if($con=ssh2_connect('111.111.11.111',22)) echo 'ok!';
if(ssh2_auth_password($con,'apache','xxxxxx')) echo ' ok!';
if(ssh2_scp_send($con,'localfile','/remotefolder',0755)) echo ' ok!';

ローカルファイルのニーズ:0644リモートフォルダのニーズ:0775

解決策が同じユーザーbashでphpを実行することではないかと思います...

@Yzmir Ramirezは、次のように提案しました。「「apacheがアクセスできる場所にキーをコピーする」ことは、セキュリティ違反です。セキュリティで保護されたユーザーとして実行するようにスクリプトを変更してから、を設定することをお勧めします。サーバー間のパスワードなしのログイン用のsshキー。

これは私がもう少し時間を投資しなければならないものです。誰かがこれを行う方法を知っているなら、どうか、それは大きな助けになるでしょう。

4

3 に答える 3

5

私たちのアプリケーションでこれと同じことを設定したとき、私も255のエラーに遭遇し、それらがさまざまなことを意味する可能性があることを発見しました。これは特に役立つエラーコードではありません。実際、現在でも、ソリューションが1年以上スムーズに実行された後でも、ログに255が表示されることがあります。

また、いくつかの変数が関係しているため、それを機能させるのは少し面倒かもしれません。私が非常に役立つと思ったのは、変数にrsyncコマンドを作成し、それをログに記録することでした。このようにして、使用されている正確なrsyncコマンドを取得し、手動で実行してみることができます。apacheユーザーにsuして、スクリプトと同じディレクトリ(またはスクリプトがcwdとして設定しているもの)から実行することもできます。これにより、プログラムで実行した場合と同じように動作します。これにより、Webサーバーを扱う必要がなくなるため、rsyncコマンドのデバッグがはるかに簡単になります。また、手動で実行するときに、明示されていない理由で失敗した場合は、詳細フラグを追加してエラー出力を増やします。

以下は、セキュリティのために少し編集された、使用しているコードです。宛先はテストインストールを簡単に行えるように完全に構​​成可能であるため、コードは実際にはローカルサーバーとリモートサーバーの両方へのrsyncをサポートしていることに注意してください。

try {
    if ('' != $config['publishSsh']['to']['remote']):
    //we're syncing with a remote server
        $rsyncToRemote = escapeshellarg($config['publishSsh']['to']['remote']) . ':';
        $rsyncTo = $rsyncToRemote . escapeshellarg($config['publishThemes']['to']['path']);
        $keyFile = $config['publishSsh']['to']['keyfile'];
        $rsyncSshCommand = "-e \"ssh -o 'BatchMode yes' -o 'StrictHostKeyChecking no' -q -i '$keyFile' -c arcfour\"";
    else:
    //we're syncing with the local machine
        $rsyncTo = escapeshellarg($config['publishThemes']['to']['path']);
        $rsyncSshCommand = '';
    endif;

    $log->Message("Apache running as user: " . trim(`whoami`), GLCLogger::level_debug);
    $deployCommand = "
        cd /my/themes/folder/; \
        rsync \
        --verbose \
        --delete \
        --recursive \
        --exclude '.DS_Store' \
        --exclude '.svn/' \
        --log-format='Action: %o %n' \
        --stats \
        $rsyncSshCommand \
        ./ \
        $rsyncTo \
         2>&1
    "; //deployCommand
    $log->Message("Deploying with command: \n" . $deployCommand, GLCLogger::level_debug);
    exec($deployCommand, $rsyncOutputLines, $returnValue);
    $log->Message("rsync status code: $returnValue", GLCLogger::level_debug);
    $log->Message("rsync output: \n" . implode("\n", $rsyncOutputLines), GLCLogger::level_debug);
    if (0 != $returnValue):
        $log->Message("Encountered error while publishing themes: <<<$returnValue>>>");
        throw new Exception('rsync error');
    endif;

    /* ... process output ... */
} catch (Exception $e) {
    /* ... handle errors ... */
}

コードについて注意すべき点がいくつかあります。

  • exec()を使用して、出力を変数にキャプチャできるようにしています。次に、それを解析して、追加、変更、および削除されたファイルの数に関して結果をログに記録して報告できるようにします。

  • rsyncの標準出力と標準エラーストリームを組み合わせて、両方を返しています。また、戻り結果コードをキャプチャして確認しています。

  • Apacheが実行されているユーザー、rsyncコマンド自体、rsyncコマンドの出力など、デバッグモードのときにすべてをログに記録しています。このように、前述のように、コピーアンドペーストをすばやく行うだけで、同じユーザーと同じコマンドを簡単に実行できます。

  • rsyncコマンドで問題が発生した場合は、影響を与えることなく冗長性を調整し、ログの出力を確認できます。

私の場合、適切なキーファイルを指定するだけで、セキュリティについて過度に心配する必要はありませんでした。そうは言っても、これをどのように処理するかについてのいくつかの考え:

  • Apacheにファイルへのアクセスを許可することは、ファイルがWebディレクトリにある必要があることを意味するわけではありません。別のネットワークマシン上でも、Apacheユーザーがアクセスできる場所ならどこにでもファイルを置くことができます。他のセキュリティ層によっては、これが許容できる妥協案である場合とそうでない場合があります。

  • コピーするデータによっては、他のマシンのsshユーザーのアクセス許可を厳しく制限できる場合があります。そのため、悪意のあるユーザーがそこに侵入した場合、被害を与える能力は最小限に抑えられます。

  • suEXECを使用して、Apacheユーザー以外のユーザーとしてスクリプトを実行し、キーへのアクセスを他のユーザーにロックすることができます。したがって、Apacheユーザーを危険にさらす人は、単にキーにアクセスできません。

これがお役に立てば幸いです。

于 2011-01-26T17:04:15.547 に答える
0

この問題の単純ですが間接的な解決策はここにあり、私はこれを使用しています。

phpから直接rsyncを実行しないでください。問題があるだけでなく、セキュリティ上のリスクもあります。むしろ、2つのスクリプトを準備するだけです。phpスクリプトでは、ファイルシステム上の1つの変数の値を0から1に変更するだけです。

次に、反対側で、永久に実行され、次のロジックを持つrsyncスクリプトを作成します。""ファイルに0が含まれている場合は、rsyncを実行しないでください。1の場合は、rsyncを実行し、rsyncが正常に実行されたら、その値を0に戻します。""

私もやっています。

于 2012-04-08T12:21:22.217 に答える
0

Webサーバーにコマンドを実行させると、Webサーバーはそれを独自のユーザー(「nobody」または「apache」など)として実行し、そのユーザーのホームディレクトリ/.sshで秘密鍵を探します。自分のユーザーは「/home/you/.ssh/keyfile」にあるか、名前を付けています。

sshにその特定のキーを-iパラメータとともに使用させます。

ssh -i /home/you/.ssh/keyfile

そしてそれはうまくいくはずです

于 2011-01-23T17:58:51.943 に答える