折腾记录:将wordpress搬家到腾讯云

由于腾讯云有学生计划,每个月可以有50块的代金券,于是我就愉快地用上了腾讯云的服务器。本来迁移一个wordpress应该是很简单的事情,居然被我折腾了一天!!!整整一天!!所以,还是记录一下吧。

想象中的迁移其实相当简单啊,由于先前已经把apache、php模块、mysql都装好了,只要把数据库和网站文件复制过来,然后改一下wp-config.php就行啦。但没想到的是,由于版本的不一致和权限的问题,我踩了不少坑。

第一坑:mysql版本不一致

在腾讯云,我的系统是centos6.7,mysql是通过yum安装的,看看版本:

rpm -qa | grep mysql

mysql版本

5.1版本的,而我在另外在另外一台服务器上面的mysql是5.6版本的,所以,当我想愉快的用navicat-for-mysql来进行数据传输的时候,出现了编码错误,无法传输。高版本的mysql有这样的排序规则:utf8mb4_unicode_ci,低版本的没有。

所以,我只能去踩第二个坑了。

第二坑:不能直接把数据库搬过来

踩完第一坑,想着说,既然不能这么传输数据库,那我就直接导出sql,然后在新的数据库执行就好了。

导出、导入完毕,然后上传wordpress文件到服务器,更改wp-config.php中的数据库配置。然后配置虚拟主机,重启apache,一切正常。

浏览器输入ip来访问。居然重定向到apache的默认页面去了。很明显,数据库根本连接不了。。

最后的解决方法是,老老实实的,先不导入数据库,让wordpress自己完成安装,把默认的表都建齐了,然后把默认的数据给删掉,最后把之前导出的sql文件里的insert语句重新执行一遍,相当于重新写数据了。

第三坑:固定链接与.htaccess文件

网站的url设计用的是域名+文章名,这个可以在wordpress后台的“固定链接”里面设置。但是我设置了之后,发现居然只有“朴素”模式可以用,采用别的固定链接,都会404。

搜索引擎和wordpress都告诉我,是.htaccess文件的问题。

wordpress的.htaccess文件

于是我在网站根目录下新建了一个.htaccess文件,把它告诉我要填写的内容写进去了,保存。

vim .htaccess

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

然后,在apache的virtual host配置里,加了以下设置,使.htaccess生效:

<Directory “/mypath/wordpress”>
AllowOverride ALL
Order allow,deny
Allow from all
</Directory>

其中,AllowOverride ALL是一定要加的,这个代表使用.htaccess的策略。

但是,问题出现了,加了这个配置之后,图片、css、js等静态文件访问不了了。

经过好久好久的测试,千言万语可以通过以下一行命令解决:

将路径先切换到wordpress网站根目录,然后

chown -R apache:apache ./*

把所有文件的拥有者改成apache,把所属的组改成apache,这样apache就有权限了。这也直接能解决第四个坑

第四坑:在线更新wordpress出错

无论是升级wordpress还是升级插件,总是会出现权限错误,都不成功。

都是权限不足!如果你够暴力,直接全部777权限,解决,但不建议这么做。我最终还是选择了把网站的owner和group都改成了apache,正如坑三所提到的那样。

总结

权限问题!权限问题!权限问题!

这个问题在我配置网站的时候经常有,次次有,所以一定要把系统的各种权限搞懂,不要每次都用root去倒腾一些东西,得不偿失!要建立起良好的权限管理的习惯。

这篇写的思路比较混乱,之后再把之前配置整个服务器的过程记录一下。

10-fold CV是什么意思

今天在看《Convolutional Neural Networks for Sentence Classification》这篇论文的时候,在实验部分看到了这样的一个表格(摘取两行数据):

Data c l N |V| |Vpre| Test
MR 2 20 10662 18765 16448 CV
SST-1 5 18 11855 17836 16262 2210

关于表头,论文给出了注释:

c: Number of target classes. l: Average sentence length.
N: Dataset size.
|V|: Vocabulary size.
|Vpre|: Number ofwords present in the set of pre-trained word vectors.
Test:Test set size (CV means there was no standard train/test splitand thus 10-fold CV was used).

关于最后的一个Test,即测试数据集,说是由于没有标准的测试集,所以用一个10-fold CV来代替。

那这个10-fold CV到底是什么来的。

查了下资料,10-fold CV也就是10-fold cross-validation,是一种交叉验证的方法,最简单的解释就是,将数据集分成10份,轮流将其中9份用于训练,1份用于测试,循环10次,求最终准确度的平均值。

依此类推,k-fold CV亦是如此。

所以我下载的http://www.cs.cornell.edu/people/pabo/movie-review-data/rt-polaritydata.tar.gz 这个数据集,由于没有验证测试集,所以就用10-fold CV 这种方法来做了。

python的map函数的用法

作为python的常用内置函数之一,map函数在某些场景解决问题确实方便,今天就整理一下map函数的用法。

函数官方解释

def map(function, sequence, *sequence_1): # real signature unknown; restored from __doc__
“””
map(function, sequence[, sequence, …]) -> list

Return a list of the results of applying the function to the items of
the argument sequence(s). If more than one sequence is given, the
function is called with an argument list consisting of the corresponding
item of each sequence, substituting None for missing values when not all
sequences have the same length. If the function is None, return a list of
the items of the sequence (or a list of tuples if more than one sequence).
“””
return []

看上去还是挺好理解的,加上一些例子就没问题了。

参数

function:一个函数

Sequence:列表

*sequence_1:多个列表

返回值

一个列表list

作用

①传入一个函数,一个列表的情况

将函数作用于列表中的每一个元素,最终返回作用后的结果列表。

相当于[function(x) for x in sequence]

②传入一个函数,多个列表的情况

取不同列表相同位置的元素,传入函数中进行处理,最终返回作用后的结果列表。

例子

①传入一个函数,一个列表的情况

上代码:

list1 = [1, 2, 3, 4]
def incre(x):
    return x+1
result_list = map(incre,list1)
print result_list

输出结果为[2, 3, 4, 5]

②结合匿名函数lambda使用

以下代码的效果和例子①是一样的:

list1 = [1, 2, 3, 4]
result_list = map(lambda x:x+1,list1)
print result_list

lambda函数,这是python的匿名函数,这里先不多说了。

③传入一个函数,多个列表的情况

先上代码:

list1 = [1, 2, 3, 4]
list2 = [2, 3, 4, 5]
list3 = [3, 4, 5, 6]
def addition(x,y,z):
    return x+y+z
result_list = map(addition,list1,list2,list3)
print result_list

输出结果是[6, 9, 12, 15]

看数字,可以感觉得出来,6=1+2+3,9=2+3+4,12=3+4+5,15=4+5+6,这个时候再看看我在上面的解释:

取不同列表相同位置的元素,传入函数中进行处理,最终返回作用后的结果列表

就比较好理解了,这相当于并行处理。

这里要注意两点:

1.传入的列表(或元组)的数目,要和函数参数的数目一致,比如例子③里面函数addition就需要三个参数,这个时候得传三个列表进去。

2.不同列表的长度要一致,且对应元素的类型要相同。

④传入None

这种情况,直接传入None作为函数,看代码:

list1 = [1, 2, 3, 4]
list2 = [2, 3, 4, 5]
result_list = map(None, list1)
print result_list
#输出结果:[1, 2, 3, 4]
result_list = map(None, list1, list2)
print result_list
#输出结果:[(1, 2), (2, 3), (3, 4), (4, 5)]

如果只传一个列表进去,那就原封不动的返回,如果传多个列表,则效果和zip()函数是一样的,返回一个大列表,里面是多个列表相同位置元素组合出来的元组。

python的切片(slice)机制

在python编程中,我们经常要取list或者tuple里面的元素,或者对字符串进行处理,这恰恰也是python的一个闪光点,它的切片(slice)机制,使得我们处理这类问题变得简单灵活。

“切片”是针对列表(list)、元组(tuple)的,另外,字符串也可以当作特殊的list,通过切片,可以很轻易的实现截取字符串、反转字符串的操作。

所谓的切片,就是按照你的规则,将一个列表切成另外一个列表,先来直观感受一下。

list = ["lookfor404","lipengfei","hello","what"]
list1 =list[0:2:2]
print list1

你猜输出什么?输出了一个新的列表['lookfor404']

假如是这样呢?又会输出什么?

list = ["lookfor404","lipengfei","hello","what"]
list1 =list[0:2:1]
print list1

答案是['lookfor404', 'lipengfei']

现在就来解释一下。切片的使用就是这么简单,在一个list后面加个中括号,里面有两个冒号,插空有3个参数。

list[first_index:last_index:step]

这个表示,从这个list的first_index开始,到last_index结束(不包括last_index本身),以step步长来截取这个list

回到刚才的例子,由于list = ["lookfor404","lipengfei","hello","what"],这个list有4个元素,而list1 =list[0:2:2]表示的是,从list的第0个元素(lookfor404)开始,到第2个元素(hello)结束,以步长2来截取list,这里要注意的是,前两个参数0和2,在数学上是个半闭半开的区间:[0,2)。所以,很自然的,可以得到list1的结果就是['lookfor404']

当然,并不是一定要用两个冒号,如果只使用了一个冒号,就意味着步长默认为1。以上是常规用法,下面拓展一下,其实它很强大,所以python不需要一些字符串的截取函数了。

比如————
复制list,可以直接这样

list = ["lookfor404","lipengfei","hello","what"]
list1 =list[:]

list1就复制了list的内容过来了,因为冒号两边不填参数的话,就默认从0到最后一个元素(包括最后一个元素)。

再比如————
反转字符串,可以这样

str = "helloworld"
str1 =str[::-1]

此时输出str1就是'dlrowolleh'。原因在于步长参数,我们选择了负数,没错,负数就表示反着来,-1表示倒序,-2表示隔着步长2倒序,也就是说,如果str1 =str[::-2],那么输出str1为'drwle'

最后对边界进行一个总结,直接上代码:

s = ["a","b","c","d"]       # s的上界为0,下界为 4(事实上,最后一个元素的索引为3,但这里称4为下界)
s[-100:100]       #返回 [1,2,3,4] :-100超出了上界,100超出了下界:等价于 s[0:4]
s[-100:-200]      #返回 [] :-100,-200均超出了上界,自动取上界:等价于s[0:0]
s[100:200]        #返回 [] :100,200均超出了下界,自动取下界值:等价于s[4:4]
s[:100]           #返回 [1,2,3,4] :开始值省略表示从第0个开始,等价于s[0:4]
s[0:]             #返回 [1,2,3,4] :结束值为空表示到最后一个结束,等价于s[0:4]

运行ggplot出现问题:no display name and no $DISPLAY environment variable

最近在用django做一个项目,关于数据可视化的。作图方面,之前用过百度的echart,这个是在前端直接调用的,这次想尝试在后台直接生成图,然后存在服务器上,之后前端再把图片显示出来就好了。

用的ggplot。

在windows下,用runserver测试,没问题。但是在服务器上,就跑不了了,出现了这样的提示:

tkinter.TclError: no display name and no $DISPLAY environment variable

查看了一下debug信息,发现貌似和Matplotlib有关,继续顺藤摸瓜。

找到了问题所在:http://matplotlib.org/faq/howto_faq.html#howto-webapp

官网的英文解释:

Many users report initial problems trying to use maptlotlib in web application servers, because by default matplotlib ships configured to work with a graphical user interface which may require an X11 connection. Since many barebones application servers do not have X11 enabled, you may get errors if you don’t configure matplotlib for use in these environments. Most importantly, you need to decide what kinds of images you want to generate (PNG, PDF, SVG) and configure the appropriate default backend. For 99% of users, this will be the Agg backend, which uses the C++ antigrain rendering engine to make nice PNGs

不想读完也没关系,大概说下怎么回事。

不同的系统有不同的用户图形接口,默认的接口在windows下跑是没有问题的,问题是我们很多的webapp都不在windows上跑,一般在linux上面,所以要更改它的默认配置,把模式更改成Agg。

纯代码解决方案

这也是大部分人在网上诸如stackoverflow的问答平台得到的解决方案,在引入pyplot、pylab之前,要先更改matplotlib的后端模式为”Agg”。直接贴代码吧!

# do this before importing pylab or pyplot
Import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot asplt

更改配置文件方案

就我的情况而言,上面那种解决方案似乎不适用,因为我是在django中使用的ggplot,它调用matplotlib的时机,我并不是很清楚。所以试了几次,都没有能把matplotlib.use('Agg')这句代码放在正确的位置上,因而也解决不了错误。

所以我转向了另一种解决方案,也是从官网启发而来。

好了,这里告诉我们,什么是backend:

http://matplotlib.org/faq/usage_faq.html#what-is-a-backend

然后这里告诉我们,怎么改配置文件:

http://matplotlib.org/users/customizing.html#customizing-matplotlib

看到下面这个地方:

matplotlibrc文件

没错,它的配置文件就是matplotlibrc,在哪里呢?不同系统不一样,我的系统是ubuntu,运行了命令whereis matlotlibrc,找到了。

matplotlibrc文件位置

编辑一下:

sudo vim /etc/matplotlibrc

找到backend这里,然后将其改成Agg,如下!

# The default backend; one of GTK GTKAgg GTKCairo GTK3Agg GTK3Cairo
# CocoaAgg MacOSX Qt4Agg Qt5Agg TkAgg WX WXAgg Agg Cairo GDK PS PDF SVG
# Template.
# You can also deploy your own backend outside of matplotlib by
# referring to the module name (which must be in the PYTHONPATH) as
# ‘module://my_backend’.
backend : Agg

保存,运行,错误消失。

在linux服务器上部署django项目

不得不承认,django自带的runserver功能确实强大,使得我们在开发的过程中可以轻松的在本地调试、查看网站。但开发是开发,做的项目总归是要部署到服务器上面去的,最近把项目部署到linux上了,这里记录一下。

官方文档:https://docs.djangoproject.com/en/1.9/howto/deployment/

我是参照着文档部署的。下面是我的环境:

ubuntu14.04.3
python2.7.6
apache2.4.7
django1.9.7
mod_wsgi4.5.3

接下来进入配置环节。

安装python-dev

默认情况下,ubuntu系统是安装了python的,不过如果只用这个python,在后面的部署过程就会出问题,先查看你的python版本,不出意外的话是2.7.x,然后额外安装一个对应的dev版。

apt-get install python2.7-dev

安装django

这个很简单,直接pip安装就行,选择好你要的版本。

pip install Django==1.9.7

安装python的mysql驱动

如果你的数据库用的是mysql,还得安装这个。

sudo apt-get install python-mysqldb

安装Apache

在ubuntu系统上,Apache是预装了的,但是它不支持apxs的,对于之后要安装的wsgi组件来说,apxs是必须的。还得安装一个Apache的dev版。先确认你已经安装的Apache版本,我的是Apache2,所以直接运行以下命令继续安装dev版:

sudo apt-get install apache2-dev

安装编译mod_wsgi

有了上述的准备工作之后,安装mod_wsgi就不是什么问题了。

这个是官方文档:https://modwsgi.readthedocs.io/en/develop/user-guides/quick-installation-guide.html

我记录一下我安装编译的步骤。

先去下载源代码:https://github.com/GrahamDumpleton/mod_wsgi/releases

我下载的是mod_wsgi-4.5.3.tar.gz。

然后上传到服务器,解压:

tar xvfz mod_wsgi-X.Y.tar.gz

PS:X,Y为你实际的文件版本,跟文件名一致即可。

解压之后,cd到对应的目录。然后运行

./configure

./configure命令
然后继续运行:

make

最后运行(PS:这一步是需要管理员权限的):

sudo make install

安装成功:
mod_wsgi安装成功
注意图片的第一行,说的是mod_wsgi安装的路径;还有最后一行,要给mod_wsgi.so加上对应的权限。

sudo chmod 644 /usr/lib/apache2/modules/mod_wsgi.so

配置mod_wsgi到Apache上

安装成功之后,要更改一下Apache的配置文件。编辑(不同系统下Apache配置文件不一样,有的是httpd.conf)

sudo vim /etc/apache2/apache2.conf

在文件的最后一行,加上
LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so
其中第三个参数,是刚才安装完的mod_wsgi.so对应的路径。

部署django项目

django项目刚开始的时候,我们一般都是运行startproject命令来生成项目,这样做有一个好处,django会帮我们自动生成wsgi的配置文件。

首先把本地的django项目复制到服务器上,一般是/var/www/html下,以你Apache的配置为准。

然后我们继续编辑Apache的配置文件:

sudo vim /etc/apache2/apache2.conf

在最后,添加如下内容:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

Require all granted< /Files>

要注意,/path/to/mysite.com/ 这个路径不要搞错,就是你项目的路径。

配置完毕,重启Apache。

sudo apachectl restart

访问网站
直接输入ip地址访问网站,发现访问不了,查看了一下Apache的error log:

from django.core.wsgi import get_wsgi_application
ImportError: No module named ‘django.core.wsgi’

后来发现,原来是权限问题,无法执行django里面的文件。心累。。

加个权限就行了。

cd /usr/local/lib/python2.7/dist-package
sudo chmod a+x django

ok,项目就这么部署完毕了,如果你是正式的项目,记得把django的debug模式关掉。

WinSCP上传文件出错解决方法

在用WinSCP上传本地文件到/var/www的时候,出现了一个错误:

Permission denied.
Error code: 3
Error message from server: Permission denied

很明显,权限错误。

也就是说,我登陆的这个账号,不能往这个文件夹里面写东西。解决方法也有很多种,无非就是更改权限,或者更改文件归属了。

最暴力的方法:

sudo chmod 777 -R /var/www

其中,-R代表www下的子文件的权限也被更改
或者可以更改文件夹的归属:

sudo chown -R username /var/www/

其中username更改为你登陆WinSCP的用户名即可。

问题是解决了,但是以上方法并不是最好的方法,最好的方法是要根据自己服务器的安全策略,然后给文件夹设定对应的权限,这就涉及到linux的跟权限有关的知识了,这里也整理一下。

文件权限

以以下这个文件为例:

drwxrwxr-x 2 ubuntu ubuntu 4.0K Jul 26 11:58 testdir

一个一个解释。

drwxrwxr-x:有10个字母,第一个字母代表文件的类型,-代表文件,d代表文件夹,l代表链接;剩下9个字母,三个字母分为一组,共有三组。第一组代表文件所有者的相应权限,第二组代表与文件所有者同一组的用户的相应权限,第三组代表其他用户的权限。r代表读权限,w代表写权限,x代表执行权限。

2:代表链接的文件数,有2个。

ubuntu:文件所有者

第二个ubuntu:文件所有者所在组

再后面就是时间和文件名了。

更改文件权限

更改文件权限的基本命令是chmod,这里抛出一个规定,那就是每种权限对应一个数字:r=4,w=2,x=1,所以rwx可以表示为7(4+2+1),rw-可以表示为6(4+2),就是简单的加法。有了这个规定,我们来看命令就很明白了。

chmod 751 abc:赋予abc权限rwxr-x–x

chmod u=rwx,g=rx,o=x abc:同上,u=用户权限,g=组权限,o=不同组其他用户权限

chmod u-x,g+w abc:给abc去除用户执行的权限,增加组写的权限,减号代表去除权限,加号代表增加权限

chmod a+r abc:a代表所有用户,这里是给所有用户添加读的权限

chmod a=rwx abc:这条命令等价于chmod 777 abc

在windows下用ppk后缀文件登陆远程服务器

最近要部署一个项目到服务器上,对方给我生成了一个以ppk为后缀名的密钥,让我直接登陆,这里记录一下过程。

用putty通过ssh登陆服务器

下载putty

貌似官网上不了。我是在这里下载的:

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

下载putty.exe,不用安装。

连接服务器

打开putty,在host name那里填写服务器地址,登录方式默认就行了。

putty登陆服务器

在左边栏打开选择SSH,找到AUTH,然后Browse你的ppk授权文件,点击open。

导入ppk授权文件

然后输入ppk授权文件对应的linux用户名,即可登陆成功,如下:

putty登陆成功

用WinScp登陆文件服务器

WinScp给了我们图形化的操作界面,允许我们从windows直接拖拽文件到服务器上,非常方便。这里记录下怎么用ppk文件来登陆。

下载、安装WinScp

下载地址:http://winscp.net/eng/download.php

安装过程可以选择语言,默认是中文,我选择的是英文。

使用ppk文件登录

打开软件,在Host name填写服务器地址,Port number默认22即可,User name填写用户名。然后点击下面的advanced选项。

打开winscp

然后选择ssh下的authentication,在private key file选择授权文件(即你的ppk后缀名文件)即可。

winscp选择授权文件

点击ok,然后回到第一个界面,login就行了。

登录成功,可以直接拖拽文件实现上传下载了。

winscp登陆成功

即使走到了 有个裂口

写下这个标题的时候,我打开了昨天晚上录的视频–我当然发给了我的损友,我也确认无误,eason唱的是“即使走到了 有个裂口”。

对于我这种不怎么会维系友情的人,演唱会成为了我们三个见面的理由。

我一边吃着薯条,一边回忆起几年前五月天的演唱会。好学说,“哈哈哈这么多年我们居然没有友尽”。“哈哈哈我也觉得好神奇。”大概每个人都有痛苦的日子,但都会挺过来。慢慢慢慢的肚子里能装得下越来越多的苦水。

回到演唱会现场,时间关系,今晚的encore环节就直接没有了,哦不是没有encore,而是直接唱下去。听到了最佳损友和与我常在。值了!可是李荣浩你是出来干嘛的,还以为你要来陈奕迅演唱会唱薛之谦的歌。

在一起会有多美
在一起也会不美
一个人,同偕到老不靠运气

2016-07-17 203237

那么,9月五月天见!

初中的这个四人小组,也是神奇。要等某个人从法国回来,我们就能聚上一次,其他三个人,懒的懒,宅的宅,读书的读书,上班的上班。这些破借口虽然不成立,但是也是一种说法。

只不过当我们听到法国学子说到关于“30岁”的故事之后,有点笑不出来。“呸呸呸”,“童言无忌”!

说到底,我们还是存在着那么一份一起去普罗旺斯逛逛的可能性的,退一万步,每年吃一次辣辣的火锅不过分吧。

和滨哥和初中生打球是一件有趣的事,不过令人生气的是,他也会被气坏。

做过两次梦,一次你弱的像小孩,一次你说你好了,不疼了。

可能你也熬过去了。

我们这边也步入了正轨,你还担心什么呢。时间其实也没过去多少,它不是治愈了我,而是安排了很多事情填补了我的空隙。

最近的思绪就和以上文字一样,毫无章法。谁叫我,字都快不会写了。