当前位置: 首页 > news >正文

Spring Boot 日志

目录

1.概述

2.切换日志实现

3.使用

3.1.日志级别

3.3.日志离线

3.4.详细定制


1.概述

由一些历史原因,JAVA领域存在有很多日志框架,如Log4j、Logback、log4j2。

log4j是Java日志框架的元老,在log4j被Apache Foundation收入门下之后,由于理念不合,log4j的作者Ceki离开并开发了slf4j和logback。这几个框架都很热门,这就造成了不同系统、不同开源框架使用的日志框架都不同。

因为不同日志框架的日志输出格式、API均不同,所以当系统中存在多种日志框架被混用就会出现冲突,最直接的现象就是——日志格式不统一,这对项目的日志排查来说是极不方便的,甚至有时候还会因为日志框架的冲突而报错。因此同一个项目中统一日志框架是十分有必要的,但是如果只是单纯的保留一个日志框架,移除其余日志框架,由于各日志系统API的不同很可能系统根本就起不来,所以需要一个中间层来进行适配,从而解决这个问题。

这个中间层就是——日志门面。日志门面使用门面模式屏蔽掉了不同日志实现之间的不同,对外暴露统一的API。

2.切换日志实现

SpringBoot默认使用SLF4J作为日志门面,LogBack作为日志实现来记录日志。

这里我们不去细究SLF4J是怎么去完成适配的,只需要知道SpringBoot自带了日志门面,使用日志门面来输出日志,当想要切换日志实现的时候,排掉LogBack,引入新的实现即可。

以切换为log4j2为例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--1. 排除掉依赖 ,以此排除掉logback+slf4j引用-->
    <exclusions>
         <exclusion>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-logging</artifactId>
          </exclusion>
     </exclusions>
</dependency>
<!--2. 添加log4j2依赖 -->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

3.使用

3.1.日志级别

配置:

可以指定全局日志等级,也可以以方法为粒度指定日志等级,支持*作为通配符

#全局日志等级
logging.level.root=trace
#单都指定日志等级
logging.level.com.eryi.controller.MyRunner.*=trace

代码:

package com.eryi.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class MyRunner implements CommandLineRunner {//特别注意,要使用slf4j的Logger和LoggerFactoryLogger logger= LoggerFactory.getLogger(MyRunner.class);@Overridepublic void run(String... args) throws Exception {//日志级别:error<warn<info<debug<tracelogger.trace("trace......");logger.debug("debug......");//Spring Boot默认使用info级别logger.info("info......");logger.warn("warn......");logger.error("error......");}
}

3.3.日志离线

不指定路径,日志文件只会在控制台输出,不会离线为本地文件。

使用path可以指定路径,文件名默认使用springlog.log

使用file可以指定路径+文件名,不指定路径会默认离现在工程目录下。

file和path是两个冲突设置,如果同时配置,只有file会生效。

3.4.详细定制

spring boot的配置文件中的日志配置项只能进行粗粒度的配置,想对日志进行细粒度的定制需要在类路径下(一般是在resources下)编写xml配置文件。命名规则为XXX-spring.xml,XXX是日志框架的名称。

以下为一个logback-spring.xml的模板:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
     configuration中有appender、logger、root三个节点
      appender:表示的是定义了一种文件的输出格式  就有点类似于 变量进行了定义 但是没有来得及使用
      logger:这个就表示的是我们定义了这个变量在哪一个局部能够使用
              我们的日志原本是针对于整个工程的配置  但是你可以定义在哪一个包里面  使用什么日志输出格式 以及 输出到哪些地方
      root:相当于定义的是整个项目 的日志输出级别  以及 输出日志到哪些地方
    -->

    <!--
       定义了日志的输出  ConsoleAppender  这个类表示的是输出到控制台
    -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--设置输出到控制台的编码和格式

        %d{yyyy-MM-dd-HH:mm:ss.SSS}:这个表示的是时间的引用
        %level:当前输出的日志级别
        [%thread]:表示当前是哪一个线程
        %class:这个表示的是这个日志是在哪一个类中打印出来的
        %line:这个表示的是打印这个日志是在这个类的 哪一行打印出来的
        %msg:这个表示的是打印的消息是什么
        %n:这个表示的是换行
        -->
        <encoder>
            <pattern>%d{yyyy-MM-dd-HH:mm:ss.SSS}------->%level--------->[%thread]-%class:%line----->%msg%n</pattern>
            <!--设置了打印到控制台的编码-->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!--
       定义日志输出到文件的格式
       name:是可以随便写的   FileAppender:输出到文件
    -->
    <appender name="file" class="ch.qos.logback.core.FileAppender">

        <!--这个表示的是日志文件输出的路径  这个默认表示的是输出到当前项目的根目录下 叫做file.log-->
        <file>log/file.log</file>
        <!--这个表示的是 每一次写日志的时候是在上一次的基础上进行追加-->
        <append>true</append>
        <encoder>
            <!--定义了输出的格式-->
            <pattern>%d{yyyy-MM-dd-HH:mm:ss.SSS} %level    [%thread]-%class:%line>>%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!--
            prudent=true:表示的是日志的写入是线程安全的、但是线程安全会降低效率  一般默认设置为false
        -->
        <prudent>false</prudent>
    </appender>

    <!--
       RollingFileAppender:表示的是日志要滚动输出

    -->
    <appender name="timeFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--
            rollingPolicy滚动的策略
            TimeBasedRollingPolicy:最常用的一个、根据时间进行滚动 当达到一定的时间的时候、就会自动开辟一个新的日志文件
            FixedWindowRollingPolicy:根据固定窗口的算法重命名文件的滚动策略
            TriggeringPolicy:根据当前活动文件的大小来来确定是否滚动
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件的名字  引用了当前的日期-->
            <fileNamePattern>log/logFile%d{yyyy-MM-dd}.log</fileNamePattern>
            <!--生成这个日志文件 保留多少天-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--编码的格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd-HH:mm:ss.SSS} %level    [%thread]-%class:%line>>%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--
       RollingFileAppender:这个是滚动输出
       FixedWindowRollingPolicy:根据活动窗口算法的大小来滚动输出

    -->
    <appender name="fixedFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志的名字-->
        <file>log/fixedFile.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>log/fixedFile%i.log.zip</fileNamePattern>
            <!--最少生成一个日志文件-->
            <minIndex>1</minIndex>
            <!--最多生成3个日志文件-->
            <maxIndex>3</maxIndex>
        </rollingPolicy>

        <!--根据文件的大小来设置滚动输出的-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!--日志文件的最大的大小-->
            <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>
        <!--日志输出的格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd-HH:mm:ss.SSS} %level    [%thread]-%class:%line>>%msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!--文件输出-->
    <appender name="filter" class="ch.qos.logback.core.FileAppender">
        <file>log/filter.log</file>
        <append>true</append>
        <!--
            LevelFilter:的意思是添加了一个日志级别的过滤器
            如果日志的级别等于配置的级别。那么则执行onMatch里面的配置
            否则执行 onMismatch中的内容
        -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <!--
                 ACCEPT:当前的日志会立即被执行不经过其他的过滤器了
                 DENY:日志立即被抛弃、也不再经过其他的过滤器了
                 NEUTRAL:下一个过滤器将继续执行、如果是最后一个过滤器的话那么就会被执行
            -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--临界值过滤器:如果你输出的日志级别 是低于下面定义的这个级别的话那么 就会被过滤掉-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>

        <encoder>
            <pattern>%d{yyyy-MM-dd-HH:mm:ss.SSS} %level    [%thread]-%class:%line>>%msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
        <prudent>false</prudent>
    </appender>

    <!--设置局部的 这个日志的输出级别 或者 是 在哪里输出日志-->

                <!--测试的路径-->
    <!--    <logger name="com.project.controller" level="trace" addtivity="false">
            <appender-ref ref="stdout" />
            <appender-ref ref="file" />
            <appender-ref ref="timeFile" />
        </logger>-->

    <!--这个是给全局设置一个日志级别  所有的都适用
        appender-ref :全局的日志我们要打印到哪些地方

    -->
    <root level="error">
<!--        打印到控制台-->
        <appender-ref ref="stdout" />
<!--        打印到file文件里-->
        <appender-ref ref="file" />
        <appender-ref ref="timeFile" />
        <!--<appender-ref ref="fixedFile" />-->
        <!--<appender-ref ref="filter" />-->
    </root>

</configuration>
 

相关文章:

Spring Boot 日志

目录 1.概述 2.切换日志实现 3.使用 3.1.日志级别 3.3.日志离线 3.4.详细定制 1.概述 由一些历史原因&#xff0c;JAVA领域存在有很多日志框架&#xff0c;如Log4j、Logback、log4j2。 log4j是Java日志框架的元老&#xff0c;在log4j被Apache Foundation收入门下之后&a…...

好用的研发管理看板工具有哪些?10款主流看板管理软件盘点

10大企业看板工具软件&#xff1a;1.软件开发项目看板 PingCode&#xff1b;2.通用看板软件 Worktile&#xff1b;3.开源看板软件 Wekan&#xff1b;4.免费看板软件 Trello&#xff1b;5.个人和小团队的看板软件 Todoist &#xff1b;6.开源免费看 Kanboard&#xff1b;7.面向个…...

【软考系统架构设计师】2022下案例分析历年真题

【软考系统架构设计师】2022下案例分析历年真题 【软考系统架构设计师】2022下案例分析历年真题【软考系统架构设计师】2022下案例分析历年真题2022下案例分析历年真题第一题&#xff08;25分&#xff09;2022下案例分析历年真题第二题&#xff08;25分&#xff09;2022下案例分…...

Java skill - @JsonAlias 和 @JsonProperty

Java skill - JsonAlias 和 JsonPropertyJava skill系列目录&#xff1a;JsonAlias 和 JsonProperty使用 JsonProperty 的麻烦场景&#xff1a;使用 JsonAlias 应对麻烦场景&#xff1a;Java skill系列目录&#xff1a; 【Java skill - 统计耗时用StopWatch】 【Java skill - …...

【实际开发18】- 静态 3

目录 1. 调试与评估 2. 单元测试的管理 1. 单元测试的文档 3. 系统集成的模式与方法 1. 集成测试前的准备 2. 集成测试的模式 3. 大棒集成方法 ( Big-bang Integration) 4. 自顶向下和自底向上集成方法 1. 自顶向下法 ( Top-down Integration ) 2. 自底向上法 ( Bott…...

【swagger2】开发api文档

文章目录一、swagger2 简介背景Open API ???swagger2的作用swagger2常用工具组件&#xff1a;二、Springfox三、springBoot使用swagger2&#xff08;简单示例&#xff09;四、Swagger-UI使用五、配置文件1、配置类&#xff1a;给docket上下文配置api描述信息2、配置类&#…...

Github 上如何提交 pull request

什么是复刻&#xff08;forking&#xff09;? 我们可以通过复刻操作将喜爱的仓库保存自己的Github账户中&#xff0c;以便独立地对其进行操作。 通过复刻&#xff0c;我们可以得到包含完整版本历史的目标仓库的实例&#xff0c;之后可以对复刻得到的仓库进行任意操作而不会影响…...

Redis面试知识

概述 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能…...

Spring面试重点(四)——Spring事务

Spring事务 事务的方式 spring中使用事务有两种方式&#xff0c;一种是编程式事务&#xff0c;一种是声明式事务。编程式事务推荐使用TransactionTemplate&#xff0c;实现TransactionCallback接口&#xff0c;需要编码实现&#xff1b;声明式事务只需要在函数增加注解Transa…...

♡ — MySQL 存储引擎

MySQL 存储引擎架构 MySQL 存储引擎采用的是插件式架构&#xff0c;支持多种存储引擎&#xff0c;我们甚至可以为不同的数据库设置不同的存储引擎以适应不同场景的需要&#xff1b;存储引擎是基于表的&#xff0c;而不是数据库。 MyISAM 和 InnoDB 的区别 MySQL 5.5 之前&am…...

大数据技术架构(组件)34——Spark:Spark SQL--Optimize

2.2.3、Optimize2.2.3.1、SQL3.3.1.1、RB1、Join选择在Hadoop中&#xff0c;MR使用DistributedCache来实现mapJoin。即将小文件存放到DistributedCache中&#xff0c;然后分发到各个Task上&#xff0c;并加载到内存中&#xff0c;类似于Map结构&#xff0c;然后借助于Mapper的迭…...

Zookeeper实现分布式锁

文章目录ZK节点类型watch监听机制Zookeeper实现分布式锁锁原理创建锁的过程释放锁的过程ZK锁的种类代码实现Zookeeper是一个开源的分布式协调服务&#xff0c;是一个典型的分布式数据一致性解决方案。 分布式应用程序可以基于Zookeeper实现诸如数据发布/订阅&#xff0c;负载均…...

MFC 添加重新启动管理器支持

重启管理器是添加到 Visual Studio for Windows Vista 或更高版本操作系统的功能 如果发生意外关闭或重启&#xff0c;重新启动管理器将为你的应用程序添加支持。 重新启动管理器的行为取决于应用程序的类型。 如果你的应用程序是文档编辑器&#xff0c;则重新启动管理器让应用…...

一文带你深刻的进入Python,并且了解Python的优缺点

最近几年Python被吹的神乎其神&#xff0c;很多同学都不清楚Python到底能干什么&#xff1f;就盲目去学习Python,今天我就Python的应用领域来简单盘点一下&#xff0c;让想学习Python 的同学找对方向不迷茫。 2. Python 的特点 这里就谈谈自己的看法&#xff0c;首先 Python是…...

别具一格,原创唯美浪漫情人节表白专辑,(复制就可用)(html5,css3,svg)表白爱心代码(4)

别具一格,独此一家&#xff0c;原创唯美浪漫情人节表白专辑 不一样的惊喜哦~&#xff01;&#xff08;html5,css3,svg)表白爱心代码&#xff08;复制就可用&#xff09;&#xff08;4&#xff09; 目录 款式四&#xff1a;时光的记忆款 1、拷贝完整源代码 2、更新时光盒所…...

编译原理—翻译方案、属性栈代码

系列文章戳这里&#x1f447; 什么是上下文无关文法、最左推导和最右推导如何判断二义文法及消除文法二义性何时需要消除左递归什么是句柄、什么是自上而下、自下而上分析什么是LL(1)、LR(0)、LR(1)文法、LR分析表LR(0)、SLR(1)、LR(1)、LALR(1)文法之间的关系编译原理第三章习…...

链表

一、从尾到头打印链表题目&#xff1a;输入一个链表&#xff0c;按链表从尾到头的顺序返回一个ArrayList。解题思路&#xff1a;使用栈作为中转&#xff0c;可以实现倒置打印classSolution { public:vector<int> printListFromTailToHead(ListNode* head){//使用栈完成中…...

CSS 样式优先级

CSS 样式优先级决定了最终呈现在浏览器中的样式是哪一组样式&#xff0c;在多组样式中有冲突时&#xff0c;最终呈现在浏览器中的样式是具有最高优先级的样式。 CSS 样式优先级顺序如下&#xff1a; 内联样式 > 内部样式 > 外部样式 !important > 内联样式 > ID…...

SpingMVC获取请求参数

通过ServletAPI获取请求参数将HttpServletRequest作为控制器方法的形参&#xff0c;此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象。html<form th:action"{/param/servletAPI}" method"post">用户名&#xff1a;<input ty…...

微搭使用笔记(二)微搭低代码平台介绍及基础使用

概述 官网地址&#xff1a; 官网 官方文档&#xff1a; 官方文档 FAQ: FAQ 腾讯云微搭低代码是一个高性能的低代码开发平台&#xff0c;用户可通过拖拽式开发&#xff0c;可视化配置构建 PC Web、H5 和小程序应用。支持打通企业内部数据&#xff0c;轻松实现企业微信管理、工…...

CountDownLatch的定义、使用 、原理

一、定义 CountDownLatch的作用很简单&#xff0c;就是一个或者一组线程在开始执行操作之前&#xff0c;必须要等到其他线程执行完才可以。我们举一个例子来说明&#xff0c;在考试的时候&#xff0c;老师必须要等到所有人交了试卷才可以走。此时老师就相当于等待线程&#xff…...

《Terraform 101 从入门到实践》 Terraform在公有云Azure上的应用

《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新&#xff0c;书中的示例代码也是放在GitHub上&#xff0c;方便大家参考查看。 简介 Azure是微软的公有云&#xff0c;它提供了一些免费的资源&#xff0c;具体可以查看&#xff1a; https:/…...

别具一格,原创唯美浪漫情人节表白专辑,(复制就可用)(html5,css3,svg)表白爱心代码(3)

别具一格&#xff0c;原创唯美浪漫情人节表白专辑&#xff0c; (复制就可用)&#xff08;html5,css3,svg)表白爱心代码(3) 目录 款式三&#xff1a;心形实时显示认识多长时间桃花飞舞&#xff08;猫咪&#xff09;款 1、拷贝完整源代码 2、拷贝完整js代码 3、修改时间 4、…...

Linux 删除修改日期大于某一天的文件

在服务器运维过程中,我们往往会产生大量的日志文件. 如果日志文件命名能看出日志产生的时间,这些文件是很好删除的. 但有时,我们可能有成千上万的没有命名规律日志文件 下面的方法可以根据日志最后修改时间 批量删除这些文件 先给出完整命令: find /mydir -mtime 10 -name &…...

【算法题】1845. 座位预约管理系统

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 题目&#xff1a; 请你设计一个管理 n 个座位预约的系…...

【专业认知】保研北大金融 / 入职腾讯产品经理

2023.02.11 一. 朱博文学长分享——关于大学生活的一点思考 1. 自我介绍 大数据18级 经济学双学位 保研至北大金融硕士 “多思考、多感受、兼听则明” 2. 大学生活 2.1 为什么要上大学 1&#xff1a;追求美好生活的需要 “美好”难以量化&#xff0c;因为每个人对生活…...

OpenHarmony使用Socket实现一个UDP客户端详解

一、前言 我们在这里介绍Socket的使用,是为了后面的一篇文章实现设备配网做铺垫。 二、示例详解 点击获取BearPi-HM_Nano源码 ,以D3_iot_udp_client为例: 示例本身很简单,只需要修改 udp_client_demo.c 的2处代码,就能测试了: //连接WIFI,参数1是:WIFI名称,参数2是:…...

使用VUE自定义组件封装部门选择功能

背景 照惯例&#xff0c;先交待下背景&#xff0c;从真实需求出发&#xff0c;讲述实现效果、设计思路和实现方式。 软件系统中&#xff0c;会有一些常见常用的选择功能&#xff0c;如部门选择、人员选择等&#xff0c;用于填报表单&#xff0c;使用频率很高。直接使用一方面会…...

C语言基础应用(一)数据类型

一、数据类型 1、数据类型的分类 2、常量 常量是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。 2.1 常量举例 // 整型常量 举例 /*718 十进制0213 八进制0x4b 十六进制30u 无符号整数30l 长整型30ul 无符号长整型*/ // 浮点常量…...

算法笔记(三)—— 桶排序及排序总结

堆 逻辑上是一棵完全二叉树&#xff08;依次遍满或者全满&#xff09;。 数组可以转为完全二叉树&#xff0c;完全二叉树某结点左孩子(2*i1)&#xff0c;右孩子(i*22)&#xff0c;父结点((i-1/)2)&#xff0c;根节点的父还是自己。 如何将数组转化为堆&#xff08;大根堆&…...

金华网站建设优化技术/杭州数据推广

题意&#xff1a;每个人都有一个物品&#xff0c;对应一定的钱数&#xff0c;想要得到此物品可以直接出钱&#xff0c;也可以通过用其他人的物品并添加一些钱来交换&#xff0c;问要得到酋长的物品最少需要多少钱&#xff1f;另外&#xff0c;每个人都有一个等级&#xff0c;要…...

建设部网站一级建造师报名/软件开发培训机构去哪个学校

问题&#xff1a;之前做过类似题&#xff0c;但这次仍然不能解决相关问题。 字符串倒过来输&#xff1a;StringBuffer strnew StringBuffer(s); sstr.reverse().toString() Bitset Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total…...

iis怎么做IP网站/uc搜索引擎入口

多是以下三种情况 1 验证码需要的扩展没有安装或者没有开 一般都是GD库 2 文件有bom头影响了验证码的输出 用一些编辑器去除bom头 3 在验证码输出前缓冲区有内容 这种情况比较多 在验证码输出前调用一下 ob_clean()转载于:https://www.cnblogs.com/zwsblogs/p/9223280.html...

帮人做传销网站违法吗/seo需要懂代码吗

代谢与脂质组学平台服务项目&#xff1a;三羧酸循环通路分析/糖酵解/磷酸戊糖途径分析/脱氧核苷、核苷分析/ CoA 及相关代谢产物/嘌呤代谢产物分析/游离氨基酸分析/游离脂肪酸分析生物样品&#xffe5;300 /针(每一类)代谢流(Flux)分析/靶标性代谢组学/非靶向代谢组学/非靶向脂…...

淘宝客 wordpress 主题/大数据精准营销系统

1.首先安装mysql 具体教程可以参考https://blog.csdn.net/zhouzezhou/article/details/52446608 注意安装产品的时候记得选择MySQL Connector C&#xff0c;如图 2.安装好mysql之后&#xff0c;就开始配置&#xff0c;点击项目->点击项目属性&#xff0c;如图&#xff1a; 3…...

java做教程网站/免费个人博客网站

第1关:Hyperledger Fabric 基本概念 任务描述 本关任务:根据本实训的相关知识,完成与 Hyperledger Fabric 基本概念相关的选择题。 相关知识 超级账本介绍 超级账本,即 Hyperledger,是区块链技术中第一个面向企业级应用场景的开源分布式账本平台。 2015年12月由 Linux …...