Cyrus Blog

FLAG{S0_H4PPY_C_U_H3R3} (>.<)

几种持久化及反向代理解决方案

本文共 1.5k 字,预计阅读时间 6 分钟。

先说一下 Hexo 的配置,以及我这个主题的一些问题和解决方案。然后说一下 Python(Django) 和 NodeJS(Hexo) 的持久化问题,以及 Nginx 和 Apache 反代指定端口的方法。

Hexo+Hacker主题

对不起,我的 WordPress 后台炸了。然后温馨提示:
前端选手不要用 Hexo!安心 WordPress吧。
选择 Hexo 原因是,毕竟是基于 NodeJS 。比起基于 Ruby 的 Jekyll 和 Octopress,至少能看得懂,事实证明如果看不懂可能根本没法修理迁移过程中的问题。虽然 Jekyll 有一个不错的后台编辑器 Prose,但是查了一下 Hexo 也有功能相同的插件。
安装过程不说了。通过 WP 后台导出 xml,然后用 hexo-migrator-wordpress 导入。这时候往往编译不过去。
问题出在 Hexo 使用的 MarkDown 渲染上,他会把文章中的 { %{ # 自动渲染,不管在不在代码段,这里我是加了空格。对前端选手各种 template 和 ctf 选手各种奇怪的 flag 很不友好。同时 WordPress 转移的格式很不好,这里写了一个脚本:

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
import os
def f(fln):
fl = open(fln, "r")
flo = open("0-%s"%fln, "w")
s = fl.readline()
while s != "":
if s[0] == "\t":
s = s[1:]
if s[0] == "#":
flo.write(s[:-1])
elif s.partition("<pre")[1] != "":
flo.write("\n```\n")
flo.write(s.replace("<pre>","").replace("<pre",""))
elif s.partition("</pre>")[1] != "":
flo.write(s.replace("</pre>",""))
flo.write("\n```\n")
else:
flo.write(s)
s = fl.readline()
fl.close()
flo.close()

rootdir = '../md-raw'
list = os.listdir(rootdir)
for i in range(0,len(list)):
path = os.path.join(rootdir,list[i])
if str(path)[-3:] == ".md":
print(path[8:])
f(path[8:])

写完脚本才发现还有实体字符没有替换(逃
选了一个 Hacker 主题,链接最下方。对,我就是觉得到处都是 Next 不想用。
这个主题有几个问题:

  1. 主页无法显示摘要,当然可以用 <!--more-->,不过为什么好好写 md 要加这个呢对不对。所以我就换了一个首页(
    themes/hacker/layout/index.ejs 里随便写。建议备份一下,万一作者哪天心情好写了这个 feature 还能更新。

    实际上还有一个解决方案,我现在在 themes/hacker/layout/components/article.ejs 里改了一下这段文字,大概位于42行左右:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     <div class="article-content">
    <div class="entry">
    <% if (index){ %>
    <%- strip_html(item.content).substring(0, 250) %>&emsp;
    <a href="<%- config.root %><%- item.path %>" target="_blank">阅读全文</a>
    <% } else { %>
    <%- item.content %>
    <% } %>
    </div>
    </div>

大概有现在这样的摘要界面。
2. 列表渲染没 CSS。在 themes/hacker/source/css/components/article.styl 中,加上这一段:

1
2
3
4
5
6
ul
margin 2rem 0
line-height 1.8
ol
margin 2rem 0
line-height 1.8
  1. Archives 页面标题巨丑。还是同一个目录,隔壁的 archive.styl 中,.archive-title 部分给改成这样。原来似乎是 2.8em 和 1,下面的 time 也可以自己看着改。
    1
    2
    font-size 2.2em
    line-height 1.5

然后推荐一个 hexo-admin 插件,可以自行加后台权限。

Django的持久化

最近包括 Hexo 在内搭了两个站,分别体验了一下 Python 和 NodeJS 的持久化服务。
Django 的持久化是用 supervisor 做的,ubuntu 下 apt 直接可以安装。在 /etc/supervisor/conf.d 目录下可以自行新建一个配置文件,实际上每个配置文件中可以包含多个启动项。Django 部署可以考虑用 uWSGI 或者 Gunicorn。这里以 Django + Gunicorn 为例写的配置文件。

1
2
3
4
5
6
7
8
9
[program:winter]
command = gunicorn -w8 -b0.0.0.0:8008 app.wsgi:application
directory = ~/app-folder/
startsecs = 0
stopwaitsecs = 0
autostart = false
autorestart = true
stdout_logfile = ~/app/gunicorn_supervisor_log.log
stderr_logfile = ~/app/gunicorn_supervisor_err.log

其中的 directory 就是运行 command 的目录,这里也就是 manage.py 所在目录,Gunicorn 在此目录运行。
supervisor 具体用法直接 supervisorctl -h 就好啦,注意有一个 -ctl 在后面(

Hexo的持久化

Hexo 其实也可以使用 supervisor 做持久化服务,但是不知为啥在我自己 VPS 上安装失败了。所以最后用了一个 npm 原生的解决方案:forever。
在 Hexo 目录下,建立一个 js 文件,写入这段配置即可,此处为 blog.js:

1
2
3
4
5
6
7
8
9
10
11
var spawn = require('child_process').spawn;
free = spawn('hexo', ['server', '-p 4000']);
free.stdout.on('data', function (data) {
console.log('standard output:\n' + data);
});
free.stderr.on('data', function (data) {
console.log('standard error output:\n' + data);
});
free.on('exit', function (code, signal) {
console.log('child process eixt ,exit:' + code);
});

网上有流传一种 require(‘hexo’)… 的配置并不能生效(逃
安装完成后只有一句话:

1
forever start --minUptime 1000 --spinSleepTime 1000 -l hexo.log -a blog.js

中间参数可以自行 forever -h

Nginx的反向代理

/etc/nginx/conf.d 目录下,新建一个 conf 配置文件,写入以下配置,这里以 Django 说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server{
listen 80; # 监听的端口
server_name 111.222.333.444; # 服务器ip
server_name 0.0.0.0;
server_name django.website.com; # 域名
location / {
proxy_pass http://127.0.0.1:8008; # 本地反代端口(运行Gunicorn的端口)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 128m;
}
location /static { # 静态文件相对链接路径
alias ~/app-root/static; # 静态文件的本地绝对路径
}
}

Nginx 重启一下即可,一般不需要额外配置。
如果 Django 的 templates 中用了 STATIC_URL 相对路径,记得要和相对链接路径一致。

Apache2的反向代理

Apache2 的配置文件存放管理相对比较好,但是一大堆 enabled 和 available 对新手很不友好。
Apache2 的反向代理一般在 /etc/apache2/sites-enabled/ 中直接配置 VirtualHost:

1
2
3
4
5
<VirtualHost *:80>
ServerName blog.website.com
ProxyPass / http://website.com:4000/
ProxyPassReverse / http://website.com:4000/
</VirtualHost>

第一行是要让用户访问的二级域名或者别的子域名,第二第三行是反向代理的端口。
两个坑:

  1. 第二第三行不能使用相对路径,也就是需要用 http:// 开头定位一个绝对地址,是的 localhost 也不行,直接打 127.0.0.1 这种 ip 也不行。
  2. 要将 Proxy 和 Proxy_http 相关文件从 mods-available 复制到 mods-enabled。推荐直接用 cp proxy* ../mods_enabled进行复制。