这篇文章接上篇 基于 Git 搭建代码托管服务器,Git 服务器也可以托管电子书。新建一个 git 项目,在根目录下为不同的电子书创建子目录,在子目录下按照 gitbook 模板编写 markdown,然后通过 git push 推送到 git server,触发服务器 hooks 脚本执行,脚本会调用 gitbook 程序生成 html 格式电子书。服务器上启动一个静态 HTTP Server,就可以把电子书发布出去了。如果要更新电子书内容,只需要修改相应的 markdown 内容,然后 push 到服务器,电子书就会自动更新。
有了 Git + Gitbook + Markdown 编辑器后就可以开始写博客了。这种方式和 github pages 是一样的,但部署速度更快,且可以定制 git hooks 脚本,还可以利用服务器渲染动态页面。github pages 虽是免费的,但只能部署静态的内容。
首先创建一个新的仓库,名为 mybook,登录服务器
$ cd /home/git
$ sudo mkdir mybook.git && cd mybook.git
$ sudo git init --bare
Initialized empty Git repository in /home/git/mybook.git/
修改仓库用户归属,确保后面可以 git 用户有权限推送代码
sudo chown -R git:git /home/git/mybook.git
在自己的电脑上克隆仓库
git clone git@huoyijie.cn:/home/git/mybook.git
正克隆到 'mybook'...
warning: 您似乎克隆了一个空仓库。
打开 vscode,打开 mybook 文件夹,目前是空项目。添加框架代码后来看一下项目结构。
$ tree -L 2
.
├── bin
│ └── www
├── mybook.json
├── mygitbook
│ ├── book.json
│ ├── README.md
│ └── SUMMARY.md
├── node_modules
│ ├── http-server
│ ├── shelljs
├── package.json
├── package-lock.json
├── public
│ ├── gitbook
│ └── index.html
└── scripts
└── deploy.js
从上到下依次介绍下主要目录和文件
bin/www为http server启动脚本,看下内容
#!/bin/bash
DIR="public"
if [ ! -d "$DIR" ]; then
mkdir $DIR
echo "Home Page" > $DIR/index.html
fi
./node_modules/http-server/bin/http-server $DIR -a 127.0.0.1 -p 8001
静态文件存储目录为 $DIR=public ,监听 8001 端口。
mybook.json是自定义的关于当前仓库中 book 的配置文件,来看下内容
{
"deployBook": ["mygitbook"],
"dropBook": []
}
每个 book 都有唯一的字符串 name,如当前这篇博客文章的名字为 mygitbook。这个配置文件目前还很简单,只定义了 2 个配置项。
- deployBook: 需要发布到 http server 的 book name列表
- dropBook: 需用从 http server 中删除的 book name列表
也就是说,新增的 book 要在 deployBook 配置一下才会真正发布到 http server,需要下线的 book 要在 dropBook 配置一下。修改完配置推送变更到服务器就会自动部署更新。
mygitbook 目录里是当前文章真正的内容,可以通过
gitbook init初始化。为了更方便的管理,我创建了gitbookgen.js脚本,可以快速生成电子书模板。node_modules 为当前项目依赖的 npm 包,主要是 http server 和 shelljs,后者可以方便调用系统 shell 命令。
package.json 为 Node.js 项目配置文件
{
"name": "mybook",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "bin/www"
},
"dependencies": {
"http-server": "^0.12.3",
"shelljs": "^0.8.4"
}
}
public 目录为 http server 静态内容存储的目录,后面会把电子书部署在这个目录下
scripts/deploy.js 目录为部署 book 的脚本文件,会被 git server 上面的 hooks 脚本调用
#!/usr/bin/env node
// run from project root dir with command './scripts/deploy.js'
const shell = require('shelljs')
const fs = require('fs')
console.log(`pwd: ${shell.pwd()}`)
if(shell.exec('git pull').code) {
console.error('!> deploy error -> git pull failed')
process.exit(1)
}
const publicDir = 'public'
const mybookJson = JSON.parse(fs.readFileSync('mybook.json'))
console.log(`> load mybook.json: `, mybookJson)
mybookJson.dropBook.forEach(book => {
console.log(`> drop book: ${book}`)
var tmp = book.split('|')
book = tmp[0]
var bookid = tmp[1] || ''
if (!!bookid) {
const bookDir = `${publicDir}/${bookid}`
shell.rm('-rf', bookDir)
shell.rm('-rf', book)
} else {
console.error(`!> delete book failed ->lack of param bookid.`)
process.exit(1)
}
})
mybookJson.deployBook.forEach(book => {
console.log(`> deploy book: ${book}`)
if (!fs.existsSync(book)) {
console.error(`!> deploy error with ${book} -> not exist`)
process.exit(1)
} else {
shell.cd(book)
const bookJson = JSON.parse(fs.readFileSync(`book.json`))
console.log(`> load book.json:`, bookJson)
const bookDir = `${publicDir}/${bookJson.id}`
if(!shell.exec('gitbook build').code) {
shell.cd('-')
if (!fs.existsSync(bookDir)) {
shell.mkdir(bookDir)
} else {
shell.rm('-rf', `${bookDir}/*`)
}
shell.cp('-r', `${book}/_book/*`, bookDir)
console.info(`> deploy succeed with ${book}`)
} else {
console.error(`!> deploy error with ${book}`)
process.exit(1)
}
}
})
process.exit(0)
这个脚本主要做的事情就是等变更推送到服务器后,把配置在 deployBook 下的 book 发布出去,期间调用了 gitbook build 把 markdown 内容转为 html。把配置在 dropBook 下的 book 下线掉。这个脚本是被 git server 上的 post-receive hooks 调用的。post-receive 是在 git server 接受 push 后自动触发调用的。所以这个脚本是完成推送变更,自动部署更新 book 的关键。
下面来看一下存放在 git server 上的 post-receive hooks。文件存放路径为
$ ls -l /home/git/mybook.git/hooks/post-receive
-rwxr-xr-- 1 git git 103 Mar 23 15:59 /home/git/mybook.git/hooks/post-receive
这个脚本的内容非常简单
#!/bin/sh
cd /home/git/vswork/mybook
unset GIT_DIR
./scripts/deploy.js
exec git-update-server-info
主要逻辑就是调用了 ./scripts/deploy.js 部署脚本,其中 /home/git/vswork/mybook 是通过下面的命令克隆的,也是服务器上对应的博客工作目录。
$ cd /home/git/vswork
$ sudo git clone /home/git/mybook.git
$ cd mybook
$ npm install
安装好依赖后,修改下用户归属
sudo chown -R git:git mybook
到此为止,项目基本已经部署配置完成。接下来就是打开 vscode,编辑 mygitbook 电子书。编辑完成后 push 到服务器上完成文章自动部署更新。下面是 push 代码后的输出,可以看到 scripts/deploy.js 脚本在服务器上执行后的输出,有在自动部署 mygitbook。
$ git push
对象计数中: 4, 完成.
Delta compression using up to 8 threads.
压缩对象中: 100% (4/4), 完成.
写入对象中: 100% (4/4), 1.94 KiB | 1.94 MiB/s, 完成.
Total 4 (delta 2), reused 0 (delta 0)
remote: pwd: /home/git/vswork/mybook
remote: From /home/git/mybook
remote: 4fe0a5e..6e62e3d master -> origin/master
remote: Updating 4fe0a5e..6e62e3d
remote: Fast-forward
remote: mygitbook/README.md | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++--
remote: 1 file changed, 104 insertions(+), 4 deletions(-)
remote: > load mybook.json: {
remote: '// deployBook': "['firstbook','secondbook']",
remote: deployBook: [ 'mygitbook' ],
remote: '// dropBook': "['firstbook|f44b5ae08bb611ebbf5b4f5ee88ae545','secondbook|f44b5ae08bb611ebbf5b4f5ee88ae545']",
remote: dropBook: []
remote: }
remote: > deploy book: mygitbook
remote: > load book.json: {
remote: id: 'c0a4a7508bc011eb952e418fdf675f27',
remote: name: 'mygitbook',
remote: title: '使用 Git 与 Gitbook 创建管理电子书',
remote: author: 'huoyijie',
remote: description: '使用 Git 与 Gitbook 创建管理电子书',
remote: introduce: '这里是内容介绍...',
remote: coverImg: 'https://cdn.huoyijie.cn/ab/c0a4a7508bc011eb952e418fdf675f27/mygitbook-cover.jpg',
remote: language: 'zh-hans',
remote: plugins: [ '-lunr', '-search', '-sharing', '-fontsettings' ],
remote: links: { sidebar: { '首页': 'https://huoyijie.cn/?from=article_mygitbook' } }
remote: }
remote: info: 7 plugins are installed
remote: info: 2 explicitly listed
remote: info: loading plugin "highlight"... OK
remote: info: loading plugin "theme-default"... OK
remote: info: found 1 pages
remote: info: found 0 asset files
remote: info: >> generation finished with success in 0.4s !
remote: > deploy succeed with mygitbook
To huoyijie.cn:/home/git/mybook.git
4fe0a5e..6e62e3d master -> master
OK,关于如何使用 Git 与 Gitbook 创建管理电子书的主要内容介绍完了。