5

JavaでJSchを介してSSH接続を確立していますが、この.shファイルを実行しようとするまで、すべてが正常に機能しているように見えました。シェルスクリプトの名前は次のとおりですrepoUpdate.sh。非常に単純です。

echo  ' ****Repository update****'
echo  ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'

svn update /home/cissys/repo/2.3.0

これは、コマンドの適切な応答とともにLinuxコンソールに直接表示される出力です。

[cissys@dsatelnx5 ~]$ repoUpdate.sh
 ****Repository update****
 Location: /home/cissys/repo/
 Command: svn update /home/cissys/repo/2.3.0

At revision 9432.

これが、この同じファイルを呼び出そうとするSSH接続を使用したメソッドのJavaコードです。

public void cmremove()
{
    try
    {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        UserInfo ui = new SUserInfo(pass, null);
        session.setUserInfo(ui);
        session.setPassword(pass);
        session.connect();
        
        ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
        
        InputStream in = channelExec.getInputStream();
        
        channelExec.setCommand("./repoUpdate.sh");
        channelExec.connect();
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        int index = 0;
        
        while ((line = reader.readLine()) != null)
        {
            System.out.println(++index + " : " + line);
        }
        
        channelExec.disconnect();
        session.disconnect();
        
        System.out.println("Done!");
    }
    catch(Exception e)
    {
        System.err.println("Error: " + e);
    }
}

そして、私が得る応答は次のとおりです。

run:
1 :  ****Repository update****
2 :  Location: /home/cissys/repo/
3 :  Command: svn update /home/cissys/repo/2.3.0
Done!
BUILD SUCCESSFUL (total time: 2 seconds)

svnコマンド( )の出力や実行の兆候はまったくありAt revision 9432ません。

コマンドを正しく実行させずに、ある時点でセッションを閉じている可能性があると思います。updateRepo.sh`` file would've had something like cp test.txt test_2.txt`であれば、問題なく実行できます。しかし、私はこれと他のいくつかの特定の.shファイルでのみこの問題を抱えています。

どんな助けでもいただければ幸いです。

4

2 に答える 2

6

あなたのシェルコマンドが何らかの理由svnでエラーになっているのではないかと思います-おそらくあなたの道にない、おそらく他の奇妙な環境への影響があります-しかしあなたはそれを探していないのでエラー出力を受け取っていません。通常、エラーは取得したストリームで送信されchannelExec.getErrStreamますが、コードではストリームからのみ読み取りgetOutputStreamます。

これを診断するには、これらのエラーメッセージを取得する必要があります。Javaプログラムが一度に2つのストリームからプルするよりも、Linuxで通常の出力メッセージとエラーメッセージの両方に1つのストリームを使用する方がおそらく簡単なので、この行を次の行の先頭に追加しますrepoUpdate.sh

exec 2>&1

これにより、スクリプトの残りの部分で、読み取っている1つのストリームが出力とエラーの両方として使用されるようになります。

また、を呼び出す直前chanelExec.disconnectに、Javaプログラムで終了ステータスを記録してから、「完了」を変更する必要があります。それが何であったかに基づくメッセージ:

    int exitStatus = channelExec.getExitStatus();
    channelExec.disconnect();
    session.disconnect();

    if (exitStatus < 0) {
        System.out.println("Done, but exit status not set!");
    } else if (exitStatus > 0) {
        System.out.println("Done, but with error!");
    } else {
        System.out.println("Done!");
    }

これを行うと、コマンドが期待どおりに機能しない理由を示すエラーメッセージが表示されます。

于 2012-07-18T10:35:23.153 に答える
5

これが私がしたことです。repoUpdate.shファイルの先頭に
を追加し、@ DanielMartinが提案したように、出力エラーを読み取るためのコードを追加しました。その結果、次のようになります。 exec 2>&1

public void cmremove()
{
    try
    {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        UserInfo ui = new SUserInfo(pass, null);
        session.setUserInfo(ui);
        session.setPassword(pass);
        session.connect();

        ChannelExec channelExec = (ChannelExec)session.openChannel("exec");

        InputStream in = channelExec.getInputStream();

        channelExec.setCommand("./repoUpdate.sh");
        channelExec.connect();

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        int index = 0;

        while ((line = reader.readLine()) != null)
        {
            System.out.println(++index + " : " + line);
        }

        int exitStatus = channelExec.getExitStatus();
        channelExec.disconnect();
        session.disconnect();
        if(exitStatus < 0){
            System.out.println("Done, but exit status not set!");
        }
        else if(exitStatus > 0){
            System.out.println("Done, but with error!");
        }
        else{
            System.out.println("Done!");
        }
    }
    catch(Exception e)
    {
        System.err.println("Error: " + e);
    }
}

だからそれは実際に大いに役立った。実際、思った通りにコマンドが正しく実行されていないことを確認しました。私はこれをJava出力で取得していました:

run:
1 :  ****Repository update****
2 :  Location: /home/cissys/repo/
3 :  Command: svn update /home/cissys/repo/2.3.0
4 : ./repoUpdate.sh[6]: svn: not found [No such file or directory]
Done!
BUILD SUCCESSFUL (total time: 2 seconds)

次に、repoUpdate.shファイルを変更して、svnコマンドの絶対パスを追加してみました(ありがとう、@ ymnk)

exec 2>&1
echo  ' ****Repository update****'
echo  ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'

/opt/subversion/bin/svn update /home/cissys/repo/2.3.0

私のJavaの場合、私は探していたものを手に入れました。

run:
1 :  ****Repository update****
2 :  Location: /home/cissys/repo/
3 :  Command: svn update /home/cissys/repo/2.3.0
4 : At revision 9443.
Done!
BUILD SUCCESSFUL (total time: 3 seconds)

私は$PATH、Javaを介してセッションから取得したものが、Linuxコンソールで直接取得したものと同じではないことを発見しました。したがって、svnパスを追加することで実際にうまくいきました。ご助力ありがとうございます!

于 2012-07-18T20:32:02.047 に答える