2012-07-20 136 views
5

我有一個非常小的Java程序,能夠使用apache-commons-net庫在SSL(不是SFTP)或FTPS上執行FTP。我編寫這個程序的原因是客戶端機器是AIX 5.3,它不支持通過SSL的FTP(OOTB),並且FTP主機只運行啓用FTP的SSL運行FileZilla服務器。該程序運行良好沒有任何問題,但它產生的日誌量是巨大的。我的問題是 - 有沒有辦法控制日誌記錄的數量Apache-commons-net lib的受控日誌記錄(Java)

注同樣 - 該程序爲我的極簡要求工作絕對沒問題)

下面是我的代碼片段

import java.io.*; 
import java.text.MessageFormat; 
import java.util.logging.Logger; 
import org.apache.commons. 
..... 
.... 
.... 
try { 
      int reply; 
      logger.info("# Invoking Trust Manager"); 
      client.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); 
      //client.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager()); 
      logger.info("# Connect Call"); 
      client.connect(server, port); 
      client.login(username, password); 
      logger.info("# Login Success"); 

      client.setFileType(FTP.ASCII_FILE_TYPE); 
      client.execPBSZ(0); // Set protection buffer size 
      client.execPROT("P"); // Set data channel protection to private 
      client.enterLocalPassiveMode(); 

      logger.info(MessageFormat.format("Connected to {0} .", server)); 
      reply = client.getReplyCode(); 
      if (!FTPReply.isPositiveCompletion(reply)) { 
       client.disconnect(); 
       logger.severe("FTP server refused connection."); 
       System.exit(1); 
      } 

      if (flag.equals("-d")) { //Dir mode 
       if (args.length == 7){ 
        renameFile = args[6]; //copy rename token 
       } 
       //We will get the file listing and stream the output to create files 
       logger.info("# Invoked Directory mode"); 
       client.changeWorkingDirectory(remoteFile); 
       FTPFile[] ftpFiles; 
       ftpFiles = client.listFiles(remoteFile); 
       if (ftpFiles != null && ftpFiles.length > 0) {      
        for (FTPFile file : ftpFiles) { 
         if (!file.isFile()) { 
          continue; 
         }       
         InputStream fin = client.retrieveFileStream(remoteFile + "/" + file.getName()); 
         if (fin == null) { 
          logger.severe(MessageFormat.format("could not retrieve file: {0}", file.getName())); 
          continue; 
         } 
         // write the inputStream to a FileOutputStream 
         OutputStream out = new FileOutputStream(new File(localFile + "/"+ renameFile + file.getName())); 
         int read = 0; 
         byte[] bytes = new byte[1024]; 

         while ((read = fin.read(bytes)) != -1) { 
          out.write(bytes, 0, read); 
         } 
         fin.close(); 
         out.flush(); 
         out.close(); 
         fin = null; 
         client.completePendingCommand(); 
        } 
       } 
      } 

      if (flag.equals("-f")) { //File mode 
       //Transfer a single file 
       logger.info("# Invoked File mode"); 
       client.listFiles(); 
       boolean retrieved = client.retrieveFile(remoteFile, new FileOutputStream(localFile)); 

       if (retrieved) { 
        logger.info("# File copied."); 
       } 
      } 
     } catch (Exception e) { 
      if (client.isConnected()) { 
       try { 
        client.disconnect(); 
       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
      logger.severe("!! Could not connect to server.!! Please retry!"); 
      e.printStackTrace();    
     } finally { 
      client.disconnect();    
      logger.info("# FTP Client disconnected"); 
      System.exit(0); 
     } 

它產生傳輸一個文件就像如下─日誌

Jul 20, 2012 5:00:08 AM com.mff.ftps.FTPSSLTool main 
INFO: Connecting to IP: 216.153.173.246 on Port: 00890 
Jul 20, 2012 5:00:09 AM com.mff.ftps.FTPSSLTool main 
INFO: # Initiating SSL connection 
Jul 20, 2012 5:00:09 AM com.mff.ftps.FTPSSLTool main 
INFO: # Invoking Trust Manager 
Jul 20, 2012 5:00:09 AM com.mff.ftps.FTPSSLTool main 
INFO: # Connect Call 
IBMJSSEProvider2 Build-Level: -20110513 
keyStore is: /usr/java6_64/jre/lib/security/cacerts 
keyStore type is: jks 
keyStore provider is: 
init keystore 
SSLContextImpl: Using X509ExtendedKeyManager com.ibm.jsse2.xc 
SSLContextImpl: Using X509TrustManager org.apache.commons.net.util.TrustManagerUtils$TrustManager 
Installed Providers = 
    IBMJSSE2 
    IBMJCE 
    IBMJGSSProvider 
    IBMCertPath 
    IBMSASL 
    IBMXMLCRYPTO 
    IBMXMLEnc 
    Policy 
    IBMSPNEGO 
JsseJCE: Using SecureRandom from provider IBMJCE version 1.2 
trigger seeding of SecureRandom 
done seeding SecureRandom 
IBMJSSE2 to send SCSV Cipher Suite on initial ClientHello 
JsseJCE: Using cipher AES/CBC/NoPadding from provider TBD via init 
IBMJSSE2 will allow RFC 5746 renegotiation per com.ibm.jsse2.renegotiate set to none or default 
IBMJSSE2 will not require renegotiation indicator during initial handshake per com.ibm.jsse2.renegotiation.indicator set to OPTIONAL or default taken 
IBMJSSE2 will not perform identity checking against the peer cert check during renegotiation per com.ibm.jsse2.renegotiation.peer.cert.check set to OFF or default 
JsseJCE: Using MessageDigest MD5 from provider IBMJCE version 1.2 
JsseJCE: Using MessageDigest SHA from provider IBMJCE version 1.2 
JsseJCE: Using MessageDigest MD5 from provider IBMJCE version 1.2 
JsseJCE: Using MessageDigest SHA from provider IBMJCE version 1.2 
%% No cached client session 
*** ClientHello, SSLv3 
RandomCookie: GMT: 1342778411 bytes = { 246, 135, 47, 123, 204, 170, 94, 224, 76, 244, 28, 242, 63, 243, 124, 13, 93, 156, 170, 88, 91, 79, 89, 55, 157, 135, 214, 250 } 
Session ID: {} 
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_AES_128_CBC_SHA, SSL_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_RC4_128_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_RENEGO_PROTECTION_REQUEST] 
Compression Methods: { 0 } 
*** 
main, WRITE: SSLv3 Handshake, length = 81 
main, READ: SSLv3 Handshake, length = 74 
*** ServerHello, SSLv3 
RandomCookie: GMT: 1342778410 bytes = { 142, 39, 57, 18, 38, 123, 184, 245, 24, 29, 238, 158, 68, 17, 226, 210, 53, 31, 36, 225, 52, 166, 78, 116, 251, 98, 122, 4 } 
Session ID: {143, 221, 201, 170, 184, 190, 241, 94, 223, 253, 199, 199, 50, 161, 233, 224, 88, 78, 82, 162, 13, 222, 236, 56, 215, 253, 101, 12, 39, 45, 126, 203} 
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5 
Compression Method: 0 
*** 
Server did not supply RI Extension - com.ibm.jsse2.extended.renegotiation.indicator=optional or default - processing will continue 
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5] 
** SSL_RSA_WITH_RC4_128_MD5 
main, READ: SSLv3 Handshake, length = 1361 
*** Certificate chain 
chain [0] = [ 
[ 
    Version: V3 
    Subject: CN=ftps.thillsecure.com, OU=Terms of use at www.verisign.com/rpa (c)05, OU=Thill Logistics, O=TCFC LLC, L=Neenah, ST=Wisconsin, C=US 
    Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 

    Key: IBMJCE RSA Public Key: 
modulus:134055911103149706293270567805752446004906288958857850 
public exponent: 
65537 

    Validity: [From: Sun Dec 04 18:00:00 CST 2011, 
       To: Wed Dec 12 17:59:59 CST 2012] 
    Issuer: CN=VeriSign Class 3 Secure Server CA - G3, OU=Terms of use at https://www.verisign.com/rpa (c)10, OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US 
    SerialNumber: [168622087069244624687861365106323602194] 
.... 
.... 
.... 
Hundreds and hundreds of more lines 

我使用java.utils.logging.Logger我自己記錄的目的,但原木線getti ng由apache-commons-net庫方法本身生成的多行日誌模糊處理。

所以再次 - 問題是 - 「有沒有一種方法來控制apache-commons-net庫本身的日誌行爲?我可以使用任何方法或需要設置的任何標誌?」

UPDATE:

我終於得到了控制記錄(特別感謝Flavio)。我所要做的只是在我的代碼中包含System.setProperty("javax.net.debug", "false");。我最初設置爲System.setProperty("javax.net.debug", "ssl");,它啓用了調試級別日誌記錄。現在日誌更加簡短。同樣明顯的是,日誌不是來自commons-net library,而是來自javax.net。日誌是短得多,看起來像如下─

Jul 30, 2012 9:03:16 AM com.mff.ftps.FTPSSLTool main 
INFO: Connecting to IP: xxx.xxx.xxx.xxx on Port: 890 
Jul 30, 2012 9:03:16 AM com.mff.ftps.FTPSSLTool main 
INFO: # Initiating SSL connection 
Jul 30, 2012 9:03:16 AM com.mff.ftps.FTPSSLTool main 
INFO: # Invoking Trust Manager 
Jul 30, 2012 9:03:16 AM com.mff.ftps.FTPSSLTool main 
INFO: # Connect Call 
220 GlobalSCAPE Secure FTP Server 
USER XXXXXXX 
331 Password required for XXXXXXX. 
PASS XXXXXXXXX 
230 Login OK. Proceed. 
Jul 30, 2012 9:03:22 AM com.mff.ftps.FTPSSLTool main 
INFO: # Login Success 
TYPE A 
200 Type set to A. 
PBSZ 0 
200 PBSZ Command OK. Protection buffer size set to 0. 
PROT P 
200 PROT Command OK. Using Private data connection 
Jul 30, 2012 9:03:24 AM com.mff.ftps.FTPSSLTool main 
INFO: Connected to xxx.xxx.xxx.xxx . 
CWD /Data/Inv 
Jul 30, 2012 9:03:24 AM com.mff.ftps.FTPSSLTool main 
INFO: # Invoked Directory mode 
250 Folder changed to "/Data/Inv". 
SYST 
215 UNIX Type: L8 
PASV 
227 Entering Passive Mode (216,153,173,246,109,220). 
LIST /Data/Inv 
150 Opening ASCII mode data connection for file list. 
226 Transfer complete. 1430 bytes transferred. 1278 Bps. 
Jul 30, 2012 9:03:30 AM com.mff.ftps.FTPSSLTool main 
INFO: # FTP Client disconnected 

回答

4

我認爲你正在尋找錯誤的地方;這些消息不是來自apache commons網絡庫。

我認爲他們來自IBMJSSEProvider2你看到在第一行中提到。根據這一link,你應該能夠通過禁用它們設置的系統屬性javax.net.debug,或與os400.stdoutos400.stderr特性對它們進行重定向。

+0

太棒了!那正是我所期待的。我在我的代碼System.setProperty(「javax.net.debug」,「ssl」)中有這樣的東西,並且我將它修改爲System.setProperty(「javax.net.debug」,「false」) ;'。這大大減少了伐木,謝謝一噸。 – Annjawn 2012-07-30 14:04:52

0

您可以設置使用setLevel()應用程序的日誌級別。類Level用於定義應在日誌中寫入哪些消息。您可以設置以下日誌級別之一:

  • Level.SEVERE(最高級別)
  • Level.WARNING
  • Level.INFO
  • Level.CONFIG
  • Level.FINE
  • Level.FINER
  • Level.FINEST

如果使用LOGGER.setLevel(Level.INFO),每一個日誌級別高於或等於INFO將在日誌中寫,SEVERE, WARNING and INFO。另外,您可以使用Level.OFFLevel.ALL級別關閉註銷或記錄所有內容。

向您的應用程序添加更高的日誌級別,例如logger.setLevel(Level.SEVERE)

public void writeLog() { 
    // Set the LogLevel to Severe, only severe Messages will be written 
    LOGGER.setLevel(Level.SEVERE); 
    LOGGER.severe("Severe Log"); 
    LOGGER.warning("Warning Log"); 
    LOGGER.info("Info Log"); 
    LOGGER.finest("Really not important"); 

    // Set the LogLevel to Info, severe, warning and info will be written 
    // Finest is still not written 
    LOGGER.setLevel(Level.INFO); 
    LOGGER.severe("Severe Log"); 
    LOGGER.warning("Warning Log"); 
    LOGGER.info("Info Log"); 
    LOGGER.finest("Really not important"); 
} 

的更多信息:http://www.vogella.com/articles/Logging/article.html

P.S.請注意您的logging.properties文件,該文件設置您的global log level

+0

感謝您的迴應。但是這會控制'apache-commons-net'日誌嗎?在我上面的原始問題中看到的大多數日誌行來自'apache-commons-net'庫,而不是來自我的類​​文件。正如你可以看到它從Keystore到cokkies到證書鏈的每一步打印。此時我想控制庫的日誌本身(不是我的程序級日誌記錄),因爲我不想看到太多細節,這些細節在調試/開發期間通常很有用。 – Annjawn 2012-07-21 02:50:51

+0

基於此[問題](http://stackoverflow.com/questions/5009658/adjust-logging-level-for-apache-commons-logging?answertab=active#tab-top),我認爲它不會工作。嘗試按照這個'logging.properties' [文件示例](http://www.java-tips.org/java-se-tips/java.util.logging/how-以進行配置,一個記錄器默認值上帶有一個-properties.html)。它將覆蓋全局屬性。 – Yamaneko 2012-07-21 04:10:01

0

那麼,我已經有了與Spring,Quartz,Hibernate等相同的問題API和框架創建巨大的日誌巨石。

我在每個包的基礎上爲每個API設置自定義級別。

  • logger.org.spring = WARN
  • logger.org.hibernate = DEBUG
  • logger.org.quartz = INFO
  • logger.com.myApp = DEBUG

中當然,這不是完整的財產集,但你明白了。 您可以使用軟件包名稱 - org.apache.commons併爲該軟件包分配一個日誌級別。 請注意:來自該包級別下的任何級別的任何和每個日誌都將被配置爲與此級別相同。

我在log4j上使用了slf4j(http://www.slf4j.org/),而不是util logger。但我相信在你的情況下,修復可能會有點扭曲。 如果我可能有點大膽,我建議使用SLF4J。 HTH。

0

預計apache-commons-net日誌記錄可以使用commons-loggingSLF4J - 在沒有任何其他控制因素的情況下,這些日誌應該將日誌記錄路由到java.util.logging

這裏的最終答案是,如果你看到混合在輸出文件(不是控制檯)中的日誌,那麼它們很可能是通過普通的記錄器進行路由。並且java.lang.logging在這裏工作,所以讓我們嘗試配置。

配置java.util.logging

創建日誌記錄屬性文件,說myLog.properties,並自定義級別不同的包。例如,除了信息設定一個較高的水平 - 如嚴重的 - 對於厭惡包com.mff.ftps

# handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler 
handlers=java.util.logging.FileHandler 

# Set ROOT logger level 
.level=INFO 
com.mff.ftps.level=SEVERE 
# Set any number specifications: <package.path>.level=<LOGLEVEL> 

java.util.logging.ConsoleHandler.level=WARNING 
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 

java.util.logging.FileHandler.level=FINEST 
java.util.logging.FileHandler.pattern=myLogFile.log 
java.util.logging.FileHandler.limit=1073741824 # 1MB 
java.util.logging.FileHandler.count=2 
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter 

當您啓動java中,指定日誌屬性文件:

的Java -Djava.util.logging.config.file=<pathTo>/myLog.properties -cp .. 。

或編寫代碼:

File logPropFile = new File("<pathTo>/myLog.properties"); 
InputStream logPropStream = new FileInputStream(logPropFile); 
try { 
    LogManager.getLogManager().readConfiguration(logPropStream); 
} 
finally { 
    logPropStream.close(); 
} 
+0

謝謝,但解決方案是設置'javax.net.debug'。 – Annjawn 2012-07-30 14:06:20