Log4Net 日志组件通用代码

matese-fields-233175-unsplash.jpg | center | 827x550

概述

C# 领域最知名的日志组件非 Log4Net 莫属。一直以来都是现用现查手册,虽然浪费不了多少时间,但是这种习惯终归不好。于是,搜集了一份封装比较完善的代码,具体实现了:可零配置,动态指定文件名和文件路径,按日期和大小自动分割文件。

代码详情

1. 创建配置文件类

初始化Logger时首先读取配置项中的同名Appender,如果存在使用配置参数,如果不存在则使用默认配置。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestProject.Log4net
{
    public class ReadParamAppender : log4net.Appender.AppenderSkeleton
    {
        private string _file;
        public string File
        {
            get { return this._file; }
            set { _file = value; }
        }

        private int _maxSizeRollBackups;
        public int MaxSizeRollBackups
        {
            get { return this._maxSizeRollBackups; }
            set { _maxSizeRollBackups = value; }
        }

        private bool _appendToFile = true;
        public bool AppendToFile
        {
            get { return this._appendToFile; }
            set { _appendToFile = value; }
        }

        private string _maximumFileSize;
        public string MaximumFileSize
        {
            get { return this._maximumFileSize; }
            set { _maximumFileSize = value; }
        }

        private string _layoutPattern;
        public string LayoutPattern
        {
            get { return this._layoutPattern; }
            set { _layoutPattern = value; }
        }

        private string _datePattern;
        public string DatePattern
        {
            get { return this._datePattern; }
            set { _datePattern = value; }
        }

        private string _level;
        public string Level
        {
            get { return this._level; }
            set { _level = value; }
        }

        protected override void Append(log4net.Core.LoggingEvent loggingEvent)
        {
        }
    }
}

2. 动态创建Logger工厂类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Configuration;

using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository;
using log4net.Repository.Hierarchy;

[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace TestProject.Log4net
{
    public static class CustomRollingFileLogger
    {
        private static readonly ConcurrentDictionary<string, ILog> loggerContainer = new ConcurrentDictionary<string, ILog>();

        private static readonly Dictionary<string, ReadParamAppender> appenderContainer = new Dictionary<string, ReadParamAppender>();
        private static object lockObj = new object();

        //默认配置
        private const int MAX_SIZE_ROLL_BACKUPS = 20;
        private const string LAYOUT_PATTERN = "%d [%t] %-5p %c  - %m%n";
        private const string DATE_PATTERN = "-yyyyMMdd\".txt\"";
        private const string MAXIMUM_FILE_SIZE = "256MB";
        private const string LEVEL = "debug";

        //读取配置文件并缓存
        static CustomRollingFileLogger()
        {
            IAppender[] appenders = LogManager.GetRepository().GetAppenders();
            for (int i = 0; i < appenders.Length; i++)
            {
                if (appenders[i] is ReadParamAppender)
                {
                    ReadParamAppender appender = (ReadParamAppender)appenders[i];
                    if (appender.MaxSizeRollBackups == 0)
                    {
                        appender.MaxSizeRollBackups = MAX_SIZE_ROLL_BACKUPS;
                    }
                    if (appender.Layout != null && appender.Layout is log4net.Layout.PatternLayout)
                    {
                        appender.LayoutPattern = ((log4net.Layout.PatternLayout)appender.Layout).ConversionPattern;
                    }
                    if (string.IsNullOrEmpty(appender.LayoutPattern))
                    {
                        appender.LayoutPattern = LAYOUT_PATTERN;
                    }
                    if (string.IsNullOrEmpty(appender.DatePattern))
                    {
                        appender.DatePattern = DATE_PATTERN;
                    }
                    if (string.IsNullOrEmpty(appender.MaximumFileSize))
                    {
                        appender.MaximumFileSize = MAXIMUM_FILE_SIZE;
                    }
                    if (string.IsNullOrEmpty(appender.Level))
                    {
                        appender.Level = LEVEL;
                    }
                    lock(lockObj)
                    {
                        appenderContainer[appenders[i].Name] = appender;
                    }
                }
            }
        }

        public static ILog GetCustomLogger(string loggerName, string category = null, bool additivity = false)
        {
            return loggerContainer.GetOrAdd(loggerName, delegate(string name)
            {
                RollingFileAppender newAppender = null;
                ReadParamAppender appender = null;
                if (appenderContainer.ContainsKey(loggerName))
                {
                    appender = appenderContainer[loggerName];
                    newAppender = GetNewFileApender(loggerName, string.IsNullOrEmpty(appender.File) ? GetFile(category, loggerName) : appender.File, appender.MaxSizeRollBackups,
                        appender.AppendToFile, true, appender.MaximumFileSize, RollingFileAppender.RollingMode.Composite, appender.DatePattern, appender.LayoutPattern);
                }
                else
                {
                    newAppender = GetNewFileApender(loggerName, GetFile(category, loggerName), MAX_SIZE_ROLL_BACKUPS, true, true, MAXIMUM_FILE_SIZE, RollingFileAppender.RollingMode.Composite, 
                        DATE_PATTERN, LAYOUT_PATTERN);
                }
                log4net.Repository.Hierarchy.Hierarchy repository = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
                Logger logger = repository.LoggerFactory.CreateLogger(repository, loggerName);
                logger.Hierarchy = repository;
                logger.Parent = repository.Root;
                logger.Level = GetLoggerLevel(appender == null ? LEVEL : appender.Level);
                logger.Additivity = additivity;
                logger.AddAppender(newAppender);
                logger.Repository.Configured = true;
                return new LogImpl(logger);
            });
        }

        //如果没有指定文件路径则在运行路径下建立 Log\{loggerName}.txt
        private static string GetFile(string category, string loggerName)
        {
            if (string.IsNullOrEmpty(category))
            {
                return string.Format(@"Log\{0}.txt", loggerName);
            }
            else
            {
                return string.Format(@"Log\{0}\{1}.txt", category, loggerName);
            }
        }

        private static Level GetLoggerLevel(string level)
        {
            if (!string.IsNullOrEmpty(level))
            {
                switch (level.ToLower().Trim())
                {
                    case "debug":
                        return Level.Debug;

                    case "info":
                        return Level.Info;

                    case "warn":
                        return Level.Warn;

                    case "error":
                        return Level.Error;

                    case "fatal":
                        return Level.Fatal;
                }
            }
            return Level.Debug;
        }

        private static RollingFileAppender GetNewFileApender(string appenderName, string file, int maxSizeRollBackups, bool appendToFile = true, bool staticLogFileName = false, string maximumFileSize = "5MB", RollingFileAppender.RollingMode rollingMode = RollingFileAppender.RollingMode.Composite, string datePattern = "yyyyMMdd\".txt\"", string layoutPattern = "%d [%t] %-5p %c  - %m%n")
        {
            RollingFileAppender appender = new RollingFileAppender
            {
                LockingModel = new FileAppender.MinimalLock(),
                Name = appenderName,
                File = file,
                AppendToFile = appendToFile,
                MaxSizeRollBackups = maxSizeRollBackups,
                MaximumFileSize = maximumFileSize,
                StaticLogFileName = staticLogFileName,
                RollingStyle = rollingMode,
                DatePattern = datePattern
            };
            PatternLayout layout = new PatternLayout(layoutPattern);
            appender.Layout = layout;
            layout.ActivateOptions();
            appender.ActivateOptions();
            return appender;
        }
    }
}

使用方法

1. 零配置使用

Log logger = CustomRollingFileLogger.GetCustomLogger("pay", "10001");  
logger.Debug("debug message");  

将在运行目录下生成 Log\10001\pay.txt

按日期分割日志文件,如果文件超过256M,也进行分割。

2. 使用配置文件

修改App.config/Web.config,添加或修改项:

<configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <log4net>
    <appender name="pay" type="Rainstorm.Log4net.ReadParamAppender">
      <param name="file" value="D:\\log\\pay.txt"/> <!--文件路径 -->
      <param name="appendToFile" value="true"/> <!--如果同名文件已存在,是否在文件中追加日志 -->
      <param name="maxSizeRollBackups" value="100"/> <!--在发生文件分割时,最多保留的历史文件个数 -->
      <param name="maximumFileSize" value="2MB"/> <!--设置按文件大小分割的阈值 -->
      <param name="datePattern" value="yyyyMMdd'.txt'"/> <!--按日期分割时文件重命名规则 -->
      <param name="level" value="debug"/> <!--logger输出等级 -->
      <layout type="log4net.Layout.PatternLayout"> <!--日志输出格式 -->
        <conversionPattern value="%d - %m%n"/> <!--文件路径 -->
      </layout>
    </appender>
    <root>
      <level value="INFO"/>
      <appender-ref ref="pay"/>
    </root>
  </log4net>

调用方式:

ILog logger = CustomRollingFileLogger.GetCustomLogger("pay");
logger.Debug("debug message");

相关链接

腾讯云主机 Ubuntu 系统使用 sftp 上传文件

laptop-desk-code.jpg | center | 827x551

概述

经常有操作系统与云服务器间传递文件的需求,通常采用的方式有:搭建ftp服务器、云盘同步工具、winscp、sftp等,其中我比较喜欢winscp 和 sftp 的方式,当然,如果你说两边都装个QQ,同是windows系统的前提下也无可厚非。

今天,介绍的是采用sftp方式与腾讯云Ubuntu系统间同步文件的开启方式。

解决方法

腾讯云主机 Ubuntu 系统默认开通的用户是:ubuntu,
此账户无法使用sftp上传文件。

我们的解决方式是,启用root 账户!

启用前需要修改配置文件

执行命令:

vim /etc/ssh/sshd_config

将下面两个参数修改为 yes

PermitRootLogin yes

PasswordAuthentication yes

修改 root 账户密码

sudo passwd

使用FilleZilla连接云主机

image.png | left | 637x621

更新时间

  • 【2018-5-11 14:52:18】添加背景说明。

相关链接

腾讯云主机 Ubuntu 安装 WordPress

laptop-desk-code.jpg | center | 827x551

概述

Ubuntu 16.04 安装 WordPress 主要分三步:安装 Nginx 并解析域名 ,安装 PHP ,安装 MySQL。在此基础上本文还扩充了添加SSL证书、www跳转到主域名、域名的DNS解析等内容。

安装 Nginx 并解析域名

首先,更新依赖包:

切换到root账户,否则更新包会有如下错误

ubuntu@VM-ubuntu:~$ apt-get update
Reading package lists... Done
W: chmod 0700 of directory /var/lib/apt/lists/partial failed - SetupAPTPartialDirectory (1: Operation not permitted)
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)

切换到 root 账户

sudo su

更新依赖包:

apt-get install update

等待更新完毕!安装 Nginx

apt-get install nginx

安装过程中如果提示(Y/N)的时候,一律输入y

此时,在浏览器中输入IP地址,如果安装成功,则可以看到默认的 Nginx 页面:

image.png | left | 714x313

然后,设置域名的DNS解析

image.png | left | 827x517

解析成功后,在浏览器输入域名可以看到刚才的 Nginx 默认页。

最后,修改 Nginx 配置文件

配置文件路径:/etc/nginx/sites-available/default

......

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files uri uri/ =404;
        }

......

修改36行的 root /var/www/html;root /var/www/myblog;

添加SSL证书

申请免费SSL证书:

地址:https://freessl.org/

申请步骤:

输入要申请证书的域名:

image.png | left | 827x356

按照要求,验证域名所有权:

image.png | left | 827x669

验证完成,下载证书文件。

证书文件

证书文件包含两个:

image.png | left | 243x80

这两个文件的含义是:

文件名 内容
cert.pem 服务端证书
chain.pem 浏览器需要的所有证书但不包括服务端证书,比如根证书和中间证书
full_chain.pem 包括了cert.pem和chain.pem的内容
private.key 证书的私钥

一般情况下full_chain.pemprivate.key就够用了

Nginx 安装SSL 证书

创建ssl证书目录:

cd /etc/nginx
mkdir ssl

在此路径下添加两个文件:

root@VM-ubuntu:/etc/nginx/ssl# vim mydomain.crt
root@VM-ubuntu:/etc/nginx/ssl# vim mydomain.key

mydomain.crt 对应文件 full_chain.pem 中的内容。
__mydomain.key __对应文件 private.key 中的内容。

修改站点配置文件,启用SSL证书

编辑站点配置文件:

root@VM-ubuntu:/etc/nginx/sites-available# vim default 

服务器部分,注释掉80端口监听,开启443端口监听并指定SSL证书路径:

server {
        #listen 80 default_server;
        #listen [::]:80 default_server;

        # SSL configuration
        #
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        ssl on;
        ssl_certificate /etc/nginx/ssl/mydomain.crt;
        ssl_certificate_key /etc/nginx/ssl/mydomain.key;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
........

修改完成后,检查配置文件语法并重启服务器:

root@VM-ubuntu:/etc/nginx/sites-available# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@VM-ubuntu:/etc/nginx/sites-available# service nginx restart

刷新浏览器后,可以查看证书信息:

image.png | left | 768x660

网站安全性检查

检查网站安全性等级:https://www.ssllabs.com

Test your server:

image.png | left | 760x622

SSL A+配置

生成一个 DH group。

sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

再来就是针对 SSL 做一些自定义的设置:(添加 Security enhancements 中的内容)

 # SSL configuration
        #
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        ssl on;
        ssl_certificate /etc/nginx/ssl/rqc.im.crt;
        ssl_certificate_key /etc/nginx/ssl/rqc.im.key;

##### Security enhancements begin

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_ecdh_curve secp384r1;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 1.1.1.1 114.114.114.114 valid=300s;
        resolver_timeout 5s;
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;

##### Security enhancements end

修改完成后,检查配置文件语法并重启服务器:

root@VM-ubuntu:/etc/nginx/sites-available# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@VM-ubuntu:/etc/nginx/sites-available# service nginx restart

重新测试网站SSL等级:

image.png | left | 827x401

http 跳转到 https

默认安装完成之后,如果用户打开 http://mydomain 页面会显示错误,不会自动跳转到https。
解决方式是:多曾加一个 server block,监听 80 端口,返回 301 重定向。

server {

    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mydomain.com www.mydomain.com;
    return 301 https://server_namerequest_uri;

}

设置完成之后,同样检查语法,重启Nginx:

root@VM-ubuntu:/etc/nginx/sites-available# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@VM-ubuntu:/etc/nginx/sites-available# service nginx restart

安装 PHP 7.2

首先添加 PPA

sudo apt-get update

sudo apt-get install software-properties-common
sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php

sudo apt-get update

然后,安装 PHP7.2

sudo apt-get -y install php7.2-fpm php7.2-common php7.2-mbstring php7.2-xmlrpc php7.2-gd php7.2-xml php7.2-mysql php7.2-cli php7.2-zip php7.2-curl

安装完毕之后配置 php-fpm :

vim /etc/php/7.2/fpm/php.ini

//;cgi.fix_pathinfo=1 改为
cgi.fix_pathinfo=0

安装 MySQL 5.7

输入安装命令:

sudo apt-get install mysql-server

期间需要设置mysql密码
查看安装的版本:

mysql --version

检查MySQL的运行状态:

sudo systemctl status mysql

登录Mysql

$ mysql -u root -p
Enter Password:

在 mysql 执行:

CREATE DATABASE myblog DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

CREATE USER 'blogname' IDENTIFIED BY 'blogpwd';

GRANT ALL PRIVILEGES ON myblog.* TO 'blogname';

FLUSH PRIVILEGES;
EXIT;

MySQL 常用命令(了解)

停止MySQL服务:

sudo systemctl stop mysql

MySQL的启动命令:

sudo systemctl start mysql

MySQL重启命令:

sudo systemctl restart mysql

设置MySQl安全服务(了解)

命令行环境执行:

mysql_secure_installation

设置步骤:
1. 第一步是启用密码验证插件 Y
2. 验证级别:2
3. 用户当前的密码强度是50,可以选择修改密码,此处可以选择忽略。
4. 移除匿名用户:y
5. root账户只允许本地登录:y
6. 移除默认的test数据库:y
7. 重新加载权限表

重新配置 Nginx

vim /etc/nginx/sites-available/default

打开配置文件,配置:

server {
    listen 80;
    listen [::]:80;
    root /var/www/wordpress;

    index index.php index.html index.htm index.nginx-debian.html;
    # 注意我们添加了 index.php
    server_name  example.com www.example.com;

    client_max_body_size 100M;

    location / {
        try_files uri uri/ /index.php?args;             }      location ~ \.php {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
         fastcgi_param SCRIPT_FILENAME document_rootfastcgi_script_name;
         include fastcgi_params;
    }
}

安装 WordPress

下载 WordPress 安装包解压后上传到网站目录(此处可参考我的另一篇文章《腾讯云主机 Ubuntu 系统使用 sftp 上传文件》)。

可以在浏览器中一步步按照指示安装。

也可以复制 wp-config-sample.php 修改名称为 wp-config.php

打开 wp-config.php 文件:

配置数据库连接字符串:

// ** MySQL 设置 - 具体信息来自您正在使用的主机 ** //
/** WordPress数据库的名称 */
define('DB_NAME', '数据库名称');

/** MySQL数据库用户名 */
define('DB_USER', '登录用户');

/** MySQL数据库密码 */
define('DB_PASSWORD', '登录密码');

/** MySQL主机 */
define('DB_HOST', 'localhost');

/** 创建数据表时默认的文字编码 */
define('DB_CHARSET', 'utf8');

/** 数据库整理类型。如不确定请勿更改 */
define('DB_COLLATE', '');

另外添加如下配置:

/* 配置 WordPress 文件上传 */
define('FS_METHOD', 'direct');
define('FS_CHMOD_DIR', 0777);
define('FS_CHMOD_FILE', 0777);

设置完成,打开浏览器。

相关链接

做自己专业的事

做不专业的事

昨天花了一天的事件折腾笔记本,Windows系统用久了有些卡。之前浏览资讯网站了解到Windows 10 创意者更新专业版序列号可以通过Window 7 旗舰版免费升级得到。于是,从早上开始折腾笔记本安装Windows 7。但是,由于笔记本较新默认通过UEFI方式启动,传统的安装方式死活不成功。从早上上班折腾到快下班也没能获得免费的序列号,一天的高度专注也搞得身心俱疲。

不得已,放弃了这种方式。而后,在浏览论坛的过程中,偶然看到淘宝购买的字眼。于是,去淘宝搜索了一下,映入眼帘的是一批5元、8元、10元获取正版激活码的宝贝。看描述,猜测他们获取的方式也是通过升级系统而来。抱着试一下的态度买了一个9元的。结果不出所料,轻轻松松激活成功。前后花费时间不到2分钟!

一天时间的成果不及9元的价值,想想都有些可惜。可惜的背后是对这种现状的思索,思索为什么不去找专业的人去做这种事呢?为什么看到问题第一个想法是去找解决方案,而没有一丝一毫的意识去找能解决的人呢?

做专业的事

前天看完逻辑思维的一本书,其中有一章特别提到生物圈的演化历程及人力的未来。作者反复论证未来的发展趋势是分工,而且是更加细致的分工,越细致的分工会越高效的利用资源,分工是高效的前提。回归到今天发生的事上就是应该做自己专业的事,把他人专业是事交给他人,不在这上面浪费时间才能在自身专业上更加深入发挥所长。

Ubuntu 使用 Fish Shell

1. Fish shell安装启动

1.1 Ubuntu 安装 Fish Shell

命令行运行代码:sudo apt-get install fish

1.2 启动fish

命令行输入代码:fish进入Fish Shell环境,退出使用代码:exit

Fish Shell环境如下图:
image.png-10kB

2. Fish shell的特色功能

2.1 命令提示功能:

灰色的部分是提示内容:

image.png-9.5kB

命令和参数都能智能提示:命令未输完前按下Tab键智能提示,并列出可选的命令:

image.png-16.1kB

2.2 自动检查命令是否正确

红色命令错误,蓝色命令正确:

错误命令:

image.png-4.6kB

正确命令:

image.png-4.5kB

2.3 路径有效显示下划线,无效显示红色

有效命令,显示下划线:

image.png-5.3kB

无效命令依然显示红色:

image.png-4.7kB

3. 常用快捷键

  1. 命令补全:→ 或者 Ctrl+F

4. 参考文章:

  1. Fish shell 入门教程

MySQL 解压版安装(Windows Server 2016 x64)

1. 本文说明

本文主要讲述 MySQL解压版在 Windows Server2016 x64 服务器上的安装过程,用于记录自己在安装MySQL过程中遇到的坑和基本 的使用方法。理论上这些内筒也适用于Windows10和Window7用户。

2. 软件下载

这里,下载MySQL最新社区版。我下载的版本是:mysql-5.7.18-winx64.zip

软件下载

继续阅读“MySQL 解压版安装(Windows Server 2016 x64)”

Hexo博客的搭建流程

这是之前使用Hexo搭建静态博客的教程。目前已经重新回到Wordpress平台,主要原因还是定制行强、耐玩。

本文从六个方面描述Hexo搭建博客的完整流程:

1. 安装Node.js

下载链接:http://nodejs.org/

2. 安装hexo

执行命令:npm install -g hexo

因为特殊的网络环境,安装的速度非常慢,而且极大的可能会失败。

解决办法:修改npm的安装源。

下面提供两种修改方式:

方式一,通过config命令:(亲自尝试,推荐使用)

命令行执行:

npm config set registry http://registry.cnpmjs.org
npm info underscore

方式二,通过命令:(未做尝试,不推荐)

npm -registry http://registry.cnpmjs.org info underscore

最后,重新执行命令:npm install -g hexo 直到安装成功。

3. 生成Hexo静态博客

  1. 选择博客文件的存放位置(以下以 C:\BlogFiles为例)
    • 进入C盘:cd C:
    • 创建文件夹BlogFiles:mkdir BlogFiles
    • 进入文件夹BlogFiles:cd BlogFiles
  2. 初始化博客
    • hexo init
      • 命令执行完成,在BlogFiles文件夹下添加以下内容:
        • node_modules: Hexo需要的nodejs组件
        • scaffolds:工具模板
        • source
          • _posts 文章文件夹
        • themes:主题文件
        • _config.yml:全局配置文件
  3. 生成静态页面并运行
    • 生成静态页面
      • 运行:hexo g (或者hexo generate)生成的静态内容存放在 public 文件夹下,此文件夹包含所有需要发布的内容
    • 运行查看效果
      • 运行:hexo s (或者 hexo server )在浏览器地址栏输入:http://localhost:4000 查看网站效果

4. 修改主题效果(个人风格爱好,我使用的是 NexT)

  1. 下载最新版本:https://github.com/iissnan/hexo-theme-next/releases
  2. 修改解压的文件,并把文件夹重命名为:next,放在themes文件夹下
  3. 修改主题配置文件:next/_config.yml
    • scheme: Mist
  4. 修改站点语言为:简体中文,在/_config.yml 文件里修改:language:zh-Hans
  5. 修改默认主题:为next,在/_config.yml 文件里修改:theme: next
  6. 设置菜单:在 next/_config.xml 中设置 menu: 菜单项,取消相应注释
  7. 添加RSS输出
    • 参考:http://hanhailong.com/2015/10/08/Hexo%E2%80%94%E6%AD%A3%E7%A1%AE%E6%B7%BB%E5%8A%A0RSS%E8%AE%A2%E9%98%85/
    1. 安装插件:hexo-generator-feed 命令:$ npm install hexo-generator-feed --save
    2. 修改站点配置文件_config.yml ,添加以下内容:
# Extensions
## Plugins: http://hexo.io/plugins/
#RSS订阅
plugin:
- hexo-generator-feed
#Feed Atom
feed:
type: atom
path: atom.xml
limit: 20
3. 修改主题配置文件 next/_config.yml 的rss字段值:rss: "/atom.xml"

5. 高频使用命令:

  • 清理Hexo的缓存,删除Public文件夹:$ hexo clean
  • 生成静态文件:$ hexo g

  • 启动测试模式:$ hexo s (模式端口号是:4000)

如果启动失败,请指定启动端口号:$ hexo s -p 3600 (使用3600端口)

6. 注意事项:

配置文件应严格遵守格式规范,我遇到过设置项前多一个或少一个空格报错的情况。不过,让人欣慰的是查看报错的详细信息,基本都可以定位到错误的位置。

走到人生的另一个阶段

还有一周就春节了,深圳这边处处透露着独有的过年气息。之前拥挤的车道、挤挤攘攘的人群和嘈杂喧闹的街市一夜之间,销声匿迹。让我们这种不是迫切渴望回家的人,心情也变得急迫起来。

想想我的车票还在下周,不得不重新淡定一下,安心投入到工作中去。掐指一算,这份工作最多还有半个多月,在这最后一段时间里,我能做的最好的就是别给后人留坑。

从去年的四月份到现在不到一年的时间,和上份工作相比短了许多,不过却比上份工作学到了多得多的东西,同时也比上面工作,遭受到了多得多的摧残。回想一下,从2013年7月份开始毕业后的第一份工作,到去年4月份离职,两年半的时间,那是很幸福的两年半。虽然所做的工作和我所学的工业工程专业完全不搭边,但是大公司背景和完善的体制。让我这种神经大条的人,工作起来也很轻松。后来准备离职的时候,我挺害怕的,因为我很清楚,我可能再也找不到这种公司。后来在换新公司的过程中,也验证了我的这个判断。在进入现在这家小公司的时候,一些东西真的不是很满意,除了能拿到上家翻倍的薪资。但是这个的代价却相当大,从做制造管理转行去做软件实施顾问,完全从零开始,开始的三个月里每天都是早上六点多坐一个小时的公交去客户那里,到晚上八点多再坐地铁回来,中午吃饭最多十分钟。每天脑海里的唯一念头都是搞好这个,明天申请离职。和前一份工作去富士康实习期间的念头一模一样。当然,那时候大部分人确实走了。三个月下来,几乎掌握了所有东西,连客户项目经理都给老板打电话说我表现很好。自然而然,刚转正就拿到了,绩效第一A+。接下来的日子就幸福了很多,但同时也意识到了可以试着往更深的层次发展。于是又作死地找了另一个行业,从顾问换到开发。可以想象的到前期又将是极度痛苦不堪的过程。

其实我很认同,前份工作离职前经理给我讲的一句话: 任何工作,最开始的半年是最难的。坚持下去就好了。而我将按照他这句话,步入生的另一个阶段。