leadscloud

Google SEO|外贸营销推广

CSS 有哪些样式可以给子元素继承!

可继承的:font-size,font-weight,line-height,color,cursor
不可继承的一般是会改变盒子模型的:display,marginborderpaddingheight

box-sizing常用的属性有哪些? 分别有啥作用?

box-sizing有两个值:content-box(W3C标准盒模型),border-box(怪异模型),
这个css 主要是改变盒子模型大小的计算形式
可能有人会问padding-box,这个之前只有 Firefox 标准实现了,目前50+的版本已经废除;
用一个栗子来距离,一个div的宽高分别100px,border为5px,padding为5px

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <style>
.test {
box-sizing: content-box;
border: 5px solid #f00;
padding:5px;
width: 100px;
height: 100px;
}

</style>
<div class="test"></div>
<!--
content-box的计算公式会把宽高的定义指向 content,border和 padding 另外计算,
也就是说 content + padding + border = 120px(盒子实际大小)

而border-box的计算公式是总的大小涵盖这三者, content 会缩小,来让给另外两者
content(80px) + padding(5*2px) + border(5*2px) = 100px
-->

清除浮动的方式有哪些?比较好的是哪一种?

常用的一般为三种.clearfix, clear:both,overflow:hidden;

CSS 中transition和animate有何区别? animate 如何停留在最后一帧!

这种问题见仁见智,我的回答大体是这样的..待我捋捋.
transition一般用来做过渡的,而animate则是做动效,算是前者的一个补充拓展;
过渡的开销比动效小,前者一般用于交互居多,后者用于活动页居多;
至于如何让animate停留在最后一帧也好办,就它自身参数的一个值就可以了

1
2
animation-fill-mode: forwards;  
<!--backwards则停留在首帧,both是轮流-->

让我们来举个栗子….自己新建一个 html 跑一下….

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Box-sizing</title>
<style>
.test {
box-sizing: border-box;
border: 5px solid #f00;
padding: 5px;
width: 100px;
height: 100px;
position:absolute;
/*
简写的姿势排序
@keyframes name : 动画名
duration 持续时间
timing-function 动画频率
delay 延迟多久开始
iteration-count 循环次数
direction 动画方式,往返还是正向
fill-mode 一般用来处理停留在某一帧
play-state running 开始,paused 暂停 ....
更多的参数去查文档吧..我就不一一列举了
*/
animation: moveChangeColor ease-in 2.5s 1 forwards running;
}

@keyframes moveChangeColor {
from {
top:0%;
left:5%;
background-color:#f00
}
to{
top:0%;
left:50%;
background-color:#ced;
}
}

</style>
</head>

<body>
<div class="test"></div>
</body>

</html>

块级元素水平垂直居中的方法

我们要考虑两种情况,定宽高和不定宽高的;

方案 N 多种,我记得我很早写过这类的笔记

网页元素居中攻略记

CSS样式权重的优先级

    !important > 行内样式 > id > class > tag

CSS特异性

JS有几种数据类型,其中哪些的基本数据类型有哪些!

七种数据类型

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6 新定义)
  • Object

其中5种为基本类型: string,number,boolean,null,undefined

Object 为引用类型(范围挺大),也包括数组、函数,

Symbol是原始数据类型 ,表示独一无二的值

nullundefined的差异

相同点

在 if判断语句中,值都默认为 false
大体上两者都是代表无,具体看差异

不同点

  • null转为数字类型值为0,而undefined转为数字类型为 NaN(Not a Number)
  • undefined是代表调用一个值而该值却没有赋值,这时候默认则为undefined
  • null是一个很特殊的对象,最为常见的一个用法就是作为参数传入(说明该参数不是对象)
  • 设置为null的变量或者对象会被内存收集器回收

this对象的理解

简言之: 谁调用指向谁, 运行时的上下文确定, 而非定义的时候就确定;

强行绑定 this的话,可以用 call,apply,bind,箭头函数….来修改this的指向

bind的 js简单模拟

1
2
3
4
5
6
7
Function.prototype.emulateBind =  function (context) {
var self = this;
return function () {
return self.apply(context);
}

}
阅读全文 »

微信开发的时候,必须要输入URL而且必须是外网域名,导致本地没法调试,不过使用ngrok可以创建一个内网穿透的服务器,这样就可以使用本地的服务器调试了。

ngrock下载地址

开启 ssh 端口

./ngrok tcp 22

这时在外网即可 ssh 访问本机:

ssh user@0.tcp.ngrok.io -p17840

开启 http(s) 服务:

./ngrok http 80

免费版并不能自定义域名,每次启动时的端口都会改变

CentOS6 搭建自己的 ngrok 服务

https://www.ngrok.cc/
https://natapp.cn/

回想2007年,那时候我刚加入Mozilla’s JavaScript团队,那时候的一个典型的JavaScript程序只需要一行代码,听起来像个笑话。

两年后,Google Maps发布。在这之前,JavaScript主要用来做表单的验证,你用来处理<input onchange=>这个程序当然只需要一行。

时过境迁,JavaScript项目已经发展到让人叹为观止,社区涌现了许多帮助开发的工具。但是最迫切需要的是一个模块系统,它能将你的工作分散到不同的文件与目录中,在需要的时候他们能彼此之间相互访问,并且可以有效的加载所有代码。所以JavaScript有模块系统这很正常,而且还有多个模块系统(CommonJS、AMD、CMD、UMD)。不仅如此,它还有几个包管理器(npm、bower),用来安装软件还能拷贝一些深度依赖。你可能认为ES6和它的新模块系统出现得有点晚。

那我们来看看ES6为现存的模块系统添加了什么,以及未来的标准和工具能否建立在这个系统上。首先,让我们看看ES6的模块是什么样子的。

模块的基础知识

ES6模块是一个包含了JS代码的文件。没有所谓的module关键词,一个模块看起来和一个脚本文件没什么不一样,除了一下两个区别:

  • ES6的模块自动开启严格模式,即使你没有写"use strict";
  • 在模块中,你可以使用importexprot

先来谈谈export。在默认情况下,模块中所有的声明都是私有的,如果你希望模块中的某些声明是公开的,并在其他模块中使用它们,你就必须导出它们。这里有一些实现方法,最简单的是添加export关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// kittydar.js - Find the locations of all the cats in an image.
// (Heather Arthur wrote this library for real)
// (but she didn't use modules, because it was 2013)

export function detectCats(canvas, options) {
var kittydar = new Kittydar(options);
return kittydar.detectCats(canvas);
}

export class Kittydar {
... several methods doing image processing ...
}

// This helper function isn't exported.
function resizeCanvas() {
...
}
...

你可以export任何的顶级变量:functionclassvarletconst

你如果要写一个模块知道这么多就够了!你不必再把所有的东西放到一个立即执行函数或者回调函数里面,只需要在你需要的地方进行声明。由于这个代码是一个模块,而不是一个脚本,所有的声明的作用域都只属于这个模块,而不是所有脚本和模块都能全局访问的。你只要把模块中的声明导出成一组公共模块的API就足够了。

除了导出,模块里的代码和其他普通代码没有什么区别。它可以访问全局变量,像ObjectArray。如果你的模块在浏览器运行,还能够使用documentXMLHttpRequest

在另一个文件中,我们可以导入并使用detectCats()函数:

1
2
3
4
5
6
7
8
9
// demo.js - Kittydar demo program

import {detectCats} from "kittydar.js";

function go() {
var canvas = document.getElementById("catpix");
var cats = detectCats(canvas);
drawRectangles(canvas, cats);
}

要从一个模块导入多个变量,你可以这样写:

1
import {detectCats, Kittydar} from "kittydar.js";

当你运行一个包含import声明的模块,会先导入要导入的模块并加载,然后根据深度优先的原则遍历依赖图谱来执行对应模块,并跳过已经执行的模块,来避免循环。

这就是模块基础知识,这真的很简单。;-)

导出列表

你可以把你要导出的功能名写在一个列表里,然后用大括号括起来,这样就不用在每个要导出的功能前面加上export标记。

1
2
3
4
5
export {detectCats, Kittydar};

// no `export` keyword required here
function detectCats(canvas, options) { ... }
class Kittydar { ... }

导出列表并不需要写在文件的第一行,它可以出现在模块文件的顶级作用域的任何位置。你可以有多个导出列表,或者将导出列表与导出声明混合使用,只要不重复导出同一个变量名就行。

重命名导出和导入

有时,导入的变量名碰巧与你需要使用的一些变量名冲突了,ES6允许你重命名导入的变量。

1
2
3
4
5
6
7
// suburbia.js

// Both these modules export something named `flip`.
// To import them both, we must rename at least one.
import {flip as flipOmelet} from "eggs.js";
import {flip as flipHouse} from "real-estate.js";
...

同样,你在导出变量的时候也可以重命名它们。这在你想使用不同名字导出相同功能的时候十分方便。

1
2
3
4
5
6
7
8
9
10
11
// unlicensed_nuclear_accelerator.js - media streaming without drm
// (not a real library, but maybe it should be)

function v1() { ... }
function v2() { ... }

export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};

默认的导出

新的标准在设计上是兼容已经存在的CommonJS和AMD模块的。如果你有一个Node项目,并且你已经执行了npm install lodash。你使用ES6代码能够单独引入Lodash中的函数:

1
2
3
import {each, map} from "lodash";

each([3, 2, 1], x => console.log(x));

如果你已经习惯使用_.each而不是each,你依然想像以前一样使用它。或者, 你想把_当成一个函数来使用,因为这才是Lodash。

这种情况下,你只要稍微改变下你的写法:不使用花括号来导入模块。

1
import _ from "lodash";

这个写法等同于import {default as _} from "lodash";。所有的CommonJS 和AMD模块在ES6中都能被当作default导出,这个导出和你在CommonJS中使用require()导出得到东西一样,即exports对象。

ES6模块在设计上可以让你导出更多的东西,但对于现在的CommonJS模块,导出的default模块就是能导出的全部东西了。例如,在写这篇文章时,据我所知,著名的colors模块没有特意去支持ES6语法,这是一个CommonJS模块组成的包,就像npm上的那些包一样,但是你可以直接引入到你的ES6代码中。

1
2
// ES6 equivalent of `var colors = require("colors/safe");`
import colors from "colors/safe";

如果你希望自己ES6模块也具有默认导出,这很简单。默认的导出方式并没有什么魔力;他就像其他导出一样,除了它的导出名为default。你可以使用我们之前提到的重命名语法:

1
2
3
4
5
let myObject = {
field1: value1,
field2: value2
};
export {myObject as default};

或者使用简写:

1
2
3
4
export default {
field1: value1,
field2: value2
};

export default关键词后面可以跟任何值:一个函数、一个类、一个对象,所有能被命名的变量。

模块对象

不好意思,这篇文章有点长。JavaScript并不孤独:因为一些原因,所有的语言中都有模块系统,并且倾向于设计大量杂乱而又无聊的小特性。幸运的是我们只剩下一个话题,噢,不对,是两个。

1
import * as cows from "cows";

当你使用import *的时候,被引入的是一个模块命名空间对象(module namespace object),它的属性是模块的输出。如果“cows”模块导出一个名为moo()的函数,那么在导入“cows”之后,你可以使用cows.moo()来进行调用。

聚合模块

有时候一个包的主模块只不过是导入包其他所有的模块,并用统一的方式导出。为了简化这种代码,有一种将导入导出全部合一的简写:

1
2
3
4
5
6
7
8
9
10
// world-foods.js - good stuff from all over

// import "sri-lanka" and re-export some of its exports
export {Tea, Cinnamon} from "sri-lanka";

// import "equatorial-guinea" and re-export some of its exports
export {Coffee, Cocoa} from "equatorial-guinea";

// import "singapore" and export ALL of its exports
export * from "singapore";

这种export-from表达式类似于import-from后面跟了一个export。这和真正的导入有一些区别,它不会在当前作用域中绑定将要导出的变量。如果你打算在world-foods.js中使用Tea来编写一些代码,请不要使用这种简写,你会发现Tea为定义。

如果“singapore”导出的命名与其他导出发生了冲突,那就会出现错误,所以请谨慎使用。

呼,我们已经把语法介绍完了!下面来谈谈一些有趣的事情。

import到底做了什么?

不管你信不信,它什么都没做。

噢,你看起来没那么好骗。那么你会相信标准几乎没有说import到底该怎么做吗?这是件好事吗?(作者貌似很爱开玩笑。)

ES6将模块的加载细节完全交给了实现,其余的模块执行部分却规定得非常详细

简单来说,当你告诉JS引擎运行一个模块的时候,它的行为可以归纳为以下四部:

  1. 解析:读取模块的源代码,并检查语法错误。
  2. 加载:加载所有的导入模块(递归进行),这是还未标准化的部分。
  3. 链接:对于每个新加载的模块,在实现上都会创建一个作用域,并把模块中声明的所有变量都绑定在这个作用域上,包括从其他模块导入的变量。如果你想试试import {cake} from "paleo",但是“paleo”模块没真正导出名为cake的变量,你会得到一个错误。这很糟糕,因为你离运行js并品尝蛋糕只有一步之遥。
  4. 运行时间:最后,开始执行加载进来的新的模块中的代码。这时,整个import过程已经完成了,所以前面说代码执行到import这一行声明时,什么都没有发生。

看到没?我说了什么都不会发生,在编程语言这件事上,我从来都不说慌。

现在我们可以开始介绍这个系统中有趣的部分了。这有一个非常炫酷的技巧。由于系统没有指定如何加载的这方面的细节,并且你可以通过查看源代码中导入的声明,提前计算出所有的依赖项,所以ES6的实现可以通过预处理器完成所有的工作,然后把所有的模块打包到一个文件中,最后通过网络进行请求一次即可。像webpack这样的工具就是这么做的。

这是一个优雅的解决方案,因为通过网络加载所有的脚本文件很耗时,假如你请求一个资源后,发现里面有import声明,然后你又得请求更多资源。一个加载器需要非常多的网络请求来回传输。通过webpack,你不仅能在今天就使用ES6的模块话,你还能获得很多好处,并且不需要担心会造成运行时的性能下降。

原本是有计划制定一个ES6中模块加载的详细规范的,并且已经初步成型。它没有成为标准的原因之一是不知道如何与打包这一特性进行整合。我希望模块化的加载会更加标准化,也希望打包工具会越来越好。

静态 VS 动态,或者说:规则如何打破规则

作为一个动态编译语言,令人惊奇的是JavaScript拥有一个静态的模块系统。

  • 所有的importexport只能写在顶级作用域中。你不能在条件判断语句和函数作用域内使用import。
  • 所有导出的变量名必须是显式的,你不能通过遍历一个数组,动态生成一组导出名进行导出。
  • 模块对象都是被冻结的,不能通过polyfill为它添加新的特性。
  • 在所有模块运行之前, 其依赖的模块都必须经过加载、解析、链接的过程,目前没有import懒加载相关的语法。(现在import()方法已经在提案中了)
  • 对于import的错误,无法进行recovery。一个应用可能依赖许多的模块,一旦有一个模块加载失败,这个应用都不会运行。你不能在try/catch中使用import。正是因为es6的模块表现得如此静态,webpack才能在编译的时候检测出代码中的错误。
  • 你没法为一个模块在加载所有依赖项之前添加钩子,这意味着一个模块没有办法控制其依赖项的加载方式。

如果你的需求是静态的,ES6的模块系统还是相当不错的。但是你有时候你还是向进行一些hack,对吧?

这就是为什么你使用的模块加载系统会提供一些系统层次的API来配合ES6的静态的import/export语法。例如,webpack有一个API能进行代码的分割,按照你的需求对一些模块进行懒加载。这个API能够打破之前列出的规矩。

ES6的模块语法非常静态,这很好-在使用一些编译工具时我们都能尝到一些甜头。静态语法的设计可以让它与动态加载器丰富的API进行工作。

我什么时候才能使用ES6模块?

如果你今天就想使用,你需要一个预编译器,如 TraceurBabel 。这个系列之前也有相关文章,Gastón I. Silva:如何使用 Babel 和 Broccoli 编译 ES6 代码为 web 可用。Gastón也将案例放在了 GitHub 上。另外这篇文章也介绍了如何使用 Babel 和 webpack。

ES6 模块系统由 Dave Herman 和 Sam Tobin-Hochstadt进行设计,他们不顾多人(包括我)的反对,多年来始终坚持模块系统是静态的。JonCoppeard正在Firefox上实现ES6的模块化功能。JavaScript Loader的相关标准的工作也正在进行中,预计在HTML中将会被添加类似<script type=module> 这样的东西。

这便是 ES6 了。

这太有趣了,我不希望现在就结束。也许我们还能再说一会。我们还能够讨论一些关于ES6规范中零零碎碎的东西,但这些又不足够写成文章。也行会有一些关于ES6未来特性的一些东西,尽请期待下周的ES6 In Depth

原文链接:ES6 In Depth: Modules

关于Memcached系统

Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果。Memcached简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的很多问题。它的API兼容大部分流行的开发语言。本质上,它是一个简洁的key-value存储系统。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

关于分布式DDoS原理

分布式拒绝服务(DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的威力。通常,攻击者使用一个偷窃帐号将DDoS主控程序安装在一个计算机上,在一个设定的时间主控程序将与大量代理程序通讯,代理程序已经被安装在网络上的许多计算机上。代理程序收到指令时就发动攻击。利用客户/服务器技术,主控程序能在几秒钟内激活成百上千次代理程序的运行。

关于反射式DRDoS原理

DRDoS是英文“Distributed Reflection Denial of Service ”的缩写,中文意思是“分布式反射拒绝服务”。与DoS、DDoS不同,该方式靠的是发送大量带有被害者IP地址的数据包给攻击主机,然后攻击主机对IP地址源做出大量回应,形成拒绝服务攻击。

LNMP修复办法

以下是lnmp一键安装脚本的修复方法

根据阿里的建议:

如果您的Memcached版本低于1.5.6,且不需要监听UDP。您可以重新启动Memcached 加入 -U 0启动参数,例如:Memcached -U 0,禁止监听在udp协议上

vi /etc/init.d/memcached

1
2
3
4
5
6
7
8
start () {
echo -n $"Starting $prog: "
memcached -d -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -P /var/run/memcached.pid $OPTIONS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/memcached
}

改为(启动项添加 -U 0)

1
2
3
4
5
6
7
start () {
echo -n $"Starting $prog: "
memcached -d -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -U 0 -P /var/run/memcached.pid $OPTIONS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/memcached
}

参考资料

基于Memcached分布式系统DRDoS拒绝服务攻击技术研究
https://paper.seebug.org/535/

绝对路径

当Hexo项目中只用到少量图片时,可以将图片统一放在source/images文件夹中,通过markdown语法访问它们。

source/images/image.jpg

1
![](/images/image.jpg)

图片既可以在首页内容中访问到,也可以在文章正文中访问到。

相对路径

图片除了可以放在统一的images文件夹中,还可以放在文章自己的目录中。文章的目录可以通过配置_config.yml来生成。

_config.yml

1
post_asset_folder: true

_config.yml文件中的配置项post_asset_folder设为true后,执行命令$ hexo new post_name,在source/_posts中会生成文章post_name.md和同名文件夹post_name。将图片资源放在post_name中,文章就可以使用相对路径引用图片资源了。

_posts/post_name/image.jpg

1
![](image.jpg)

上述是markdown的引用方式,图片只能在文章中显示,但无法在首页中正常显示。

如果希望图片在文章和首页中同时显示,可以使用标签插件语法。

_posts/post_name/image.jpg

1
{% asset_img image.jpg This is an image %}

Github上面的一个项目 Nginx Module for Google ,可以实现快捷部署Google镜像。

重新编绎Nginx

1
2
3
4
5
[root@AY1407181147267575e9Z ~]# nginx -V
nginx version: nginx/1.6.0
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-ipv6

我使用的是lnmp.org的一键安装包,其它情形查看 https://github.com/cuber/ngx_http_google_filter_module ,上面有详细的说明。

1
2
3
4
5
6
7
8
9
10
11
12
git clone https://github.com/cuber/ngx_http_google_filter_module
git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module
cd nginx-1.6.0/
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module \
--with-http_ssl_module --with-http_gzip_static_module --with-ipv6 \
--add-module=../ngx_http_google_filter_module \
--add-module=../ngx_http_substitutions_filter_module

make && make install
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
nginx -t
service nginx restart

虚拟主机配置

vi /usr/local/nginx/conf/vhost/demo.website.com.conf, 保持内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# https的可以使用lnmp的脚本配置,在添加虚拟主机的时候有提示是否使用ssl
server {
listen 443 ssl http2;
server_name demo.website.com;
ssl_certificate /usr/local/nginx/conf/ssl/demo.website.com.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/demo.website.com.key;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers CHACHA20:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!DSS:!PKS;
ssl_session_cache builtin:1000 shared:SSL:10m;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
location / {
google on;
google_scholar on; # google_scholar 依赖于 google, 所以 google_scholar 无法独立使用。由于谷歌学术近日升级, 强制使用 https 协议, 并且 ncr 已经支持, 所以不再需要指定谷歌学术的 tld
google_language en; # 语言偏好,默认使用 zh-CN (中文)
}
}
server {
listen 80;
server_name demo.website.com;
rewrite ^(.*)$ https://$host$1 permanent; # 访问http跳转至https
}

保存配置文件,重启nginx即可。

参考资料

Nginx Module for Google

昨天把个人博客迁移到github pages上面了,今天把博客主题重新整理了下。

这个博客从10年到今年,有8年时间了,最近一年因为域名过期,一直也没有整理它,今天把它弄好了,过几天再把之前的域名申请好,然后就可以上线了,未来准备换个域名,时间久了,人也变化很多,等这个域名的权重转移好之后,就可以更换了。

此博客重新上线,放到了github.com上面一份,VPS上面一份,使用了travis自动发布,由于国内域名需要备案,要在国内畅通打开还需要一段时间。

博客涉及到诸多技术问题,有想了解的,可以到我的github页面去查看源码,不是特别难,但第一次部署比较麻烦。

博客添加RSS功能

安装RSS插件

npm install hexo-generator-feed --save

开启网站 RSS 支持

编辑网站根目录下的 _config.yml,添加以下代码开启

1
2
3
4
5
6
7
8
9
# RSS订阅支持
plugin:
- hexo-generator-feed

# Feed Atom
feed:
type: atom
path: atom.xml
limit: 20

主题开启 RSS 支持

主题不同开启方法不同,我的是 NexT 主题,默认就可以;其他主题请参考主题说明。

生成 RSS

执行 hexo clean && hexo g重新生成博客文件完成部署即可。 转载请注明出处,本文采用 CC4.0 协议授权

头像生成地址

https://faceyourmanga.com

参考资料

https://reuixiy.github.io/technology/computer/computer-aided-art/2017/06/09/hexo-next-optimization.html
https://github.com/willin/hexo-wordcount
体验GitHub Issues的评论系统——Gitment
https://github.com/iissnan/hexo-theme-next
http://saili.science/2017/04/02/github-for-win/

使用 TRAVIS 自动部署 HEXO 到 GITHUB 与 自己的服务器

前期准备

请尽可能用比较新的 RubyGems 版本,建议 2.6.x 以上。

1
2
3
$ gem update --system # 这里请翻墙一下
$ gem -v
2.6.3

使用国内镜像

1
2
3
4
$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
https://gems.ruby-china.org
# 确保只有 gems.ruby-china.org

参考: https://gems.ruby-china.org/

安装travis

sudo gem install travis

配置github

我的github之前已经配置好GitHub Pages,现在需要变成下面这样,之前只有master一个分支。

  • master 存放 Hexo 生成好的静态文件,所有 commit 信息格式均为 Site updated: %Y-%m-%d %H:%M:%S
  • source 存放 scaffolds(脚手架)、source(文章 Markdown 源码)、_config.yml(Hexo 配置)等文件,并设置为 repo 的默认分支。

配置 Travis CI

  • 使用github帐号登录Travis,右上方按钮点击同步项目,下方打开需要集成的项目,最后点击齿轮进入项目配置页面
  • 打开Build only if .travis.yml is present

参考这篇文章 https://segmentfault.com/a/1190000009054888

通过命令行登录 Travis 并加密文件:

在hexo blog项目根目录下创建一个文件 .travis.yml

1
2
3
4
5
cd 博客根目录
touch .travis.yml

#创建一个文件夹.travis
mkdir .travis

生成一个 ssh 密钥对(不要嫌麻烦直接把你机器上的秘钥拿去用了,太危险):

1
2
3
4
cd 博客根目录
cd .travis/
# 会生成traivs.key 和travis.key.pub
$ ssh-keygen -f travis.key

然后把生成的公钥文件(e.g. travis.key.pub)分别添加到 GitHub Deploy Keys、VPS 上的 ~/.ssh/authorized_keys 中,这样 Travis CI 的机器就可以直接访问这些服务器了。

1
2
3
4
5
6
7
8
cd 博客根目录
cd .travis/
# 交互式操作,使用 GitHub 账号密码登录
# 如果是私有项目要加个 --pro 参数
$ travis login --auto
# 加密完成后会在当前目录下生成一个 travis.key.enc 文件
# 还会在你的 .travis.yml 文件里自动加上用于解密的 shell 语句
$ travis encrypt-file travis.key -add

以上步骤完成后你会得到一个 travis.key.enc

编辑 .travis.yml

1
2
cd 博客根目录
vi .travis.yml

这是我的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
language: node_js
node_js: stable

# 只监听 source 分支的改动
branches:
only:
- source

# 缓存依赖,节省持续集成时间
cache:
yarn: true
directories:
- node_modules
# - themes

before_install:
# 解密 RSA 私钥并设置为本机 ssh 私钥
- openssl aes-256-cbc -K $encrypted_9aab6d74e2ca_key -iv $encrypted_9aab6d74e2ca_iv
-in .travis/travis.key.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
# 修改本机 ssh 配置,防止秘钥认证过程影响自动部署
#- mv -fv .travis/ssh-config ~/.ssh/config #这一步不需要,如果添加了ssh_know_hosts
- git config --global user.name "leadscloud"
- git config --global user.email "sbmzhcn@gmail.com"
# 赋予自动部署脚本可执行权限
- chmod +x .travis/deploy.sh

install:
# 安装 Hexo 及其依赖
- yarn
# 当 Travis 文件缓存不存在时,从 Gitee 私有仓库 clone 主题
#- if [ ! -d "themes/next" ]; then git clone git@github.com:leadscloud/hexo-theme-next.git themes/next; fi

script:
# 生成静态页面
- node_modules/.bin/hexo clean
- node_modules/.bin/hexo generate

after_success:
# 部署到 GitHub Pages 和 VPS
- .travis/deploy.sh

addons:
ssh_know_hosts:
- github.com
- love4026.org

vi .travis/deploy.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
set -ev
export TZ='Asia/Shanghai'

# 使用 rsync同步到 VPS
rsync -rv --delete -e 'ssh -o stricthostkeychecking=no -p 22' public/ root@182.92.100.67:/home/wwwroot/love4026.org

# 先 clone 再 commit,避免直接 force commit
git clone -b master git@github.com:leadscloud/leadscloud.github.io.git .deploy_git

cd .deploy_git
git checkout master
mv .git/ ../public/
cd ../public

git add .
git commit -m "Site updated: `date +"%Y-%m-%d %H:%M:%S"`"

# 同时 push 一份到自己的服务器上
#git remote add vps git@love4026.org:hexo.git

#git push vps master:master --force --quiet
git push origin master:master --force --quiet

删除一些文件

1
2
3
cd 博客根目录/.travis/
rm travis.key
rm travis.key.pub

由于我之前有github pages内容了,我需要把之前的内容与现有的hexo博客内容合并下

1
2
3
4
git init
git remote add origin git@github.com:leadscloud/leadscloud.github.io.git
git fetch origin master:temp
git merge temp

编辑下.gitignore 忽略一些文件

1
2
3
4
5
6
7
8
9
10
.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
package-lock.json
wordpress.xml
public/

最终测试

每次 push 新 commit 到 source 分支后,Travis CI 就会自动帮你构建最新的静态博客,并部署至 Github Pages 和你自己的 VPS 上。

1
2
3
4
git checkout --orphan source
git add .
git commit -m "Travis CI"
git push origin source:source

关于 –orphan 请参考 如何建立一个没有 Parent 的独立 Git branch

我的博客项目配置文件

https://github.com/leadscloud/leadscloud.github.io/tree/source

参考链接

使用 Travis CI 自动部署 Hexo 博客
使用 Travis 自动部署 Hexo 到 Github 与 自己的服务器
优化Hexo博客 - 压缩 HTML、CSS、JS、IMG 等

中继的原因是因为一些ip在我们本地的电脑上是无法连通的,但在阿里云等其它VPS上面就可以访问,这样我们可能通过中继来继续使用我们的shadowsocks.

开启系统的转发功能

vi /etc/sysctl.conf

net.ipv4.ip_forward=0 ,修改成 net.ipv4.ip_forward=1

编辑后使用以下命令让配置马上生效

sysctl -p

iptables的命令

1
2
3
4
iptables -t nat -A PREROUTING -p tcp --dport [端口号] -j DNAT --to-destination [目标IP]
iptables -t nat -A PREROUTING -p udp --dport [端口号] -j DNAT --to-destination [目标IP]
iptables -t nat -A POSTROUTING -p tcp -d [目标IP] --dport [端口号] -j SNAT --to-source [本地服务器公网IP]
iptables -t nat -A POSTROUTING -p udp -d [目标IP] --dport [端口号] -j SNAT --to-source [本地服务器公网IP]

重启iptables使配置生效

1
2
service iptables save
service iptables restart

直接修改iptables文件

上面添加过后,未来再修改ip的话,可以直接修改文件/etc/sysconfig/iptables

1
vi /etc/sysconfig/iptables

:%s/1.1.1.1/2.2.2.2 可以替换ip地址

然后

1
service iptables restart

Linode CentOS7下面的安装流程

安装前准备

1
2
3
yum install git -y
yum install epel-release -y
yum install libsodium -y # 使用salsa20 或 chacha20 或 chacha20-ietf 算法必须的

下载shadowsocksr

1
git clone -b manyuser https://github.com/shadowsocksr-backup/shadowsocksr.git && cd shadowsocksr/

配置shadowoskcr

vi user-config.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"server": "0.0.0.0",
"server_ipv6": "::",
"server_port": 3008,
"local_address": "127.0.0.1",
"local_port": 1080,

"password": "password-lanthy.com",
"method": "chacha20",
"protocol": "auth_aes128_md5",
"protocol_param": "",
"obfs": "tls1.2_ticket_auth_compatible",
"obfs_param": "",
"speed_limit_per_con": 0,
"speed_limit_per_user": 0,

"additional_ports" : {}, // only works under multi-user mode
"additional_ports_only" : false, // only works under multi-user mode
"timeout": 120,
"udp_timeout": 60,
"dns_ipv6": false,
"connect_verbose_info": 0,
"redirect": "",
"fast_open": true
}

后台运行ssr

cd shadowsocks

后台运行

python server.py -d start

如果要停止/重启:

python server.py -d stop/restart

查看日志:

tail -f /var/log/shadowsocksr.log

SSR启动脚本

以下启动脚本均假定shadowsocks-rss安装于/root/shadowsocksr目录,配置文件为/root/shadowsocksr/user-config.json,请按照实际情况自行修改

SysVinit启动脚本,适合CentOS/RHEL6系以及Ubuntu 14.x,Debian7.x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/bin/sh
# chkconfig: 2345 90 10
# description: Start or stop the Shadowsocks R server
#
### BEGIN INIT INFO
# Provides: Shadowsocks-R
# Required-Start: $network $syslog
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Start or stop the Shadowsocks R server
### END INIT INFO

# Author: Yvonne Lu(Min) <min@utbhost.com>

name=shadowsocks
PY=/usr/bin/python
SS=/root/shadowsocksr/shadowsocks/server.py
SSPY=server.py
conf=/root/shadowsocksr/user-config.json

start(){
$PY $SS -c $conf -d start
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo "$name start success"
else
echo "$name start failed"
fi
}

stop(){
pid=`ps -ef | grep -v grep | grep -v ps | grep -i "${SSPY}" | awk '{print $2}'`
if [ ! -z "$pid" ]; then
$PY $SS -c $conf -d stop
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo "$name stop success"
else
echo "$name stop failed"
fi
else
echo "$name is not running"
RETVAL=1
fi
}

status(){
pid=`ps -ef | grep -v grep | grep -v ps | grep -i "${SSPY}" | awk '{print $2}'`
if [ -z "$pid" ]; then
echo "$name is not running"
RETVAL=1
else
echo "$name is running with PID $pid"
RETVAL=0
fi
}

case "$1" in
'start')
start
;;
'stop')
stop
;;
'status')
status
;;
'restart')
stop
start
RETVAL=$?
;;
*)
echo "Usage: $0 { start | stop | restart | status }"
RETVAL=1
;;
esac
exit $RETVAL

请将上述脚本保存为 /etc/init.d/shadowsocks

CentOS/RHEL6 执行:

1
chmod 755 /etc/init.d/shadowsocks && chkconfig --add shadowsocks && service shadowsocks start

Ubuntu 14.x,Debian7.x 执行:

1
chmod 755 /etc/init.d/shadowsocks ; update-rc.d shadowsocks defaults ; service shadowsocks start

systemd脚本

systemd脚本,适用于CentOS/RHEL7以上,Ubuntu 15以上,Debian8以上

单用户版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=ShadowsocksR server
After=network.target
Wants=network.target

[Service]
Type=forking
PIDFile=/var/run/shadowsocksr.pid
ExecStart=/usr/bin/python /usr/local/shadowsocksr/shadowsocks/server.py --pid-file /var/run/shadowsocksr.pid -c /usr/local/shadowsocksr/user-config.json -d start
ExecStop=/usr/bin/python /usr/local/shadowsocksr/shadowsocks/server.py --pid-file /var/run/shadowsocksr.pid -c /usr/local/shadowsocksr/user-config.json -d stop
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

多用户版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Unit]
Description=ShadowsocksR server
After=syslog.target
After=network.target

[Service]
LimitCORE=infinity
LimitNOFILE=512000
LimitNPROC=512000
Type=simple
WorkingDirectory=/usr/local/shadowsocksr
ExecStart=/usr/bin/python /usr/local/shadowsocksr/server.py
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=always

[Install]
WantedBy=multi-user.target

请将上述脚本保存为 /etc/systemd/system/shadowsocksr.service
并执行systemctl enable shadowsocksr.service && systemctl start shadowsocksr.service

参考资料

SSR 优化

shadowsocks SSR客户端下载

参考资料

0%