感谢:http://byx5185.iteye.com/blog/1616034

1、重写DailyRollingFileAppender :

设置 maxFileSize 和 maxBackupIndex

package com.xxx.xxx.util;  import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;  import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.spi.LoggingEvent;  /** * MyDailyRollingFileAppender extends {@link FileAppender} so that the underlying * file is rolled over at a user chosen frequency. *  * <p> * The rolling schedule is specified by the <b>DatePattern</b> option. This * pattern should follow the {@link SimpleDateFormat} conventions. In * particular, you <em>must</em> escape literal text within a pair of single * quotes. A formatted version of the date pattern is used as the suffix for the * rolled file name. *  * <p> * For example, if the <b>File</b> option is set to <code>/foo/bar.log</code> * and the <b>DatePattern</b> set to <code>'.'yyyy-MM-dd</code>, on 2001-02-16 * at midnight, the logging file <code>/foo/bar.log</code> will be copied to * <code>/foo/bar.log.2001-02-16</code> and logging for 2001-02-17 will continue * in <code>/foo/bar.log</code> until it rolls over the next day. *  * <p> * Is is possible to specify monthly, weekly, half-daily, daily, hourly, or * minutely rollover schedules. *  * <p> * <table border="1" cellpadding="2"> * <tr> * <th>DatePattern</th> * <th>Rollover schedule</th> * <th>Example</th> *  * <tr> * <td><code>'.'yyyy-MM</code> * <td>Rollover at the beginning of each month</td> *  * <td>At midnight of May 31st, 2002 <code>/foo/bar.log</code> will be copied to * <code>/foo/bar.log.2002-05</code>. Logging for the month of June will be * output to <code>/foo/bar.log</code> until it is also rolled over the next * month. *  * <tr> * <td><code>'.'yyyy-ww</code> *  * <td>Rollover at the first day of each week. The first day of the week depends * on the locale.</td> *  * <td>Assuming the first day of the week is Sunday, on Saturday midnight, June * 9th 2002, the file <i>/foo/bar.log</i> will be copied to * <i>/foo/bar.log.2002-23</i>. Logging for the 24th week of 2002 will be output * to <code>/foo/bar.log</code> until it is rolled over the next week. *  * <tr> * <td><code>'.'yyyy-MM-dd</code> *  * <td>Rollover at midnight each day.</td> *  * <td>At midnight, on March 8th, 2002, <code>/foo/bar.log</code> will be copied * to <code>/foo/bar.log.2002-03-08</code>. Logging for the 9th day of March * will be output to <code>/foo/bar.log</code> until it is rolled over the next * day. *  * <tr> * <td><code>'.'yyyy-MM-dd-a</code> *  * <td>Rollover at midnight and midday of each day.</td> *  * <td>At noon, on March 9th, 2002, <code>/foo/bar.log</code> will be copied to * <code>/foo/bar.log.2002-03-09-AM</code>. Logging for the afternoon of the 9th * will be output to <code>/foo/bar.log</code> until it is rolled over at * midnight. *  * <tr> * <td><code>'.'yyyy-MM-dd-HH</code> *  * <td>Rollover at the top of every hour.</td> *  * <td>At approximately 11:00.000 o'clock on March 9th, 2002, * <code>/foo/bar.log</code> will be copied to * <code>/foo/bar.log.2002-03-09-10</code>. Logging for the 11th hour of the 9th * of March will be output to <code>/foo/bar.log</code> until it is rolled over * at the beginning of the next hour. *  *  * <tr> * <td><code>'.'yyyy-MM-dd-HH-mm</code> *  * <td>Rollover at the beginning of every minute.</td> *  * <td>At approximately 11:23,000, on March 9th, 2001, <code>/foo/bar.log</code> * will be copied to <code>/foo/bar.log.2001-03-09-10-22</code>. Logging for the * minute of 11:23 (9th of March) will be output to <code>/foo/bar.log</code> * until it is rolled over the next minute. *  * </table> *  * <p> * Do not use the colon ":" character in anywhere in the <b>DatePattern</b> * option. The text before the colon is interpeted as the protocol specificaion * of a URL which is probably not what you want. */
public class MyDailyRollingFileAppender extends FileAppender {  // The code assumes that the following constants are in a increasing  // sequence.  static final int TOP_OF_TROUBLE = -1;  static final int TOP_OF_MINUTE = 0;  static final int TOP_OF_HOUR = 1;  static final int HALF_DAY = 2;  static final int TOP_OF_DAY = 3;  static final int TOP_OF_WEEK = 4;  static final int TOP_OF_MONTH = 5;  /** * The default maximum file size is 10MB. */  protected long maxFileSize = 10 * 1024 * 1024;  /** * There is one backup file by default. */  protected int maxBackupIndex = 1;  /** * The date pattern. By default, the pattern is set to "'.'yyyy-MM-dd" * meaning daily rollover. */  private String datePattern = "'.'yyyy-MM-dd";  /** * The log file will be renamed to the value of the scheduledFilename * variable when the next interval is entered. For example, if the rollover * period is one hour, the log file will be renamed to the value of * "scheduledFilename" at the beginning of the next hour. *  * The precise time when a rollover occurs depends on logging activity. */  private String scheduledFilename;  /** * The next time we estimate a rollover should occur. */  private long nextCheck = System.currentTimeMillis() - 1;  Date now = new Date();  SimpleDateFormat sdf;  RollingCalendar rc = new RollingCalendar();  int checkPeriod = TOP_OF_TROUBLE;  // The gmtTimeZone is used only in computeCheckPeriod() method.  static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");  /** * The default constructor does nothing. */  public MyDailyRollingFileAppender() {  }  /** * Instantiate a <code>MyDailyRollingFileAppender</code> and open the file * designated by <code>filename</code>. The opened filename will become the * ouput destination for this appender. */  public MyDailyRollingFileAppender(Layout layout, String filename,  String datePattern) throws IOException {  super(layout, filename, true);  this.datePattern = datePattern;  activateOptions();  }  /** * Get the maximum size that the output file is allowed to reach before * being rolled over to backup files. *  * @since 1.1 */  public long getMaximumFileSize() {  return maxFileSize;  }  /** * Set the maximum size that the output file is allowed to reach before * being rolled over to backup files. *  * <p> * This method is equivalent to {@link #setMaxFileSize} except that it is * required for differentiating the setter taking a <code>long</code> * argument from the setter taking a <code>String</code> argument by the * JavaBeans {@link java.beans.Introspector Introspector}. *  * @see #setMaxFileSize(String) */  public void setMaximumFileSize(long maxFileSize) {  this.maxFileSize = maxFileSize;  }  /** * Set the maximum size that the output file is allowed to reach before * being rolled over to backup files. *  * <p> * In configuration files, the <b>MaxFileSize</b> option takes an long * integer in the range 0 - 2^63. You can specify the value with the * suffixes "KB", "MB" or "GB" so that the integer is interpreted being * expressed respectively in kilobytes, megabytes or gigabytes. For example, * the value "10KB" will be interpreted as 10240. */  public void setMaxFileSize(String value) {  maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);  }  /** * Returns the value of the <b>MaxBackupIndex</b> option. */  public int getMaxBackupIndex() {  return maxBackupIndex;  }  /** * Set the maximum number of backup files to keep around. *  * <p> * The <b>MaxBackupIndex</b> option determines how many backup files are * kept before the oldest is erased. This option takes a positive integer * value. If set to zero, then there will be no backup files and the log * file will be truncated when it reaches <code>MaxFileSize</code>. */  public void setMaxBackupIndex(int maxBackups) {  this.maxBackupIndex = maxBackups;  }  /** * The <b>DatePattern</b> takes a string in the same format as expected by * {@link SimpleDateFormat}. This options determines the rollover schedule. */  public void setDatePattern(String pattern) {  datePattern = pattern;  }  /** Returns the value of the <b>DatePattern</b> option. */  public String getDatePattern() {  return datePattern;  }  public void activateOptions() {  super.activateOptions();  if (datePattern != null && fileName != null) {  now.setTime(System.currentTimeMillis());  sdf = new SimpleDateFormat(datePattern);  int type = computeCheckPeriod();  printPeriodicity(type);  rc.setType(type);  File file = new File(fileName);  scheduledFilename = fileName  + sdf.format(new Date(file.lastModified()));  } else {  LogLog.error("Either File or DatePattern options are not set for appender ["  + name + "].");  }  }  void printPeriodicity(int type) {  switch (type) {  case TOP_OF_MINUTE:  LogLog.debug("Appender [" + name + "] to be rolled every minute.");  break;  case TOP_OF_HOUR:  LogLog.debug("Appender [" + name  + "] to be rolled on top of every hour.");  break;  case HALF_DAY:  LogLog.debug("Appender [" + name  + "] to be rolled at midday and midnight.");  break;  case TOP_OF_DAY:  LogLog.debug("Appender [" + name + "] to be rolled at midnight.");  break;  case TOP_OF_WEEK:  LogLog.debug("Appender [" + name  + "] to be rolled at start of week.");  break;  case TOP_OF_MONTH:  LogLog.debug("Appender [" + name  + "] to be rolled at start of every month.");  break;  default:  LogLog.warn("Unknown periodicity for appender [" + name + "].");  }  }  // This method computes the roll over period by looping over the  // periods, starting with the shortest, and stopping when the r0 is  // different from from r1, where r0 is the epoch formatted according  // the datePattern (supplied by the user) and r1 is the  // epoch+nextMillis(i) formatted according to datePattern. All date  // formatting is done in GMT and not local format because the test  // logic is based on comparisons relative to 1970-01-01 00:00:00  // GMT (the epoch).  int computeCheckPeriod() {  RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone,  Locale.ENGLISH);  // set sate to 1970-01-01 00:00:00 GMT  Date epoch = new Date(0);  if (datePattern != null) {  for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {  SimpleDateFormat simpleDateFormat = new SimpleDateFormat(  datePattern);  simpleDateFormat.setTimeZone(gmtTimeZone); // do all date  // formatting in GMT  String r0 = simpleDateFormat.format(epoch);  rollingCalendar.setType(i);  Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));  String r1 = simpleDateFormat.format(next);  // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);  if (r0 != null && r1 != null && !r0.equals(r1)) {  return i;  }  }  }  return TOP_OF_TROUBLE; // Deliberately head for trouble...
    }  /** * Implements the usual roll over behaviour. *  * <p> * If <code>MaxBackupIndex</code> is positive, then files { * <code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code> are renamed * to {<code>File.2</code>, ..., <code>File.MaxBackupIndex</code> . * Moreover, <code>File</code> is renamed <code>File.1</code> and closed. A * new <code>File</code> is created to receive further log output. *  * <p> * If <code>MaxBackupIndex</code> is equal to zero, then the * <code>File</code> is truncated with no backup files created. */  public// synchronization not necessary since doAppend is alreasy synched  void sizeRollOver() {  File target;  File file;  LogLog.debug("rolling over count="  + ((CountingQuietWriter) qw).getCount());  LogLog.debug("maxBackupIndex=" + maxBackupIndex);  String datedFilename = fileName + sdf.format(now);  if (maxBackupIndex > 0) {  // Delete the oldest file, to keep Windows happy.  file = new File(datedFilename + '.' + maxBackupIndex);  if (file.exists())  file.delete();  // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,  // 2}  for (int i = maxBackupIndex - 1; i >= 1; i--) {  file = new File(datedFilename + "." + i);  if (file.exists()) {  target = new File(datedFilename + '.' + (i + 1));  LogLog.debug("Renaming file " + file + " to " + target);  file.renameTo(target);  }  }  // Rename fileName to datedFilename.1  target = new File(datedFilename + "." + 1);  this.closeFile(); // keep windows happy.
  file = new File(fileName);  LogLog.debug("Renaming file " + file + " to " + target);  file.renameTo(target);  }else if (maxBackupIndex < 0){//infinite number of files   //find the max backup index  for (int i = 1; i < Integer.MAX_VALUE; i++) {  target = new File(datedFilename + "." + i);  if (! target.exists()) {//Rename fileName to datedFilename.i  this.closeFile();  file = new File(fileName);  file.renameTo(target);  LogLog.debug("Renaming file " + file + " to " + target);  break;  }  }  }  try {  // This will also close the file. This is OK since multiple  // close operations are safe.  this.setFile(fileName, false, bufferedIO, bufferSize);  } catch (IOException e) {  LogLog.error("setFile(" + fileName + ", false) call failed.", e);  }  scheduledFilename = datedFilename;  }  public synchronized void setFile(String fileName, boolean append,  boolean bufferedIO, int bufferSize) throws IOException {  super.setFile(fileName, append, this.bufferedIO, this.bufferSize);  if (append) {  File f = new File(fileName);  ((CountingQuietWriter) qw).setCount(f.length());  }  }  protected void setQWForFiles(Writer writer) {  this.qw = new CountingQuietWriter(writer, errorHandler);  }  /** * Rollover the current file to a new file. */  void timeRollOver() throws IOException {  /* Compute filename, but only if datePattern is specified */  if (datePattern == null) {  errorHandler.error("Missing DatePattern option in rollOver().");  return;  }  String datedFilename = fileName + sdf.format(now);  // It is too early to roll over because we are still within the  // bounds of the current interval. Rollover will occur once the  // next interval is reached.  if (scheduledFilename.equals(datedFilename)) {  return;  }  // close current file, and rename it to datedFilename  this.closeFile();  File target = new File(scheduledFilename);  if (target.exists()) {  target.delete();  }  File file = new File(fileName);  boolean result = file.renameTo(target);  if (result) {  LogLog.debug(fileName + " -> " + scheduledFilename);  } else {  LogLog.error("Failed to rename [" + fileName + "] to ["  + scheduledFilename + "].");  }  try {  // This will also close the file. This is OK since multiple  // close operations are safe.  super.setFile(fileName, false, this.bufferedIO, this.bufferSize);  } catch (IOException e) {  errorHandler.error("setFile(" + fileName + ", false) call failed.");  }  scheduledFilename = datedFilename;  }  /** * This method differentiates MyDailyRollingFileAppender from its super class. *  * <p> * Before actually logging, this method will check whether it is time to do * a rollover. If it is, it will schedule the next rollover time and then * rollover. * */  protected void subAppend(LoggingEvent event) {  long n = System.currentTimeMillis();  if (n >= nextCheck) {  now.setTime(n);  nextCheck = rc.getNextCheckMillis(now);  try {  timeRollOver();  } catch (IOException ioe) {  LogLog.error("rollOver() failed.", ioe);  }  } else if ((fileName != null)  && ((CountingQuietWriter) qw).getCount() >= maxFileSize) {  sizeRollOver();  }  super.subAppend(event);  }
}  /** * RollingCalendar is a helper class to MyDailyRollingFileAppender. Given a * periodicity type and the current time, it computes the start of the next * interval. * */
class RollingCalendar extends GregorianCalendar {  int type = MyDailyRollingFileAppender.TOP_OF_TROUBLE;  RollingCalendar() {  super();  }  RollingCalendar(TimeZone tz, Locale locale) {  super(tz, locale);  }  void setType(int type) {  this.type = type;  }  public long getNextCheckMillis(Date now) {  return getNextCheckDate(now).getTime();  }  public Date getNextCheckDate(Date now) {  this.setTime(now);  switch (type) {  case MyDailyRollingFileAppender.TOP_OF_MINUTE:  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  this.add(Calendar.MINUTE, 1);  break;  case MyDailyRollingFileAppender.TOP_OF_HOUR:  this.set(Calendar.MINUTE, 0);  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  this.add(Calendar.HOUR_OF_DAY, 1);  break;  case MyDailyRollingFileAppender.HALF_DAY:  this.set(Calendar.MINUTE, 0);  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  int hour = get(Calendar.HOUR_OF_DAY);  if (hour < 12) {  this.set(Calendar.HOUR_OF_DAY, 12);  } else {  this.set(Calendar.HOUR_OF_DAY, 0);  this.add(Calendar.DAY_OF_MONTH, 1);  }  break;  case MyDailyRollingFileAppender.TOP_OF_DAY:  this.set(Calendar.HOUR_OF_DAY, 0);  this.set(Calendar.MINUTE, 0);  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  this.add(Calendar.DATE, 1);  break;  case MyDailyRollingFileAppender.TOP_OF_WEEK:  this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());  this.set(Calendar.HOUR_OF_DAY, 0);  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  this.add(Calendar.WEEK_OF_YEAR, 1);  break;  case MyDailyRollingFileAppender.TOP_OF_MONTH:  this.set(Calendar.DATE, 1);  this.set(Calendar.HOUR_OF_DAY, 0);  this.set(Calendar.SECOND, 0);  this.set(Calendar.MILLISECOND, 0);  this.add(Calendar.MONTH, 1);  break;  default:  throw new IllegalStateException("Unknown periodicity type.");  }  return getTime();  }
}  

2、 log4j.properties文件中配置:

其中MyDailyRollingFileAppender为重写的DailyRollingFileAppender。
# Set root logger level to DEBUG and its only appender to CONSOLE.
log4j.rootLogger=INFO,log,CONSOLE#CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%t] %-5p %C{1} : %m%n#route trace log
log4j.appender.log=org.apache.log4j.RollingFileAppender
log4j.appender.log.File=/route/route-trace-${log.name}.log
log4j.appender.log.MaxFileSize=200000KB
log4j.appender.log.MaxBackupIndex=100
log4j.appender.log.layout=org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}[%t][%c][%p]-%m%n#SQL
log4j.logger.java.sql.Connection=INFO
log4j.logger.java.sql.Statement=INFO
log4j.logger.java.sql.PreparedStatement=INFO
log4j.logger.java.sql.ResultSet=INFO#monitor
log4j.logger.monitorlog=INFO,monitorFile
log4j.additivity.monitorlog = false
log4j.appender.monitorFile=com.xxx.xxx.util.MyDailyRollingFileAppender
log4j.appender.monitorFile.File=/route/lala.log
log4j.appender.monitorFile.MaxFileSize=2KB
log4j.appender.monitorFile.maxBackupIndex=2
log4j.appender.monitorFile.layout=org.apache.log4j.PatternLayout
log4j.appender.monitorFile.layout.ConversionPattern=%m%n

转载于:https://www.cnblogs.com/amunamuna/p/8664072.html

DailyRollingFileAppender-设置文件大小和备份数相关推荐

  1. 【Kafka】Kafka-分区数-备份数-如何设置-怎么确定-怎么修改

    Kafka-分区数-备份数-如何设置-怎么确定-怎么修改 kafka partition 数量 更新_百度搜索kafka重新分配partition - - CSDN博客如何为Kafka集群选择合适的P ...

  2. ov5640帧率配置_赛博朋克2077 优化设置大全!帧数50暴涨100

    最近随着赛博朋克2077终于开始正式上线(最终还是没能跳票到2077年),不少朋友都购买了游戏,准备体验夜之城的生活.然而,游戏对配置的高要求,导致很多朋友发现买了游戏,却带不动. 甚至部分测评视频, ...

  3. 宝塔如何备份网站_宝塔面板如何设置网站自动备份?

    为了让网站持续稳定的运行,定期对网站进行备份是必不可少的工作之一.可以规避由于服务器故障.数据迁移.网站调试.网络攻击等方面带来的风险. 备份的方法很多,不怕麻烦的话可以定期手动备份到本地,便捷的方法 ...

  4. oracle存档模式,Oracle开启归档模式并设置RMAN自动备份策略

    title: Oracle开启归档模式并设置RMAN自动备份策略 categories: 数据库 tags: - Oracle - RMAN timezone: Asia/Shanghai date: ...

  5. ITK:设置默认的线程数

    ITK:设置默认的线程数 内容提要 输出结果 C++实现代码 内容提要 设置多线程的默认线程数. 还可以通过环境变量ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS设置默认线程 ...

  6. 线程池应该设置多少核心线程数——Java多线程系列学习笔记

    前言 本章主要讨论线程池合适的线程数量是多少,以及 CPU 核心数和线程数的关系.我们调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能.在 ...

  7. 深圳家庭数据存储 家庭数据备份 数蚁科技

    深圳家庭数据存储 家庭数据备份 数蚁科技 使用数蚁家庭数据存储撰写家庭计划,发起讨论.让一切计划有序进行.出游计划,使用数蚁家庭数据存储规划家庭出游地点.途经 风景点.食宿安排以及注意事项,和家人一起 ...

  8. 使用晨曦记账本,根据需要设置记账表格行数

    生活开支只可以依照收入和支出设置类别进行记录,我们在使用晨曦记账本添加收支时,一次记录多笔,如何设置记录的行数呢?下面一起来看设置步骤吧. 在电脑上登录上晨曦记账本,主界面上都很简洁.功能简单都可浏览 ...

  9. fedora中的一些设置与操作备份

    Virtual Box yum -y install VirtualBox 85  uname -all    86  uname -a    87  yum list  Virtual*    88 ...

最新文章

  1. 【Nginx】epoll事件驱动模块
  2. Jenkins 无法捕获构建脚本错误问题
  3. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载
  4. php 剩余空间,PHP内核探索:内存的申请与销毁
  5. 深度学习框架TensorFlow(4.Fetch and Feed)
  6. eclipse中hibernate和mybatis中xml配置文件的没有标签提醒解决方法
  7. Your PC needs to be repaired
  8. Crystal Reports第一张报表
  9. spring相互依赖怎么解决_被问到Spring循环依赖怎么解决?秀给面试官看!内附图解...
  10. python cv.rectangle_Python OpenCV cv2.rectangle()用法及代码示例
  11. 用Caffe搭建自己的网络,并用图片进行测试
  12. eclipse没有java project_用ecilpse开发一个java程序
  13. 腾讯地图计算两点间距离
  14. 帝国栏目导航点击显示不同样式的实现
  15. 使用 Kubernetes Ingress 对外暴露服务
  16. tc7102路由器虚拟服务器,国内电信推首款WiFi 6+路由器TC7102,5G和WiFi 6成黄金搭档-贤集网...
  17. excel删除重复的行_如何在Excel中删除重复的行
  18. storyboard(故事版)新手教程 图文详解 2.为无约束的故事版添加约束
  19. ffmpeg简易使用应用分享(m3u8下载与视频合并等)
  20. 【整理】Libav、FFmpeg、mplayer、VLC开源项目、FFDshow

热门文章

  1. 通过一个例子学习Kubernetes里的PersistentVolumeClaim的用法
  2. 如何解决ipconfig、ping不是内部或外部命令
  3. tplink 跨路由器 共享打印机_焦作联通案例分享:跨网段通过防火墙共享打印机设置...
  4. luci L大_“大众”果然没失望,空间大,颜值暴增
  5. vs2013 未将对象引用设置到对象的实例
  6. 分布式资源管理框架YARN的运行流程
  7. u9系统的使用方法仓库_新风系统如何使用 新风系统使用方法介绍【图文】
  8. python pip全称_“ pip install”和“ pip install”之间有什么区别和“ python -m pip install”?...
  9. linux颜色吸取工具,8 个优秀的 Linux 图形图像及色彩工具
  10. 为什么C和C++难以被取代?