go编译中出现的link signal killed问题
在vps中编译hugo代码时出现:
tool/linux_amd64/link: signal: killed
经过搜索查到类似的场景:
https://github.com/beego/wetalk/issues/32
不同的是这个是beego,而我编译的是hugo,所以初步断定应该是跟go的环境有关,而不是hugo代码。所以验证了帖子中关于内存的说法,发现重启后,果然正常。
在vps中编译hugo代码时出现:
tool/linux_amd64/link: signal: killed
经过搜索查到类似的场景:
https://github.com/beego/wetalk/issues/32
不同的是这个是beego,而我编译的是hugo,所以初步断定应该是跟go的环境有关,而不是hugo代码。所以验证了帖子中关于内存的说法,发现重启后,果然正常。
2016.12.16:由于文章中的360 网盘的资源挂了,重新更新了tomato的刷机包的路径
小米路由器R1D已经使用了快一年,一直想刷机,主要因为:
小米路由器R1D是一款基于博通bcm4709( c )和OpenWRT深度定制的智能路由器。
小米路由器是深度定制版的OpenWRT,网上大概搜了一下,可选的有OpenWRT原生系统,DD-WRT和Tomato三种系统可以尝试。
首先从官方的硬件支持列表我们并没有看到R1D的支持:https://wiki.openwrt.org/toh/start 。其次从小米论坛和google也没有找到明确支持的rom。
巧妇难为无米之炊。
结果:放弃
从官方的支持列表中:http://dd-wrt.com/wiki/index.php/Supported_Devices ,我们并没有看到R1D的支持ROM。但是我们可以找到非官方的rom,例如:http://bbs.xiaomi.cn/t-10691878 。
刷机流程参见:http://www.right.com.cn/forum/thread-143121-1-1.html ,本人尝试多次,均在第6步失败,初步判断是tftp server没有正常启动。
分析原因:原博是在0.4.58的rom上做的验证,本人尝试0.4.58版的USB和web页面升级的方式,均失败。web直接校验失败,USB刷机后,路由器无法正常启动,于是只能采用的最新开发版来验证。猜想是小米硬件做了升级限制或者在软件层面有专门对这个漏洞做修复。
结果:失败。如果有最近刷机成功的兄弟,也望留言指教。
AdvancedTomato是一套基于Tomato的路由器管理界面,其核心是tomato。这个是tomato对应R1D的下载路径:
本次刷机实际使用的是这个:http://bbs.xiaomi.cn/t-11522784 ,因为有人验证过,并且支持中文,相对风险会小些,实际效果有待日后进一步观察。
说明:
因为文章里面的360的网盘挂了,特将rom重新发布:
链接: http://pan.baidu.com/s/1o8TRooE 密码: qe4j
因为本人验证时已经是很久以前的事情了,所以建议看到的朋友在上面的路径下载最新的版本尝试。
结果:成功。
启示:按照CFE的思路,理论上也可以来刷DD-WRT,但已经折腾一天了,改日有机会再试吧。
如果你是其他型号的路由器,只要是刷相同类型的rom,流程基本相似,希望有帮到大家,也欢迎大家交流。
最后,有图有真相:
刷完后,感觉整个世界都平静了。
http://blog.icece.tw/Xiaomi-R1D-1TB-Flash-Tomato
补充:
目前看,LoRa是一个在IOT方案领域替换GSM的初步可行方案,主要从距离和功耗两个考虑方面。
介绍如下:
http://www.lora-alliance.org/What-Is-LoRa/Technology
http://www.rfwireless-world.com/Terminology/LoRa-technology-basics.html
http://www.rfwireless-world.com/Terminology/IoT-wireless-technologies.html
芯片厂商目前也已经有了量产的芯片可供评估,成本在1-2个美金。
http://www.microchip.com/design-centers/wireless-connectivity/embedded-wireless/lora-technology
http://www.semtech.com/wireless-rf/lora.html
在很多安全服务中,我们都需要签名的安全证书。
注意 如果不生成证书,后面配置部分的配置中用 pubkey 认证的 conn 都不能用,甚至不能保留在配置中。
每一个完整的 ssl 证书都有一个公钥和一个私钥,它们可以在一起也可以分开放(当然如果你要在网络上传输,肯定只能用公钥)。公钥是在网络上传输的,而私钥是藏好用来和接收到的公钥配对的(因此私钥里也有整个公钥,用来配对)。
生成一个私钥:
ipsec pki --gen --outform pem > ca.pem
没什么好解释的,--outform 一共有三个格式可选,但是另外两个是 der 和 pgp...
基于这个私钥自己签一个 CA 证书:
ipsec pki --self --in ca.pem --dn "C=CN, O=strongSwan, CN=strongSwan CA" --ca --outform pem > ca.cert.pem
这里 --self 表示自签证书,--in 是输入的私钥,--dn 是判别名,--ca 表示生成 CA,其它同上。这里需要解释下判别名:
C 表示国家名,同样还有 ST 州/省名,L 地区名,STREET(全大写) 街道名。
O 表示组织名。
CN 为通用名。
具体见微软的文档:Distinguished Names
同样生成私钥:
ipsec pki --gen --outform pem > server.pem
用我们刚才自签的 CA 证书给自己发一个服务器证书:
ipsec pki --pub --in server.pem | ipsec pki --issue --cacert ca.cert.pem \
--cakey ca.pem --dn "C=CN, O=strongSwan, CN=forum.suse.org.cn" \
--san="forum.suse.org.cn" --flag serverAuth --flag ikeIntermediate \
--outform pem > server.cert.pem
这条命令的意思解释下:
ipsec pki --pub --in server.pem
是从我们刚生成的私钥里把公钥提取出来,然后用公钥去参与后面的服务器证书签发(这个是 VPN 连接时候要用的,你不想把私钥也给它吧?那样跟没签证书一样...)。
--issue, --cacert 和 --cakey 就是表明要用刚才自签的 CA 证书来签这个服务器证书。
--dn, --san,--flag 是一些客户端方面的特殊要求:
iOS 客户端要求 CN 也就是通用名必须是你的服务器的 URL 或 IP 地址;
Windows 7 不但要求了上面,还要求必须显式说明这个服务器证书的用途(用于与服务器进行认证),--flag serverAuth;
非 iOS 的 Mac OS X 要求了“IP 安全网络密钥互换居间(IP Security IKE Intermediate)”这种增强型密钥用法(EKU),--flag ikdeIntermediate;
Android 和 iOS 都要求服务器别名(serverAltName)就是服务器的 URL 或 IP 地址,--san。
依然是生成私钥:
ipsec pki --gen --outform pem > client.pem
然后用刚才自签的 CA 证书来签客户端证书:
ipsec pki --pub --in client.pem | ipsec pki --issue --cacert caCert.pem \
--cakey caKey.pem --dn "C=CN, O=strongSwan, CN=client" \
--outform pem > client.cert.pem
这时命令行会提示你输入两遍密码,这个就是你的客户端证书密码。
看懂了服务器的,客户端的也就不难理解了。除了没有那一堆特殊要求别的都一样。
客户端证书可以每个客户端签一个,也可以让它们公用一个。是否多签看用途,一般用于区分设备(计费是不用这样的,是用账户来区分的)。
你可能还想生成一个可以直接导入的 pkcs12 证书(用于手机,诺基亚没这东西还不行):
openssl pkcs12 -export -inkey client.pem -in client.cert.pem -name "client" \
-certfile ca.cert.pem -caname "strongSwan CA" -out client.cert.p12
cp -r ca.cert.pem /etc/ipsec.d/cacerts/
cp -r server.cert.pem /etc/ipsec.d/certs/
cp -r server.pem /etc/ipsec.d/private/
cp -r client.cert.pem /etc/ipsec.d/certs/
cp -r client.pem /etc/ipsec.d/private/
CA 证书、客户证书(两个)和 .p12 证书用 FTP 复制出来给客户端用。有几种 Android 配置还需要服务器证书(server.cert.pem)。
在很多的docker的说明中,我们都能看到“layer”的身影,那么到底什么是”layer“?
参见http://docker-doc.readthedocs.org/en/latest/terms/layer.html中的说明:
When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. We think of each one of these file systems as a layer.
简单翻译如下:
当docker加载rootfs时,和传统的linux系统中一样,它是只读的,但是随后,不是将当前文件系统变成可读写,而是利用union mount添加一个可读写的文件系统在当前的只读系统上。实际上将会有很多的只读文件系统叠加在彼此之上。我们将这里的每一层文件系统称之为"layer"。
参考阅读:
https://docs.docker.com/engine/understanding-docker/#how-does-a-docker-image-work
https://www.ctl.io/developers/blog/post/caching-docker-images/
docker好文,短小精炼。水平有限,请不吝指教。
http://developerblog.redhat.com/2016/02/24/10-things-to-avoid-in-docker-containers/
ps:为了保证一致性,文中的容器即container,是docker container的简称。
最终,你选择了容器技术并且发现它解决了很多问题并且有着很多的优点:
1. 第一:不可变更-因为OS,库文件,配置参数,文件夹,应用等都包含在容器中,所以只要你保证你生产环境中使用的是和QA一样的镜像,那么它的行为就一定是一样的。
2. 第二:轻量级-容器的内存占用很小。不需要成百上千MB,只需要为主进程分配数十MB的内存就可以。
3. 第三:运行超快-启动容器就像开启一个单进程,不需要几分钟,只要短短几秒就可以完成。
但是很多用户仍然将容器仅仅当作虚拟机使用,而另外的人仅仅知道:容器是一次性的,而忘记了它还有其他很多优点。
关于容器的口头禅:容器是短暂的。
这一特性“本身”迫使用户去改变他们关于如何处理和管理容器的想法。而我也将阐述为了获取最佳性能而需要避免做的事情:
1)不要在容器中存储数据-容器可以被停止,销毁,或者替换。一个1.0版的应用应该很容易的就被替换成1.1而不应有任何影响和数据丢失。基于这个原因,如果你需要存储数据,把它存储在宿主的硬盘上,但是要避免两个容器同时写数据,造成数据异常,确保你的应用是将数据写到共享的数据路径的。
2)不要把你的应用分成两部分-因为很多人把容器当虚拟机使用,所以他们的做法是部署应用到已经在运行的容器中。也许开发中确实如此,因为你要不间断的部署和调试,但是在正式的QA和生产环节流程中,你的应用应该是容器的一部分。请记住:容器应该是不可变更的。
3)不要创建过大的镜像-镜像过大不易分发。请确认你只包含了必要的文件和库,不要包含不必要的开发包,也不要在容器运行时运行"updates"(yum update)。
4)不要使用单层的镜像-合理的使用分层的文件系统,OS是一层,安全和用户定义组件是一层,库文件是一层,配置文件是一层,最后是你的应用独立为一层。这样将使镜像的重建和管理变的容易同时易于分发。
译者:这里的层指得是"layer",关于什么是"layer",请参见docker中的”layers”指的是什么东西
5)不要从运行的容器中创建镜像-换个说法,不要用"docker commit"去创建镜像。这样创建的镜像不可准确重建和版本化管理,应该彻底避免。要使用Dockerfile或者其他可重建的S2I(source to image)方式。
6)不要只使用最新标签的版本-最新的标签就想maven中的"SNAPSHOT"。应该使用特定的标签的版本。我想你应该不想在你2个月后重新编译镜像时,收到惊奇,发现你的应用不能运行是因为顶层的layer使用了新的版本,没有向前兼容或者最新的版本是有问题的。当部署容器到生产环境时也要避免使用新的版本。
7)不要在一个容器中运行多于1个的进程-容积最好是运行单一的进程(http守护进程,应用服务器,数据库)。当你运行多个时,你将会遇到要单独管理,处理日志,以及更新的困难。
8)不要存储身份数据到镜像中,尽量使用环境变量-你应该不希望直接存储你的用户名,密码到镜像中。所以使用容器外的环境变量去获取相关的信息,一个较好的例子是postres image。
9)请使用非root权限运行进程-“docker默认是以root身份运行的。当docker运行时,将会获取到默认的安全选项。而被他人获取root是危险的,并且也不是所有环境都支持的。你的镜像应该使用 USER 指令去指定一个非root用户来运行容器”(摘自Guidance for Docker image Authors)。
10)不要依赖特定的IP-每一个容器都有它们自己的内部ip,而且这个ip可能在开启或者停止时变化。假如你的应用或者微服务需要和其他的容器通讯,请使用名称或者环境变量去传递相关的信息。
更多关于容器的信息请参见:http://developers.redhat.com/containers/
hook是wordpress实现功能扩展的重要手段,详细的介绍:
hook functions is the important methods of extention of wordpress, reference to:
Plugin API
hook主要分两类:actions 和filters。
There have two catagory of hooks: actions add filters.
对应的注册函数分别为:add_action()和add_filter()。
目前支持的hook类型参见:
The details of hook cattagory refoerence to:
http://adambrown.info/p/wp_hooks
在模板的基础函数文件中(Modify the theme's style file):
/data/wp/wordpress/wp-content/themes/premium-style/functions.php
新增以下代码( Add some codes as bellow):
function publish_post_extra($post_ID){
// 1. init curl object
$ch = curl_init();
// 2. settings
curl_setopt($ch, CURLOPT_URL, "https://xxx" . $post_ID);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
// 3. execute the curl function
curl_exec($ch);
}
add_action('publish_post', 'publish_post_extra');
add_action('deleted_post', 'publish_post_extra');
以上的代码实现动作发生时, 通过curl访问一个特定url。
The uper codes show the publish and delete hook fuction that triger the specific http get request through the curl lib.
这两天开始学习docker,发现docker确实很强大,让网站部署和维护的效率大大提高。遂准备将手头维护的几个小站,全部docker化。整理的过程中感觉到,docker可以以功能或者进程为单位进行部署和维护,不用再花时间在繁琐的配置上面,但是docker和宿主之间的数据共享以及docker间的数据共享仍然是让人头疼和操心的地方。正好翻到官方文档,看到相关内容,遂决定翻译一下,水平有限,欢迎吐槽。
几个基本概念:
docker: 一种容器管理技术,这里也指既有的开发工具链。
container: 容器
image: 镜像
volum:卷 [译者:卷可以理解成计算机中的文件路径]
原文链接:Manage data in containers
翻译正文:
之前我们介绍了docker基本概念,学习了docker 镜像如何工作以及docker之间的网络和联系。这章节我们将继续讨论怎么在docker内和docker之间管理数据。
我们将着重讨论两种你所能管理docker数据的方式
数据卷是一种特殊的存在于一个或者多个docker内部的不同于Union File System的目录。数据卷提供多种有用的特性用来持久化和共享数据:
数据卷被设计用来持久化存储数据,独立于容器的生命周期。当你删除容器时,docker并不会自动删除数据卷,不使用的数据卷,也不会替你“垃圾回收”。
你可以通过 -v 标示在 docker create 和 docker run 命令中给容器增加一个数据卷。你可以多次使用 -v 增加多个数据卷。让我们给我们的web应用容器挂载一个单独的数据卷。
$ docker run -d -P --name web -v /webapp training/webapp python app.py
这条指令将会在容器内部的 /webapp 路径下创建一个新卷。
注意:你也可以使用 VOLUME 指令在 Dockerfile 文件中添加一个或者多个卷到容器中。
docker中的卷默认是读写权限,但你也可以设置为只读。
$ docker run -d -P --name web -v /opt/webapp:ro training/webapp python app.py
你可以使用 ‘docker inspect’ 指令来查看一个卷。
$ docker inspect web
输出将会提供详细的容器配置和卷信息。输出格式类似如下:
Mounts": [ { "Name": "fac362...80535", "Source": "/var/lib/docker/volumes/fac362...80535/_data", "Destination": "/webapp", "Driver": "local", "Mode": "", "RW": true } ]
你将看到‘Source’表示的是宿主路径,‘Destination’表示的是容器路径。 RW 用来标示这个卷的读写属性。
通过 -v 标示你可以挂载一个宿主目录到容器中。
$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
这条命令将宿主的 /src/webapp 挂载到容器的 /opt/webapp 卷上。如果 /opt/webapp 已经存在,/src/webapp 将会覆盖但是不会移除已有的文件。当挂载的卷移除后,原先被覆盖的内容将可以再次使用。这个和mount的行为是一致的。
container-dir 必须是绝对路径,比如 /src/docs。host-dir可以是绝对路径,也可以是一个已经声明过的数据卷。如果你指定host-dir为绝对路径,docker将会按你指定的路径挂载,如果你提供的是一个声明的卷,docker将会按照name 指定的名称创建一个声明的卷。
一个 name 声明的卷必须以字母开头,后面跟随z-z0-9,_,. 或者 -。绝对路径都以 / 开始。
例如,你可以用/foo 或者 foo 作为一个 host-dir.如果你使用 /foo ,docker 创建一个挂载点。如果你使用 foo, docker 创建一个声明的卷。
如果你在 Mac 或者 Windows 上使用 docker,你的docker后台只能拥有有限的权限。docker尝试着自动分享你的 /User 或者 C:\Users 目录,所以在OS X上挂载如下:
docker run -v /Users/<path>:/<container path> ...
windows上如下:
docker run -v /c/Users/<path>:/<container path> ...
其他来自虚拟机的目录,比如你想共享virtualbox 中的某些目录,你需要做些额外的工作。在 virtualbox下,你先要使宿主的目录变成共享,然后才能使用 -v 来挂载。
挂载宿主的目录对测试来说很有用。比如你可以在容器中挂载源码,然后修改代码,实时看修改后的执行效果。宿主的路径必须是绝对路径,如果路径不存在,docker就会在本地创建它。这种 auto-creation 将会被移除。
这里我们仍然挂载 /src/webapp 目录,但是增加了ro选项来声明挂载的目录是只读的。
$ docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py
注意:宿主目录是主机相关的,所以你不能在Dockerfile中挂载一个宿主目录,因为镜像要可移植,而不同的主机有不同的目录结构。
Labeling 系统例如 SELinux 要求数据卷被容器挂载时要标示。如果没有标示,安全系统可能会阻止容器内的进程访问卷的内容。默认情况下,docker不会改变操作系统的卷标识。
要在容器的上下文中修改卷标识,你需要在挂载时增加 :z 或者 :Z 标识。z 表示多个容器共享卷内容,所以docke用共享标识来标示卷内容,共享的标识允许多个容器读写内容。Z 表示docker用私有的标识来标示卷内容,所以只有当前的容器能访问这个私有的卷内容。
-v 也可以用来挂载一个单独的文件而不仅仅是目录:
$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
这个指令将会让你进入容器的命令行,能获取宿主的历史纪录,并且退出时,宿主的历史记录能纪录容器的指令操作。
注意:许多编辑工具包括 vi ,sed --in-place 等可能会导致inode数据结构变更。自从docker1.1.0后,此类操作会导致" sed:cannot rename ./sedKdj9Dy:Device or resource busy"。[In the case where you want to edit the mounted file, it is often easiest to instead mount the parent directory.][译者:这句不是很明白什么意思,望看到的网友指点]
如果你有一些希望分享给多个容器的持久化数据,或者想从 non-persistent 容器中使用这些数据,最好的办法是创建一个命名的数据卷容器,然后从从容器中挂载使用数据。
让我们创建一个共享数据卷的容器。这个容器不运行应用,它提供 training/postgres 镜像,这样所有的容器都共用统一的接口,从而节省空间。
$ docker create -v /dbdata --name dbdata training/postgres /bin/true
你可以在其他的容器中用 --volumes-from 标示来挂载 /dbdata 卷。
$ docker run -d --volumes-from dbdata --name db1 training/postgres
和
$ docker run -d --volumes-from dbdata --name db2 training/postgres
这个例子里,如果 postgres 镜像已经包含一个叫做 /dbdata 的目录,将会隐藏这个目录,只有挂载的可见。
你可以多次使用 --volumes-from 从多个容器中挂载多个卷。
你也可以用 db1 db2 来引用 dbdata。
$ docker run -d --name db3 --volumes-from db1 training/postgres
如果你删除挂载了卷的容器,包括初始的dbdata 或者子序列的 db1 db2等,这些卷将不会被删除。如果你要删除卷,你需要明确的调用 docker rm -v,这个操作可以让你去在容器之间更新,或者高效的迁移数据。
注意:当你删除一个容器不带 -v 时,docker不会警告提醒你。当你不带 -v 删除容器时,将会出现‘挂起’的数据卷,这些卷不再被容器引用。‘挂起’的卷很难避免,并且占用空间。我们在尽力提升卷管理功能,参见pull request #14214
数据卷的另外一个有用的功能是用来备份,恢复和迁移数据。我们使用 --volumes-from 来创建一个新容器并挂载数据卷:
$ docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
示例中我们启动了一个新容器并且从dbdata 容器挂载了数据卷。我们把宿主本地路径挂载成 /backup.最后,我们用tar命令将dbdata数据卷备份进backup.tar,并存入 /backup目录。当命令结束时,我们将在本地目录下得到一个dbdata的备份。
你可以用它来恢复到之前备份的容器里,或者其他的容器:
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后 un-tar 备份的文件到新的容器数据卷中:
$ docker run --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar"
你可以使用上面的方法来自动化地备份迁移和恢复数据。
多个容器可以共享一个或者多个数据卷,但是同时写入的时候会发生冲突。
数据卷在宿主里面是可以直接操作的。你可以使用普通的linux工具操作它们。但是建议你不要这样直接做,因为容器和应用并不知道你的操作,这可能会导致数据操作冲突。
我们学习了很多关于怎么使用docker,接下来我们将看到怎么将docker和Docker Hub上的服务例如自动编译,创建私有仓库等结合起来使用。
Go to Working with Docker Hub
完!
译者:本文中的部分命令参数是过时或者错误的,但这些可以忽略,并不影响我们理解指令的正确用法。
最近开始做docker相关的学习和技术准备,准备将目前的一些基础服务,通过docker做同构或者异构分布式调整,提升运维效率和系统稳定性。
我的系统:
Linux chicago1 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2 x86_64 GNU/Linux
Docker要求Kernel 3.8+,幸运的是, wheezy-backports 目前有Kernel 3.16 , 该版本正式支持Docker。
在文件 /etc/apt/sources.list中添加如下行
deb http://http.debian.net/debian wheezy-backports main
然后安装linux-image-amd64包 (注意使用 -t wheezy-backports)
sudo apt-get update
sudo apt-get install -t wheezy-backports linux-image-amd64
使用get.docker.com 的脚本:
curl -sSL https://get.docker.com/ | sh
为了卸载Docker包:
$ sudo apt-get purge lxc-docker
为了永久卸载Docker及其依赖包,你应该这样:
$ sudo apt-get autoremove --purge lxc-docker
命令将不会移除镜像,容器,数据卷,或者用户创建的配置文件。如果你希望删除所有镜像,容器,数据卷 ,运行如下命令:
$ rm -rf /var/lib/docker
你必须手动删除用户创建的配置项。
网站已经迁移了一个多月,一直想写下,但是因为一个issue的问题,一直不爽快:
the tag format
一直想等待解决再来写。
周末抽空过了一遍代码,代码中是用spyc来生成yaml的。改成[xx, x] 的格式还是要费点神的,而且破坏了原来格式的简单优美,什么意思?看下两种格式的生成就明白了,前者是不用考虑长度的迭代模式,后者要考虑长度,因为要在结尾加后括号']',这样逻辑就不是简单流式的了。为了确认是否值得修改,确认了官方的文档:
yaml官方文档
发现2种格式都是支持的,但是hugo的问题是:
文档的tags和categories本质来讲,都是列表数组,没有道理两种采用不同的格式,详情:
the tag format advice
显然关闭的人并没有理解我的意思,但是还是有其他的开发者明白了我的意思,做了回复,总之此问题目前确认是属于hugo的“不优雅”。不打算勉强,为了修复而修复,静待hugo的变化吧。
hugo是一个能把markdown转化成静态html网站的工具。
说了这么多,言归正传,一键切换主要是使用这个插件:
wordpress-to-hugo-exporter
这个插件功能是通过提取wp的页面,将所有的可见页面转换成markdown文档。
支持两种方式:
1. 在wp插件页面通过按钮执行
2. 在后台命令行通过cli方式执行:
php hugo-export-cli.php
前者的文件会导出到用户客户端,后者生成的.zip在/tmp目录下。
这个插件只是将wp的内容转化成markdown文档,要创建hugo网站,你需要:
拿到插件时,是不支持中文路径的,含有中文路径的文章,都是404。这个对大陆用户来说很不方便的,因为有很多人的文章都是有中文路径的。于是提交了对应的PR:
fix the unicode url issue and markdown format error
作者很勤快,很快就合入了主干,所以现在大家可以直接使用主干的代码,就是支持中文了。