Let’s Encrypt SSL证书

生成

yum install epel-release -y
yum install certbot -y


certbot certonly --webroot -w /home/wwwroot/bt.wktadmin.com -d bt.wktadmin.com -m [email protected] --agree-tos
****

nginx 配置


upstream tornadoes { server 127.0.0.1:8000; server 127.0.0.1:8002; } server { listen 80; server_name bt.wktadmin.com; return 301 https://bt.wktadmin.com$request_uri; } server { listen 443; server_name bt.wktadmin.com; ssl_certificate /etc/letsencrypt/live/bt.wktadmin.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/bt.wktadmin.com/privkey.pem; location /static { root /root/tools/tornado; autoindex on; } location /.well-known { root /home/wwwroot/bt.wktadmin.com; autoindex on; } location / { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; # 把请求方向代理传给tornado服务器,负载均衡 proxy_pass http://tornadoes; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }

自动更新

30 2 * */2 * /usr/bin/certbot renew --quiet && /bin/systemctl restart nginx

详细:
https://juejin.im/entry/5b59c3f26fb9a04fda4e2238

scrapy爬虫部署(scrapy管理)


常用:

  • 开启:
curl https:///schedule.json -d project=default -d spider=btspider
  • 本次开启使用
curl https://blog.wktadmin.com/scrapyd/schedule.json  -d project=default -d spider=btspider
  • 关闭
 curl https://blog.wktadmin.com/scrapyd/cancel.json -d   project=default -d job=284a5496078d11e98a7df6afa62feb35

  • 列表
curl https://blog.wktadmin.com/scrapyd/listspiders.json?project=default

mysql如何支持emoji/原文: mysql数据库中utf8与utf8mb4的区别:记一次sqlalchemy的InternalError

遇到的问题
使用sqlalchemy执行下面语句的时候包错了。

insert into datasource value('YnWZ8Q4928ruM4z63I+9IQ==','','盖乐世社区','S8','刚刚看到一个贴,特搞笑。这头说完下面就有人评论打脸了😂    bixby不说最好,但怎么说也是在现有的语音技术基础上面提升一大步。(注意:现有的技术基础提升)真的搜不出来的话可能也许大概是输入的命令不对而已,可以换一句话试一试嘛。都说了bixby更人性化一点,肯定跟其他的不一样的嘛。当然,所有的语音都不说最好的,还有待提升。    好了,屁话不多说,回到我们图上这位小哥,估计是果粉,然后尝新鲜买了个s8。但还是偏向iPhone吧应该,然后一肚子火跑来撒气。但是!!我们看到评论这边,哈哈哈,秒打脸','2017-12-14','负向','http://www.galaxyclub.cn/thread-445992-4-61.html')

错误类型是InternalError,错误信息

sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1366, "Incorrect string value: '\\xF0\\x9F\\x98\\x82\\x09b...' for column 'content' at row 1") [SQL: "insert into datasource value('YnWZ8Q4928ruM4z63I+9IQ==','','盖乐世社区','S8','刚刚看到一个贴,特搞笑。这头说完下面就有人评论打脸了😂\tbixby不说最好,但怎么说也是在现有的语音技术基础上面提升一大步。(注意:现有的技术基础提升)真的搜不出来的话可能也许大概是输入的命令不对而已,可以换一句话试一试嘛。都说了bixby更人性化一点,肯定跟其他的不一样的嘛。当然,所有的语音都不说最好的,还有待提升。\t好了,屁话不多说,回到我们图上这位小哥,估计是果粉,然后尝新鲜买了个s8。但还是偏向iPhone吧应该,然后一肚子火跑来撒气。但是!!我们看到评论这边,哈哈哈,秒打脸','2017-12-14','负向','http://www.galaxyclub.cn/thread-445992-4-61.html')"]

按照之前的经验,百分之八十问题是出在这个贱贱的表情上。复查下整个连接、建表中的数据。

  • 链路上的字符集设置

1 链接引擎

engine = create_engine("mysql+pymysql://root:[email protected]:3306/bi_bigeye?charset=utf8")

2 建表

create table if not exists datasource_type( siteName varchar(20) primary key, field varchar(10) ,scope varchar(10)) Default charset='utf8'

从整个链路上看,已经使用了utf8字符集了,理论上不应该出现emoji表情无法存储的情况了。

峰回路转

网上查了篇文档也是说吧字符集设置称为utf8mb4就可以了,为什么我这还报错。。。等等,为什么mb4是什么?

这一查才知道,原来mysql中utf8字符也藏了这么复杂的坑。

utf8这种是一种变长编码方法,也就是说到使用1到4个字节来表示一个字符。但是在mysql中的utf8却最多只能存储3个字节所表示的字符,也只能支持0x0000到0xFFFF的字符串,也就是Basic Muiltilingual Plane所规划的范围,而这个范围是不包含emoji的,所以在碰到这个贱贱表情是hold不住报错了。

解决问题

既然是使用字符串的问题,那么修改下相关的字符串编码即可。对于连接引擎来说,解决起来还是很简单的,将utf8替换成utf8mb4即可,对于数据库而言已经存储了不少内容,自然无法删掉重建。这时候就需要使用平时很少用到的ALTER语法。

ALTER TABLE `datasource` DEFAULT CHARACTER SET utf8mb4 ; # 更改表的编码,不影响各个字段的编码

alter table datasource convert to character set utf8mb4;  # 更改表的编码,删除各个字段的编码

通过show create table targetTable查看各个字段的编码,更改了之后问题也就消除了。

小结

在这个过程中,了解了在mysql环境下使用utf8编码还是不够的,而要使用utf8mb4;并且学习了使用alter 更改数据库的字符集的方法。

原文

http://zhouchen.tech/2018/03/15/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%ADutf8%E4%B8%8Eutf8mb4%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%9A%E8%AE%B0%E4%B8%80%E6%AC%A1sqlalchemy%E7%9A%84InternalError/

mysql 忘记密码重置密码和修改密码

Linux下MySQL重置密码

Linux下重置密码的操作与Windows下类似。

停止MySQL服务

[[email protected] ~]# /etc/init.d/mysql stop

以安全模式启动MySQL

[[email protected] ~]# /usr/local/mysql/bin/mysqld_safe –skip-grant-tables &

登录MySQL

[[email protected] ~]# mysql -u root -p

mysql> use mysql;
mysql> update user set password=password(“123456″) where user=”root”;
mysql> flush privileges;

启动MySQL服务

[[email protected] ~]# /etc/init.d/mysql start
注意了,MySQL5.7之后,重置root密码SQL(感谢刘韦声回复):

update mysql.user set authentication_string=password('123456') where user='root';

创建用户

CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON myapp.* TO 'username'@'localhost';
FLUSH PRIVILEGES

ctrlp.vim, ack.vim, syntastic快捷键速查

一. ctrlp.vim

ctrlp.vim可以模糊查询定位:工程下的所有文件,打开的buffer,buffer内的tag,最近访问的文件.
进入搜索模式后的快捷键:

* <f5> 更新目录缓存。
* <c-f> / <c-b> 在模式之间切换
* <c-d> 在”完整路径匹配“ 和 ”文件名匹配“ 之间切换
* <c-r> 在“字符串模式” 和 “正则表达式模式” 之间切换
* <c-j> / <c-k> 上下移动光标
* <c-t> 在新的 tab 打开文件
* <c-v> 垂直分割打开
* <c-x> 水平分割打开
* <c-p>, <c-n> 选择历史记录
* <c-y> 文件不存在时创建文件及目录
* <c-z> 标记/取消标记, 标记多个文件后可以使用 <c-o> 同时打开多个文件

更多:

git: https://github.com/ctrlpvim/ctrlp.vim

以及比较丑的官网: http://kien.github.io/ctrlp.vim/

二. ack.vim

ack是一个全局搜索工具, 比Vim自带的grep快很多。

?           帮助,显示所有快捷键
Enter/o     打开文件
O           打开文件并关闭Quickfix
go          预览文件,焦点仍然在Quickfix
t           新标签页打开文件
q           关闭Quickfix

更多:

git: https://github.com/mileszs/ack.vim

三. syntastic

e
打开错误列表

\n
移动到下一个错误位置

\p
移动到上一个错误位置

更多:

git: https://github.com/vim-syntastic/syntastic

其他

本配置中, ctrlp和ack的前缀分别为: ,e,r

ubuntu下twisted安装错误解决

本机环境 python3.6, 使用pip install twisted时候出现错误:

Command ... /home/wukt/.virtualenvs/spiderenv/include/site/python3.6/twisted" failed with error code 1 in /tmp/pip-install-k06rgbaf/twisted/

同时造成无法正常安装scrapy框架。

解决方法

  1. 下载安装文件
wget https://pypi.python.org/packages/c0/7c/c1e5b61e30b7ffc96576d2a922615c8068e6996a622be813fc626cef07aa/Twisted-16.3.0.tar.bz2#md5=e044af844623e9fbcbe29f578db6053a
  1. 解压
tar jxvf Twisted-16.3.0.tar.bz2
  1. 安装
cd Twisted-16.3.0
python setup3.py install 

等待twisted安装成功后可以再使用pip install scrapy正常安装scrapy。

tmux快捷键速查

Tmux 快捷键 & 速查表

启动新会话:

tmux [new -s 会话名 -n 窗口名]

恢复会话:

tmux at [-t 会话名]

列出所有会话:

tmux ls

关闭会话:

tmux kill-session -t 会话名

关闭所有会话:

tmux ls | grep : | cut -d. -f1 | awk '{print substr($1, 0, length($1)-1)}' | xargs kill

在 Tmux 中,按下 Tmux 前缀 ctrl+b,然后:

会话

:new<回车>  启动新会话
s           列出所有会话
$           重命名当前会话

窗口 (标签页)

c  创建新窗口
w  列出所有窗口
n  后一个窗口
p  前一个窗口
f  查找窗口
,  重命名当前窗口
&  关闭当前窗口

调整窗口排序

swap-window -s 3 -t 1  交换 3 号和 1 号窗口
swap-window -t 1       交换当前和 1 号窗口
move-window -t 1       移动当前窗口到 1 号

窗格(分割窗口)

%  垂直分割
"  水平分割
o  交换窗格
x  关闭窗格
⍽  左边这个符号代表空格键 - 切换布局
q 显示每个窗格是第几个,当数字出现的时候按数字几就选中第几个窗格
{ 与上一个窗格交换位置
} 与下一个窗格交换位置
z 切换窗格最大化/最小化

同步窗格

这么做可以切换到想要的窗口,输入 Tmux 前缀和一个冒号呼出命令提示行,然后输入:

:setw synchronize-panes

你可以指定开或关,否则重复执行命令会在两者间切换。
这个选项值针对某个窗口有效,不会影响别的会话和窗口。
完事儿之后再次执行命令来关闭。帮助

调整窗格尺寸

如果你不喜欢默认布局,可以重调窗格的尺寸。虽然这很容易实现,但一般不需要这么干。这几个命令用来调整窗格:

PREFIX : resize-pane -D          当前窗格向下扩大 1 格
PREFIX : resize-pane -U          当前窗格向上扩大 1 格
PREFIX : resize-pane -L          当前窗格向左扩大 1 格
PREFIX : resize-pane -R          当前窗格向右扩大 1 格
PREFIX : resize-pane -D 20       当前窗格向下扩大 20 格
PREFIX : resize-pane -t 2 -L 20  编号为 2 的窗格向左扩大 20 格

文本复制模式:

按下前缀 [进入文本复制模式。可以使用方向键在屏幕中移动光标。默认情况下,方向键是启用的。在配置文件中启用 Vim 键盘布局来切换窗口、调整窗格大小。Tmux 也支持 Vi 模式。要是想启用 Vi 模式,只需要把下面这一行添加到 .tmux.conf 中:

setw -g mode-keys vi

启用这条配置后,就可以使用 h、j、k、l 来移动光标了。

想要退出文本复制模式的话,按下回车键就可以了。一次移动一格效率低下,在 Vi 模式启用的情况下,可以辅助一些别的快捷键高效工作。

例如,可以使用 w 键逐词移动,使用 b 键逐词回退。使用 f 键加上任意字符跳转到当前行第一次出现该字符的位置,使用 F 键达到相反的效果。

vi             emacs        功能
^              M-m          反缩进
Escape         C-g          清除选定内容
Enter          M-w          复制选定内容
j              Down         光标下移
h              Left         光标左移
l              Right        光标右移
L                           光标移到尾行
M              M-r          光标移到中间行
H              M-R          光标移到首行
k              Up           光标上移
d              C-u          删除整行
D              C-k          删除到行末
$              C-e          移到行尾
:              g            前往指定行
C-d            M-Down       向下滚动半屏
C-u            M-Up         向上滚动半屏
C-f            Page down    下一页
w              M-f          下一个词
p              C-y          粘贴
C-b            Page up      上一页
b              M-b          上一个词
q              Escape       退出
C-Down or J    C-Down       向下翻
C-Up or K      C-Up         向下翻
n              n            继续搜索
?              C-r          向前搜索
/              C-s          向后搜索
0              C-a          移到行首
Space          C-Space      开始选中
               C-t          字符调序

杂项:

d  退出 tmux(tmux 仍在后台运行)
t  窗口中央显示一个数字时钟
?  列出所有快捷键
:  命令提示符

配置选项:

# 鼠标支持 - 设置为 on 来启用鼠标
* setw -g mode-mouse off
* set -g mouse-select-pane off
* set -g mouse-resize-pane off
* set -g mouse-select-window off

# 设置默认终端模式为 256color
set -g default-terminal "screen-256color"

# 启用活动警告
setw -g monitor-activity on
set -g visual-activity on

# 居中窗口列表
set -g status-justify centre

# 最大化/恢复窗格
unbind Up bind Up new-window -d -n tmp \; swap-pane -s tmp.1 \; select-window -t tmp
unbind Down
bind Down last-window \; swap-pane -s tmp.1 \; kill-window -t tmp

配置文件(~/.tmux.conf):

# 基础设置
set -g default-terminal "screen-256color"
set -g display-time 3000
set -g escape-time 0
set -g history-limit 65535
set -g base-index 1
set -g pane-base-index 1

# 前缀绑定 (Ctrl+a)
set -g prefix ^a
unbind ^b
bind a send-prefix

# 分割窗口
unbind '"'
bind - splitw -v
unbind %
bind | splitw -h

# 选中窗口
bind-key k select-pane -U
bind-key j select-pane -D
bind-key h select-pane -L
bind-key l select-pane -R

# copy-mode 将快捷键设置为 vi 模式
setw -g mode-keys vi

# 启用鼠标(Tmux v2.1)
set -g mouse on

# 更新配置文件
bind r source-file ~/.tmux.conf \; display "已更新"

#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# Tmux Plugin Manager(Tmux v2.1)
# Tmux Resurrect
set -g @plugin 'tmux-plugins/tmux-resurrect'

# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'

# Other examples:
# set -g @plugin 'github_username/plugin_name'
# set -g @plugin '[email protected]/user/plugin'
# set -g @plugin '[email protected]/user/plugin'

# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

原文https://gist.github.com/ryerh/14b7c24dfd623ef8edc7

wtforms的调用验证方式优化

通常, 在使用flask验证器的过程中视图会有类似下面的语句:

data = request.json
form = ClientForm(data=data)
if form.validate():
    #...
else:
    #...
  • 重写的目的:
  1. 无需每次在视图中使用data=reqeust.data, form = XXForm(data=data)获取和传入请求数据.
  2. 无需在视图中使用ifelse判断, 请求数据有问题时候, 直接向客户端返回异常.
  • 分析:

为了省去视图函数向验证器每次传数据的过程, 重写构造器的时候可以直接使用request.data获取;
为了直接返回异常, 需要重写validate, 此处我们不重写, 直接定义一个类似的方法, 去调用validate.


from flask import request from wtforms import Form # 这是之前定义的参数错误异常处理类 from app.libs.error_code import ParameterException class BaseForm(Form): def __init__(self): data = request.json super(BaseForm, self).__init__(data=data) def validate_for_api(self): valid = super(BaseForm, self).validate() if not valid: # 这里如果出错将直接跑出异常, 视图中将免除了判断并使用ifelse的麻烦 raise ParameterException(msg=self.errors) return self

这时候, 继承这个类的验证表单如果验证参数有问题, 将会’自动向客户端返回一个异常json数据, 而无需在后续使用raise, 因为在验证器已经将错误raise出去了.

在form定义的表单可以直接继承自定义的基础表单, 不在继承wtfforms的原始表单, 如:

class ClientForm(BaseForm):
    #...
    secret = StringField(validators=[...])  

之后在视图中如果需要验证变方便的多, 如: 

@api.route('/register', methods=['POST'])
def create_client():
    form = ClientForm().validate_for_api()
    return Success()

视图中不在需要使用if判断参数是否合法, 也不需要将request数据当做参数传到form对象中, 后续将大大减少代码量.