markdown一键发布的个人博客搭建
[TOC]
1. 初衷
研究发布个人博客的初衷是源于一个痛苦。这个痛苦是我日常读书学习的过程中编写和总结的笔记文档,在发布到博客、简书等平台上时,都需要进行大量的格式调整动作,包括编辑器、格式、图片引用上传等,而这些繁杂的无意义发布动作,极大的降低了公开文档的积极性,也很难形成一个长期可保持的有效习惯,反而会对笔记文档的编写,产生负反馈。
因此我的诉求是有一个博客系统,可以将我日常在本地编写的笔记文档,不经修改的直接发布。
2. 文章发布的渠道选型
有了目标和需求,接下来就是选型了,针对笔记文档的公开有三种途径:
- 简书、CSDN、知乎文章等第三方的网站
- 好处:流量大、比较成型、完全不用自己折腾
- 坏处:必须使用对应的编辑器。
需要我使用他们的编辑器来排版,并不符合我的需求,但是确实有点可惜他们的流量,后续可以考虑不作为主力平台怎么再导出一份到这些平台上。
- 使用个人笔记软件,并发布到笔记软件对应的个人空间上
- 好处:和笔记软件深度结合,完全不用自己折腾。
- 坏处:流量有限,可导出性受限、对软件有很强的依赖性。
对于常年使用过为知笔记、印象笔记后,又全部放弃的人来说,笔记软件早已不是我考虑的范围了。目前的笔记软件,基本上都无法满足导出和兼容性的要求,自己写的文章基本上就是进入了一个黑盒子,完全无法通过个人来规避灾备风险。详细的关于不要使用笔记软件的心路历程,我有一篇专门的笔记来记录,再此不做详细赘述了,结论就是不要用这种黑盒子的笔记软件。
- 自己搭建博客服务器
- 好处:完全自己可控,随意定制。
- 坏处:需要自己折腾、要有云服务器、要有域名。
针对我的目标和需求,这是目前比较好的方案,那么需要准备如下几个东西:
-
域名
我的
icesky1stm.cn
域名,10年只要334,还有一些更便宜的如10年198的,1年几块钱的,这个很好解决,备案有一些流程。 -
静态IP/云服务器 + github备份
我使用的是腾讯云服务器。腾讯云、阿里云、百度云等都有1年99的新人优惠活动。其实静态IP也是也是可以考虑的,当然还有使用frp做内网穿透之类的,方法很多,但我选择最简单的。
由于云服务器可能随着优惠活动会不停的变化,因此blog服务器不能作为最终的一个文件落地位置。那么就需要一个可以中转的位置,使用github再合适不过了。本地编写,提交到github上,blog服务器再拉取,可以完美的解决备份问题。
-
选择建站的软件,需要支持markdown、需要不修改格式、需要能支持本地图片引用
-
workpress
markdown可以排除workpress等最常用的建站框架,虽然他号称占有30%的市场份额。
-
hexo
hexo是一个轻量级的博客,是基于nodejs的,并且提供了一套自有的hexo-admin的markdown编辑器,思考再三不太符合我的需求。因为我本地使用typora作为markdown编辑器,偶尔用vscode甚至vim。我不希望我的文档跟任何的软件有强关联。
-
gitblog
搜索再三,发现了github上的一个gitblog项目,开发语言是php,star有800多个,试用了一下,它的核心功能是有一个blog/文件夹,下面可以直接放md文件,另外有blog/img文件夹,用来存放markdown的相对路径链接图片(惊喜,不需要图床,细节可以参见标题5),虽然这个项目2016年已经停更了,但是功能是满足的。 优点是: 轻量、不需要数据库、markdown源文件几乎不需要修改、可以引用本地路径图片。 缺点是:没有评论功能,模板theme比较少,用php的不会魔改。
当然,使用何种blog软件都可以,后续也可能会进行修改,只能能满足
支持markdown、不需要修改格式、能支持本地图片引用
这三点就可以了。接下来就是针对具体的使用gitblog,编写一键提交的一些脚本等。 -
3. 安装、配置、使用gitblog
3.1 下载
github上的地址是(https://github.com/jockchou/gitblog),不过速度很慢。
我使用的是gitee上的国内同步镜像链接:https://gitee.com/mirrors/gitblog.git 下载
我把下载好的包解压放在了/root/gitlab/gitlab
目录下,可见的文件结构如下:
[root@VM_0_10_centos gitblog]# ls -ltr
总用量 836
-rwxrwxrwx 1 root root 4301 2月 18 10:37 README.md
-rwxrwxrwx 1 root root 11358 2月 18 10:37 LICENSE
-rwxrwxrwx 1 root root 74 2月 18 10:37 robots.txt
-rwxrwxrwx 1 root root 9793 2月 18 10:37 index.php
-rwxrwxrwx 1 root root 1099 2月 18 10:37 history.txt
-rwxrwxrwx 1 root root 2144 2月 18 10:37 example-conf.yaml
-rwxrwxrwx 1 root root 775989 2月 18 10:37 screenshot.png
drwxrwxrwx 8 root root 4096 2月 18 13:20 theme
drwxrwxrwx 7 root root 4096 2月 18 13:25 sys
drwxrwxrwx 14 root root 4096 2月 19 10:56 app
-rwxrwxrwx 1 root root 4286 2月 19 14:38 favicon.ico
-rwxrwxrwx 1 root root 3942 2月 19 14:38 logo.png
drwxr-xr-x 4 root root 4096 2月 20 10:32 blog
-rwxrwxrwx 1 root root 688 2月 20 10:41 conf.yaml
3.2 安装
- 安装服务容器: nginx
- 安装nginx的php的cgi解析工具: php-fpm
- 安装php运行环境
- 安装php的mbstring库
yum install nginx -y
yum install php-fpm -y
yum install php -y
yum install php-mbstring -y
3.3 配置
- php.ini配置文件修改和增加php-mbstring配置
; 修改
short_open_tag = On
; 新增
extension=mbstring.so
mbstring.language = Chinese
mbstring.internal_encoding = UTF-8
mbstring.encoding_translation = On
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
mbstring.detect_order = UTF-8
mbstring.substitute_character = none
-
/etc/php-fpm.d/www.conf 的默认端口就是9000,如果没有冲突可以不用修改,如果修改了记得也要修改nginx.conf中的fastcgi_pass。
- /etc/nginx/nginx.conf 修改: 一般情况只改前三行就可以了。
server {
listen 80;
server_name 49.233.140.0:80;
root /root/gitblog/gitblog;
index index.html index.htm index.php;
location ~ \.(jpg|png|gif|js|css|swf|flv|ico)$ {
expires 12h;
}
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?$1 last ;
break;
}
}
location ~* ^/(doc|logs|app|sys)/ {
return 403;
}
location ~ .*\.(php|php5)?$
{
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
3.4 启动
-
nginx
- php-fpm &
也可以使用写好的启停脚本:
- 启动服务
[root@VM_0_10_centos gitblog]# cat start.gitblog.sh
nginx
php-fpm &
- 停止服务
[root@VM_0_10_centos gitblog]# cat stop.gitblog.sh
nginx -s stop
kill -9 `ps -aef | grep php-fpm | awk '{if($8!~/grep/) print $2}'`
- 清理缓存(每次修改md文件,都要清理一下,否则可能会不生效 )
[root@VM_0_10_centos gitblog]# cat cache.gitblog.sh
rm -rf ./gitblog/app/cache/*
3.5 使用
gitblog安装的目录如下:
.
├── app
│ ├── cache
│ └── logs
├── theme
│ ├── default
│ ├── quest
│ └── simple
├── sys
├── blog
│ └── img
├── conf.yaml
├── favicon.ico
├── index.php
├── LICENSE
└── robots.txt
需要关心的有三个地方:
- conf.yaml, 这里是配置基本信息的,里面有一个example-conf.yaml是例子,都写了说明,重要的几个配置说一下
- enableCache : 应该配置成false ,否则md文件发布之后,修改了不生效,会在
app/cache/
下面生成缓存的数据。 - youyan,disqus这些评论模块应该都失效了,可以不配置。
- enableCache : 应该配置成false ,否则md文件发布之后,修改了不生效,会在
#GitBlog配置文件,使用4个空格代替Tab
---
url : "http://jockchou.gitblog.cn" #网站首页url
title : jockchou的博客 #博客标题
subtitle : 自豪地采用GitBlog #博客副标题
theme : quest #主题名称
enableCache : true #是否开启缓存
highlight : true #是否开启代码高亮支持
mathjax : false #是否开启MathJax数学公式渲染支持,MathJax和KaTeX同时设置时,KaTeX优先
katex : false #是否开启KaTeX数学公式渲染支持,MathJax和KaTeX同时设置时,KaTeX优先
youyan : 0000000 #有言评论框UID,youyan和disqus同时设置时,disqus优先
disqus : demo-site #DISQUS评论框 Short Site Name,XXX.disqus.com,youyan和disqus同时设置时,disqus优先
baiduAnalytics : 732acc76ff6bd41343951a67cbfafe34 #百度统计ID
keywords : jockchou,markdown,blog,php,github #网站关键字
description : GitBlog是一个简单易用的Markdown博客系统,这是我的第一个GitBlog博客. #网站描述
version : 2.2 #系统版本号
blog:
recentSize : 5 #最近博客显示条数
pageSize : 10 #每页显示博客条数
pageBarSize : 5 #翻页Bar的长度
allBlogsForPage : false #页面需要所有博客数据
author:
name : jockchou #你的名称
email : 164068300@qq.com #你的邮箱
github : jockchou #你的Github名称
weibo : 2558456121 #你的微博ID
text:
title: 简介 #任一文本标题
intro: > ##这里可以多行 #任一文本内容
GitBlog是一个简单易用的Markdown博客系统,
这是我的第一个GitBlog博客
- blog文件夹,下面有一个img文件夹,img用来放图片,blog用来访md文件,支持多层级,但是建议不要超过3层。下面是我的本地例子,因为我的图片引用是Pic/,因此我建了一个软链接来解决该问题。
[root@VM_0_10_centos blog]# l -tr
总用量 80
lrwxrwxrwx 1 root root 3 2月 19 15:36 Pic -> img
-rw-r--r-- 1 root root 4928 2月 19 15:36 dockerswarm集群管理初步使用.md
-rw-r--r-- 1 root root 28599 2月 19 15:36 初次使用docker并搭建oracle环境和xip环境.md
-rw-r--r-- 1 root root 16320 2月 19 15:36 安装和使用loadrunner_linux代理端.md
-rw-r--r-- 1 root root 7670 2月 19 21:00 frp内网穿透工具的使用和配置.md
drwxr-xr-x 7 root root 4096 2月 20 00:18 img
-rw-r--r-- 1 root root 13656 2月 20 10:32 markdown源文件的个人博客搭建.md
- app/library/markdown.php,这个是项目中解析markdown的程序,对于未解析到的会赋值一些默认值,可以不修改,我是把默认的作者从admin改成了icesky1stm
markdown编写的要求:
对markdown的整体格式是完全没有要求的,但是由于blog会使用到标题、分类、作者、时间、标签、摘要
等一些属性,定义这些要素,gitblog是通过在markdwon中定义一段注释来实现的,一般来说定义一下作者、日期和分类就可以了,我常用的头如下:
<!--
author: icesky1stm
date: 2021-02-18
category: 工具环境
-->
可以定义的内容有如下:
<!--
author: 博客作者名称
date: 博客时间,用于页面显示,通常来说你不需要填写这个字段,默认就是创建日期
title: 博客标题
tags: 博客里的标签,多个用逗号或空格分隔
category: 博客分类,多个用逗号或空格分隔
status: 博客状态,draft表示草稿,GitBlog解析时会忽略草稿;publish表示发表状态,默认为publish
summary: 博客摘要信息
-->
markdown如果不定义,也可以正常展现,比如标题会取默认的h1或h2,分类是无,作者会是默认的admin,时间是默认的文件创建时间等,有的时候不是很理想,但是针对老文章或者老笔记,想一股脑的放上去,还是很不错的。
4. 本地一键发布到blog上的流程
编写发布的整体流程是:
本地文件 -> 本地git仓库 ->github仓库 ->blog服务器git仓库
具体的过程其实是有一个如下的顺序,当然我是通过脚本实现了如下的动作:
- 本地编写md文件
- 将本地md文件和img图片资源复制到本地仓库
- 将本地仓库提交到远程仓库
- 通知服务器/定时执行 从远程仓库拉取最新的md数据
配合脚本实际的操作的过程是:
- 本地编写md文件
- 在finder中ctrl+c复制文件
- iterm2中执行
mdblog cmd+c
基本上几秒钟就可以搞定了,脚本我放在\$HOME/binsh下, 并设置了\$PATH
4.1 本地仓库的准备工作
- 新建blog的仓库,我创建的仓库如下:https://github.com/icesky1stm/md_blog.git
- 本地git clone该仓库,并且设置好自动git push自动提交的配置
- 由于gitblog使用的本地图片是img,而我用的是Pic,因此在blog/文件夹下需要建立一个Pic到img的软链接
ln -s img Pic
4.2 blog服务端git仓库的准备工作
- 将服务器的blog文件夹删掉, 执行 git clone https://github.com/icesky1stm/md_blog.git blog
- 编写定期同步的脚本sync.gitblog.sh,内容如下:
logname=/root/gitblog/sync.log
# 记录日志
echo `date` >> $logname
cd /root/gitblog/gitblog/blog && git pull >> $logname
# 检查日志文件最大数
maxsize=$((10*1024*1024))
logsize=`ls -l $logname | awk '{ print $5 }'`
if [ $logsize -gt $maxsize ]
then
echo "$logsize > $maxsize, 清理$logname"
rm -f $logname
# mv $logname $logname."`date +%Y-%m-%d_%H:%M:%S`"
#else
# echo "$logsize < $maxsize"
fi
- 执行crontab -e, 配置定时,我这里配置的每5分钟自动同步一次
*/5 * * * * /root/gitblog/sync.gitblog.sh
4.3 本地文件自动提交脚本
因为我的文档是散落在自己内部的一套文件归档中的,一个文件夹中包含原书籍、扩展资料和我写的md笔记文件,因此不可能把我的本地文件夹直接提交到blog中的。如果每次copy,也是比较费劲的,我是通过一个脚本来解决该问题的。
mdblog的脚本内容如下:
#!/bin/bash
# 基础信息设置
md_home=/Users/suitm/Downloads/md_blog
server_ip=49.233.140.0
server_user=root
server_pwd=****
server_shell=/root/gitblog/sync.gitblog.sh
SSHPASS=/usr/local/bin/sshpass
CP="/bin/cp -rf"
RM="/bin/rm -rf"
echo -e "\033[32m|--md_blog\033[0m"
if [ $# -ne 1 ]
then
echo -e "\033[32m|---- 2021-02-19 created by icesky \033[0m"
exit
fi
fullname=$1
filepath=`dirname "$fullname"`
filename=`basename "$fullname"`
## 获取源文件和图片位置、目标文件和图片位置
src_file_path=$fullname
src_img_path=$filepath/Pic/${filename%.*}.assets
target_file_path=$md_home/$filename
target_img_path=$md_home/Pic/${filename%.*}.assets
# 拷贝文件
echo -e " \033[32m|--1:复制文件$src_file_path -> $target_file_path\033[0m"
$CP "$src_file_path" "$target_file_path"
if [ -d "$target_img_path" ]
then
echo -e " \033[32m|--2:删除图片文件夹$target_img_path\033[0m"
$RM -rf "$target_img_path"
fi
if [ -d "$src_img_path" ]
then
echo -e " \033[32m|--3:复制图片文件夹$src_img_path -> $target_img_path\033[0m"
$CP "$src_img_path" "$target_img_path"
fi
# 提交到github上
now=`date`
echo -e " \033[32m|--4:提交git到仓库,COMMENT[$now]\033[0m"
cd $md_home && git add -A && git commit -m "$now" && git pull && git push
# sshpass远程登录服务器直接拉取刷新(这一步可选,也可以等待服务器定时同步)
echo -e " \033[32m|--5:登录远程服务器执行拉取最新数据,[$server_ip]\033[0m"
$SSHPASS -p $server_pwd ssh $server_user@$server_ip $server_shell
echo -e "\033[32m|--md_blog\033[0m"
有两点要说明:
- 这其中有一个重要的macOS的操作快捷方式是,finder中复制的文件,在iterm2中cmd+c会把文件全路径粘贴出来。
- 本地文件的Pic路径的typora设置,参见第五部分。如果是使用图床,则可以把脚本中的2和3步骤删除即可。
5. 其他说明
5.1 关于markdown图片的说明
markdown引用图片一直是一个比较大的问题,使用图片的方案有三种:
-
使用图床
目前的成熟方案基本上就是使用七牛或者iPIC等图床,很多markdown工具也支持图片复制时候的自动上传到图床。使用图床的缺点比较明显,第一是必须要联网才能看,不联网基本没有办法看的。 第二是依赖第三方的一个服务,也就是你的文档可能永远属于你的,你的图片不一定永远属于你的。
-
使用本地相对文件引用(推荐)
目前我使用的方式, typora支持图片粘贴的时候自动创建文件,同时可以选择是在
./
创建,还是./$文件名.asset
下面。我最开始使用的是
./
下面,但是一个文件夹有很多之后,会导致多个文档的无意义图片混在一起,如果想单独提取或者备份某一个文档的话,会很不方便,如果单独为每个图片都修改命名规则,则编写的无用工作量就增加了。后来我使用
./$文件名.asset
,这样基本上一个md对应一个.asset的文件夹,和html的导出效果是一样的。 这样使用起来没有什么困难,但是文件夹看起来就比较乱。目前使用的方案是,自定义的模式,
./Pic/${filename}.assets
路径,这样文件都集中在了./Pic
文件夹下面,并且还进行了分类。这与gitblog的作者的img文件夹的想法不谋而合,看来果然大家遇到的问题都是共性的。typora的设置如下:
-
将图片base64码插入到文档中=[tag1]
我偶尔会使用该方法进行图片插入,使用场景是图片较小并且图片数很少的时候使用。 他的优点是就在文档中,不需要依赖外部文件,缺点也很明显,就是会导致文档太大,并且对阅读产生很大的困扰。
具体的用法是,后面的图片链接的地址改成
data:image/png;base64,XXXXXX
,具体的例子如下:
![img](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABX4AAAPOCAYAAAC4VgAiAAAMSGlDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnltSSWiBCEgJvYnSq5QQWgQBqYKNkAQSSowJQcSuLCq4dhEBG7oqouhaALFjL4tidy0PdVFZWRcLNlTepICufu+9753vm3v/e+ac/5TPGnnRjtPcp/zJN9NmbfzKK/bPM5887Wbf47fP1bX2GmGzcbnz+fP529VzZjvDr//+P2nfTfmfMjY/Dcl88P+708+A8lvk81+9dVXNac9c+ZM2dvbK/fee2+5/fbbq0lsYtE+N/m35F9U9fBXU3BvIwAAAABJRU5ErkJggg==
优雅一点的写法是写连接,然后在文章结尾写base64的内容:
![img][imgtagname] <!--文章中-->
<!--文章的结尾-->
[imgtagname]:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABX4AAAPOCAYAAAC4VgAiAAAMSGlDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnltSSWiBCEgJvYnSq5QQWgQBqYKNkAQSSowJQcSuLCq4dhEBG7oqouhaALFjL4tidy0PdVFZWRcLNlTepICufu+9753vm3v/e+ac/5TPGnnRjtPcp/zJN9NmbfzKK/bPM5887Wbf47fP1bX2GmGzcbnz+fP529VzZjvDr//+P2nfTfmfMjY/Dcl88P+708+A8lvk81+9dVXNac9c+ZM2dvbK/fee2+5/fbbq0lsYtE+N/m35F9U9fBXU3BvIwAAAABJRU5ErkJggg==