2016-05-26 169 views
0

我有一個使用net.schmizz.sshj SFTP庫的夜間工作。timeout at net.schmizz.sshj.transport.KeyExchanger.waitForDone(KeyExchanger.java:160)

我懷疑我們SFTP進入的服務器有變化。但是,我無法確定確切的變化是什麼。我也不能在生產服務器之外重現它。所以我要尋找一個根本原因的見解或如何重現以下錯誤

net.schmizz.sshj.transport.TransportException: Timeout expired at net.schmizz.sshj.transport.TransportException$1.chain(TransportException.java:33) at net.schmizz.sshj.transport.TransportException$1.chain(TransportException.java:27) at net.schmizz.concurrent.Promise.retrieve(Promise.java:139) at net.schmizz.concurrent.Event.await(Event.java:103) at net.schmizz.sshj.transport.KeyExchanger.waitForDone(KeyExchanger.java:160) at net.schmizz.sshj.transport.KeyExchanger.startKex(KeyExchanger.java:155) at net.schmizz.sshj.transport.TransportImpl.doKex(TransportImpl.java:247) at net.schmizz.sshj.SSHClient.doKex(SSHClient.java:735) at net.schmizz.sshj.SSHClient.onConnect(SSHClient.java:723) at net.schmizz.sshj.SocketClient.connect(SocketClient.java:54) at net.schmizz.sshj.SocketClient.connect(SocketClient.java:80)

從我可以告訴,我們通過連接java.net.Socket確定,然後超時等待交換密鑰完成此代碼

package net.schmizz.sshj.transport; 

/** Algorithm negotiation and key exchange. */ 
final class KeyExchanger 
     implements SSHPacketHandler, ErrorNotifiable { 

    /** 
    * Starts key exchange by sending a {@code SSH_MSG_KEXINIT} packet. Key exchange needs to be done once mandatorily 
    * after initializing the {@link Transport} for it to be usable and may be initiated at any later point e.g. if 
    * {@link Transport#getConfig() algorithms} have changed and should be renegotiated. 
    * 
    * @param waitForDone whether should block till key exchange completed 
    * 
    * @throws TransportException if there is an error during key exchange 
    * @see {@link Transport#setTimeoutMs} for setting timeout for kex 
    */ 
    void startKex(boolean waitForDone) 
      throws TransportException { 
     if (!kexOngoing.getAndSet(true)) { 
      done.clear(); 
      sendKexInit(); 
     } 
     if (waitForDone) 
      waitForDone(); 
    } 

    /** 
    * Sends SSH_MSG_KEXINIT and sets the {@link #kexInitSent} event. 
    * 
    * @throws TransportException 
    */ 
    private void sendKexInit() 
      throws TransportException { 
     log.debug("Sending SSH_MSG_KEXINIT"); 
     clientProposal = new Proposal(transport.getConfig()); 
     transport.write(clientProposal.getPacket()); 
     kexInitSent.set(); 
    } 

void waitForDone() 
     throws TransportException { 
    done.await(transport.getTimeoutMs(), TimeUnit.MILLISECONDS); 
} 

回答

1

許多調試後張貼這個問題,我想通了,問題是,我們並沒有在爲我在本地測試沒有生產環境中運行相同的加密庫後。我通過構建最小jar來確定這一點,同時仍然保留生產中使用的所有SSHJ作品以及我們自己的所有相關代碼,然後在命令外殼程序中使用DEBUG級別日誌記錄運行它,我可以看到所有輸出。然後,我看到下面,我意識到,在我們的生產服務器日誌的超時例外是第二例外發生後和屏蔽哪些沒有被記錄在生產的根本原因:一NoClassDefFoundError

Exception in thread "reader" java.lang.NoClassDefFoundError: org/bouncycastle/crypto/ec/CustomNamedCurves 
    at net.schmizz.sshj.transport.kex.Curve25519DH.getCurve25519Params(Curve25519DH.java:51) 
    at net.schmizz.sshj.transport.kex.Curve25519SHA256.initDH(Curve25519SHA256.java:36) 
    at net.schmizz.sshj.transport.kex.AbstractDHG.init(AbstractDHG.java:55) 
    at net.schmizz.sshj.transport.KeyExchanger.gotKexInit(KeyExchanger.java:239) 
    at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:359) 
    at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:493) 
    at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:107) 
    at net.schmizz.sshj.transport.Decoder.received(Decoder.java:175) 
    at net.schmizz.sshj.transport.Reader.run(Reader.java:60) 
Caused by: java.lang.ClassNotFoundException: org.bouncycastle.crypto.ec.CustomNamedCurves 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    ... 9 more 

net.schmizz.sshj.transport.TransportException: Timeout expired 
    at net.schmizz.sshj.transport.TransportException$1.chain(TransportException.java:33) 
    at net.schmizz.sshj.transport.TransportException$1.chain(TransportException.java:27) 
    at net.schmizz.concurrent.Promise.retrieve(Promise.java:139) 
    at net.schmizz.concurrent.Event.await(Event.java:103) 
    at net.schmizz.sshj.transport.KeyExchanger.waitForDone(KeyExchanger.java:160) 
    at net.schmizz.sshj.transport.KeyExchanger.startKex(KeyExchanger.java:155) 
    at net.schmizz.sshj.transport.TransportImpl.doKex(TransportImpl.java:247) 
    at net.schmizz.sshj.SSHClient.doKex(SSHClient.java:735) 
    at net.schmizz.sshj.SSHClient.onConnect(SSHClient.java:723) 
    at net.schmizz.sshj.SocketClient.connect(SocketClient.java:54) 
    at net.schmizz.sshj.SocketClient.connect(SocketClient.java:80) 
    at kirby.App.connect(App.java:101) 
    at kirby.App.execute(App.java:45) 
    at kirby.App.main(App.java:31) 
Caused by: java.util.concurrent.TimeoutException: Timeout expired 
    ... 12 more 

的差異歸結爲類路徑。 在生產中,我們有

bcpg-jdk15on-150.jar:bcpkix-jdk15on-150.jar:bcprov-jdk15on-150.jar

但需要

bcpkix-jdk15on/1.51/bcpkix-jdk15on-1.51.jar:ecc-25519-java-1.0.1.jar:bcprov-jdk15on/1.51/bcprov-jdk15on-1.51.jar