刘贵学博客

在 Mac电脑上最优雅地用 Windows: WTG 安装过程

1. 背景

2013年底,我买了一款 15寸的 MacBookPro,已经用了5年多,现在性能配置仍算中上等,再熬2-3年完全没问题。

以前很多朋友想买笔记本让我推荐,对电脑重度用户(程序员、设计师、非游戏),我通常只给一个答案: 高配MBP,2W的价格乍一看很贵,但是可以用 6-8年,完全够本了。
有的东西看着贵,你经常使用且能大幅提高你的生产力,很合算;也有的东西看着便宜,买来就用不了几次,或没多久就坏了,跟花钱买垃圾差不多,那是真贵,比如:某想笔记本。

Mac OS系统确实方便,是Windows + Linux 二合一:界面比Windows好用,命令行跟Linux一样强大,软件生态质量更高,确实是程序员的必备神器,推荐。

我最近需要录制一门在线课程,学员应该Windows系统居多,所以课程最好用Windows环境来演示。

Mac上怎么使用Windows呢?方法不外乎以下几个:

  • 双系统,在SSD上增加安装Windows,浪费空间;
  • 虚拟机,性能太差;
  • Win To Go,将Windows安装到外置存储设备中,即插即用。

录课程,简单的视频编辑,性能要求比较高,所以虚拟机肯定不合适,笔记本的SSD只剩100多G,双系统也不合算。综合下来,最好的选择是 Win To Go。

开始折腾!

2. U盘选择

在京东购买了一款 三星的U盘 ,容量128GB,支持USB3.1读写速度很快, 价格200元左右。

除了这款U盘外,其他的品牌可以参考这个列表中 哪些U盘支持WTG

U盘拿到之后,先格式化为 FAT32。

3. 驱动文件下载【Mac系统中】

1) 插上U盘

2) 打开Boot Camp

Finder -> 应用程序 -> 实用工具 -> 启动转换助理


点击 继续

3) 选择任务

只选择中间的 从Apple下载最新的Windows支持软件

点击 继续

4) 选择存储位置

选择要存储的 U盘,点击 继续 后进入下载页面。

等几分钟后,下载完成,点击退出即可。

最好先将此 U盘中的BootCamp文件夹,备份到其他U盘中,这里面都是驱动,需要系统安装后再重新安装一遍,比如无线网卡驱动。

4. 安装 Windows 系统

下面所有的操作应该在 Windows 10 系统中进行。

1) 下载Win10 ISO

使用迅雷下载 Windows 10 Version 1703 (Updated March 2017) - DVD (Chinese-Simplified):

将下载完成后的 ISO 载入到虚机光驱(如:Daemon Tools) 中。

2) WTG辅助工具

  • 下载 WTG辅助工具 解压到某个目标,路径不应包含中文和空格。
  • 打开 WTGA/wintogo.exe, 界面如下:

  • 浏览选择 sources/install.wim文件;

  • 插入U盘,选择可移动磁盘

  • 选择安装分卷

    高级选项中保持默认配置即可,不需要任何改变。

  • 点击部署即可开始。

完成后,弹出U盘。

5 系统

将 U盘 插入Mac笔记本中,关机。

开机启动Mac,长按住 option 键,进入启动盘选择。

  • 左右建切换 选择中间的 Windows 启动选项,回车。
  • 进入 Windows 10 系统的初始化过程,基本上是 一路下一步即可,完成后自动重启。

    注:其中有 设置网络的步骤可以直接跳过。
    
  • 登入 Windows 10 系统,打开备份的 BootCamp文件夹,双击 setup.exe,即可完成驱动的安装。

  • 驱动更新完,再次重启后,就可以正式使用了。

参考资料:

Gogs自己搭建Git Server

1. 前言

Gogs 作为比gitlab更简介的git server库,用go语言实现 Git 仓库的管理,团队协作工具等。

新建 Git 用户

Gogs 默认以 git 用户运行。

$ sudo adduser git

新建好 git 用户。

$ su git 
$ cd ~
$ mkdir .ssh

以 git 用户登录,在git 用户的主目录中新建 .ssh 文件夹。

配置 Mysql 数据库

使用的 mysql 数据库,先新建一个 用户 gogs

$ mysql -u root -p
> # (输入密码)
> create user 'gogs'@'localhost' identified by '密码';
> grant all privileges on gogs.* to 'gogs'@'localhost';
> flush privileges;
> exit;

TBD

Gitlab 3. 手动安装

1. 简介

上次介绍了使用Docker自动化安装Gitlab的过程,几个命令非常简单。但是安装一些插件或定制的时候就不太容易了,所以本文将介绍Gitlab的手动安装,操作系统使用 ubuntu 16.04, 先安装依赖的软件:

更新apt:

sudo apt-get update

安装 openssh等 工具:

sudo apt-get install -y curl openssh-server ca-certificates

安装postfix工具,用于发送通知邮件

sudo apt-get install -y postfix

注意:弹出界面选择:Internet Site

2. 下载与安装

gitlab有 ce 与 ee两个版本:

  • CE 是社区版,可免费使用
  • EE 是企业版,要收费的

先更新 gitlab-ce 的apt源 :

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh|bash

安装gitlab

EXTERNAL_URL="http://192.168.200.200" apt-get install gitlab-ce

耐心等待,要下载 400M+的安装包

3. 配置

gitlab-ctl reconfigure
gitlab-ctl retart
gitlab-ctl status
gitlab-ctl tail

Gitlab 2. 使用Docker一键安装

1. 安装 Gitlab

gitlab的安装过程还是比较麻烦的,我们先使用docker可以简化安装过程。

2. docker image 下载

下载中文版镜像,命令如下:

docker pull twang2218/gitlab-ce-zh:10.6.2

3. 数据文件夹

初始化数据文件夹,

mkdir -p /data/docker/gitlab/config
mkdir -p /data/docker/gitlab/logs
mkdir -p /data/docker/gitlab/data

4. 运行docker 镜像

sudo docker run --detach \
    --hostname 192.22.200.200 \
    --publish 443:443 --publish 80:80 --publish 22:22 \
    --name gitlab \
    --restart unless-stopped \
    --volume /data/docker/gitlab/config:/etc/gitlab \
    --volume /data/docker/gitlab/logs:/var/log/gitlab \
    --volume /data/docker/gitlab/data:/var/opt/gitlab \
    twang2218/gitlab-ce-zh:10.6.2

如果端 443、80、22 端口已经被占用,可选择其他端口,如下:

--publish 8443:443 --publish 8080:80 --publish 8022:22 

Gitlab 1. 简介

1. 简介

研发流程中需要的管理工具如下:

  • 源码管理(git 或 svn)
  • 任务分配
  • 文档管理
  • 里程碑管理
  • 问题追踪
  • ……

    常用的工具如老牌的 trac,redmine等以任务分配、文档管理为主;能结合源码管理的工具如 github,coding.net等,本文所介绍的gitlab 可以在组织内部大家自己的 开源版github。

2. 运行 Gitlab

2.1 首次登陆

首次登陆gitlab 设置root用户的 密码,其他用户可通过注册后登陆。

root用户可以将其他普通用户设为管理员。

2.2 基本功能介绍

  • 代码管理:

  • 代码提交记录

  • 里程碑管理

  • 任务看板

  • 任务详情

  • Wiki文档管理,支持markdown

  • DevOps支持

ubuntu 使用 阿里云的 source.list

直接购买阿里云ECS,ubuntu系统中默认使用的是阿里云 source.list,详见:

/etc/apt/sources.list.d/sources.list.d

自建服务器如果选用 ubuntu,默认是官方的源,速度慢的很,直接使用阿里云ecs中的源,也不行,因为域名 http://mirrors.cloud.aliyuncs.com 无法在外网访问, 出掉 cloud,批量替换成 http://mirrors.aliyuncs.com 就可以了。

提一个 ubuntu 16.04 64位的 source.list

deb http://mirrors.aliyun.com/ubuntu/ xenial main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security universe

将以上内容覆盖到 /etc/apt/sources.list 文件后即可,更新:

apt clean
apt update

使用Docker 部署 MongoDB

1. 下载镜像

docker pull mongo

下载官方默认镜像,mongodb v3.6.2

查看本机镜像:

docker images

2. 运行容器

2.1 默认无密码(不安全)

docker run -p 27017:27017 -v $PWD/db:/data/db -d mongo
  • 注:Mac版的 Docker 需要将 $PWD/db地址设置到 Preferences…

window下没有尝试

2.2 开启认证 (安全,推荐)

docker run -p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=pass123 \
-v $PWD/db:/data/db -d mongo

开启用户名和密码, 使用mongo客户端连接命令如下:

mongo --host=127.0.0.1 --port=27017 \
 --username=admin --password=pass123 \
 --authenticationDatabase=admin

3. 查看 运行情况

docker ps

注:如需要查看容器IP地址,可使用如下命令

docker inspect --format='{{.NetworkSettings.IPAddress}}' e5e1a6efa7ae
  • 停止数据库:

    docker stop e5e1a6efa7ae

SSH 秘钥部署常见场景

本文涵盖两个应用场景:

  1. 通过公钥访问git代码;
  2. Linux服务器自动登录;

首先安装 ssh的客户端与服务器端:

 apt-get install openssh-server openssh-client

1) 场景1:Git账户关联

例如 github.com 或者 coding.net 上传本地 的 pub key。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
cd ~/.ssh
chmod  -R 700 ./
chmod 600 *

把产生的 pub key 配置到 SSH 秘钥设置界面即可。

2) 场景2: Linux服务器无密码自动登陆

客户端可以无密码登陆服务器。

  • (1). 需要在 客户端产生一对秘钥(参考上节)
ssh-keygen -t rsa -b 4096
cd ~/.ssh
chmod -R 700 ./
chmod 600 *
  • (2). 把公钥放到服务器配置SSHD;

~/.ssh/id_dsa.pub

  • (3). 配置sshd服务并启动;

配置sshd允许RSA登陆:

vi  /etc/ssh/sshd_config

将客户端上传的 pub key 放入可认证列表:

cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys 

最后,启动服务器:

/etc/init.d/ssh [start/stop/restart/status]
或者
service sshd start
  • (4). 客户端直接透过 ssh config 里的配置,连接到服务器;
Host myserver
    HostName 139.129.208.188
    User root
    PreferredAuthentications publickey
    identityfile ~/.ssh/private-key
    Port 22

执行 ssh myserver 即可自动连接到远端服务器。

阿里云ECS 与 MongoDB 服务器的部署

1. 购买服务

购买ECS 与 MongoDB服务,需要在同一区域购买,比如都是华北1。

先购买ECS,网络类型选择 专有网络 VPC.

购买 mongoDB时,选择专有网络类型,选择对应的VPC 名称。

2. ESC 基本配置

参考 SSH 秘钥部署常见场景 场景二。

3. 互通链接配置

3.1 MongoDB 网络代理设置

1) 阿里云的MongoDB默认是不能直接通过外网访问的,如果需要访问,可以通过 ECS 作代理。


自动加载内网 IP设置即可。
2). 测试,在ECS机器中,通过mongo shell 手动连接到mongodb

mongo --host dds-XXXX.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u root -p

注意,如果测试失败,请检查mongo的版本,必须要升级ECS中提到的 mongo版本 v3.0以上。
ubuntu16.04 下安装 mongo 3.0 以上的方法:

echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.2.list
apt-get update
apt-get install -y mongodb-org  --allow-unauthenticated

3). 通过ECS的内网连接MongoDB

其中 /etc/rinetd.conf 的内容如下:

0.0.0.0 27098   dds-XXXX.mongodb.rds.aliyuncs.com  3717
logfile /var/log/rinetd.log

如遇到以下错误

请将 /etc/rinetd.conf 配置文件中的空格替换为 Tab

启动 rinetd 服务:

pkill rinetd  //如果已经开启则先停止
rinetd

3.2 通过ECS访问数据库

在本地 使用ECS 的公网IP连接到数据库:

 mongo --host 1.1.1.1:3717 -u root -p 密码 --authenticationDatabase admin

注意,可能会遇到如下问题:

原因是 申请ECS时,没有开通相关端口, 配置方法如下:

MongoDB 连接数耗尽的解决方法

问题

今天突然发现数据库的连接特别迟缓,本地Robo 3T 客户端都连接不上,登陆阿里云后台发现连接数已经到达 500 达到最大值。

原因分析

由于阿里云的MongoDB服务器不能直接暴露给外网访问,开发机器如要访问MongoDB,需要通过一台ECS 路由中转访问。中转服务器使用 rinetd 工具做端口映射,连接没有释放的原因应该是 中转服务器与Mongodb服务器的连接被 rinetd 缓存住了。

解决方案

重启ECS 上的 rinetd 服务即可,执行命令:

rinetd restart

结果提示错误:

rinetd: couldn't bind to address 0.0.0.0 port 27099

看下 27099 这个端口被谁占用呢?

netstat -ltnp | grep ':27099'
tcp        0      0 0.0.0.0:27099           0.0.0.0:*               LISTEN      8633/rinetd

把 8633 这个进程 kill 掉就可以

pkill rinetd
rinetd restart

【效率】Mac 下常用快捷键

Mac下丢掉鼠标,提高效率

  • 编辑器 VSCODE

1. 切换环境

  • 多个桌面切换: 三手指左右滑动,触摸板;
  • 切换工作窗口: CMD + TAB
  • VSC中切换Tab:CMD+W

团队Git 协作环境的使用规范

本文的目的是让新成员快速熟悉团队协作工具和流程。

源码管理拓扑如下:

本文将涵盖如下内容:

  1. 客户端 Git for Windows 安装
  2. Coding.net的注册;
  3. SSH秘钥制作与上传;
  4. 下载(项目)源码;
  5. VSC的安装与Git插件管理源码;
    • 更新代码;
    • 提交代码;

本文将涉及的工具与环境如下:

  • Git 客户端使用: VSC 插件
  • 服务器端使用: Coding.net
  • 操作系统假定 Window 7

1. 客户端 Git for Windows

客户端 Git for Windows 下载地址:

https://git-for-windows.github.io/

安装完成过程参考:

完成后,记得注册到系统环境变量。

输入 git 命令可以测试环境是否OK。

2. Coding.net的注册

注册地址:

https://coding.net/

注册完成后,将 昵称发送给 项目管理人员, 他会将你加入项目。

注意: 本文不涉及项目的初始化,创建,添加项目成员。

加入项目后,所有项目链接下看到项目情况:

https://coding.net/user/projects

进入一个项目后,右侧选择源码

建议要选择 SSH方式,不会每次提交弹出输入密码。

git@git.coding.net:guixue/XXXApp.git

上面这个路径,就是我们项目源码的地址, 后面会用到。

3. SSH秘钥制作与上传

我们跟 git 服务器通讯使用的使用 SSH 秘钥,不用每次都输入密码,方便。

在 CMD 框中输入 :

cd C:\Users\liuguixue\.ssh
ssh-keygen

新建一个 config文件,内容如下:

host git.coding.net
 user YOURNAME
 hostname git.coding.net
 identityfile /c/Users/liuguixue/.ssh/coding
 PreferredAuthentications publickey

其中 YOURNAME 换成 coding.net 上登陆的用户名

将 coding.pub 里的内容复制,在 coding.net 里增加秘钥。

右上角用户头像, 用户设置,

输入登陆密码即可。

4. 下载项目源码

使用命令 git clone 下载源码:

5. VSC 安装与插件

5.1 安装 VSC

VSC 指的是 VS Code,由微软开源的一款现代化的代码编辑器,支持插件,性能块,非常好用。

点击如下链接下载VSC工具

https://code.visualstudio.com/

下载完成后,双击安装即可。

注意:安装目录尽量不要有中文和空格,例如:C:\soft\VSCode

5.2 安装 Git Easy 插件

步骤如下:

安装完成后,重载窗口。

5.3 更新代码

用 VSC 打开 已经clone 的代码路径,

1.先暂存本地修改:

2.拉取服务器最新代码

5.4 提交代码

提交代码之前,也需要 暂存本地代码,拉取最新代码,参考5.3.

1.提交代码

2.推送到服务器

如何写 RESTful API 文档

本文使用 apidoc 工具自动生成 RESTfull API 格式的文档

安装

npm install apidoc -g

cd rest/doc
./doc.sh

产生的 手册文件存放在 doc/gen 目录下,打开index.html 即可使用。

使用方法

基于注释,按标记 自动提取文档内容, 类似写法如下:

 /**
 * @api  {get}  /v1/focus/:id/:focus
 * @apiGroup Projecting
 * @apiDescription  关注或取消关注项目。 注:用于App
*/

参数说明:


更多明细,请参考: http://apidocjs.com/#param-api

生成的文档如下图:

RESTful 测试工具

  1. 命令行工具可以使用 curl 工具:

  • get 方法

    curl \
    localhost:7999/v1/projecting/5964ba8c34be4904b70394bf
    
  • post 方法

    curl -l -H "Content-type: application/json" -X POST \
    localhost:7999/v1/projecting/5964ba8c34be4904b70394bf  -d \
    '["59644de76ab75d074f300a5b","5966472e79478d0e2547c7a3"]'
    
  1. 图形化的建议使用 PostMan, 使用方法:

Mongodb 安全加密认证

1. 安装

  1. Ubuntu:

    apt-get install mongodb
    
  2. Mac OS

    brew install mongodb
    

2. 服务器认证配置

2.1 添加用户

use admin
db.createUser({user: 'root', pwd: 'password', roles: ['root']})

db.system.users.remove({user:"haha"})

2.2 加密配置

  • ubuntu 下的配置: /etc/mongodb.conf,修改后的内容如下:

    bind_ip = 0.0.0.0
    port = 27098
    auth=true
    
  • Mac 下的配置, /usr/local/etc/mongod.conf

    net:
        bindIp: 0.0.0.0
        port: 27098
    security:
        authorization: enabled
    

注:

  • 建议更换一个其他的端口,来保证安全;

重启服务

  1. Ubuntu下:

    /etc/init.d/mongodb restart
    // 或:
    service  mongodb restart
    
  2. Mac OS下 重启服务

    ps -A|grep mongo
    sudo kill XXXX
    sudo mongod --config /usr/local/etc/mongod.conf --fork
    

3. 客户端认证连接

  1. 使用客户端 mongo 认证连接:

    mongo --port=27098
    >use admin
    >db.auth("root", "password")
    1
    >use your-other-db
    
  2. 使用客户端 robomongo 认证连接:

  1. nodejs 中 mongoose 的重新连接字段:

    mongodb : "mongodb://root:password@YOUR-IP:27098/FireDB?authSource=admin"
    

4. 参考文档

https://scarletsky.github.io/2014/10/25/mongodb-security-and-auth/

npm 安装与使用

1 安装 nodejs

下载

https://nodejs.org/en/download/

直接安装

注意:ubuntu通过 apt-get install nodejs 安装的版本比较低。

node -v 

查看nodejs 的安装结果

2 npm 安装

直接通过命令可安装:

curl http://npmjs.org/install.sh | sudo sh 

通过

node -v 

查看npm 的安装结果

3 配置 npm registry

npm config set registry "http://r.cnpmjs.org"

也可以 使用 nrm 工具 来切换 npm 镜像库站点,

npm install -g nrm 

国内建议使用 淘宝的库:

4 nvm 配置 nodejs 的版本号

npm install -g nvm

node -v

nvm version

nvm install v6.10.3 
v8.0 v6.10.3

如果 安装 nvm 出问题 可以参考 https://github.com/creationix/nvm/blob/master/README.md , ubuntu下建议安装方法

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash

建议使用v6.10.3版本,因为 webpack等一些工具必须要求 6.X,而v6.10.3是LTS(长期技术支持)。

前端开发入门参考资料单

更新日期: 2016-01-12

1. 基础语法篇

1.1. HTML&CSS 教程

1.1.1 W3C HTML 教程

1.1.2 W3C CSS 教程

1.1.3 慕课网 HTML+CSS基础课程 练习

1.1.4 Web配色:色彩设计方法

完成1.1所有课程,建议完成作业,实现一个博客的页面,例子可以参考:
http://www.diandian.com/
http://www.ghostchina.com/

1.2. JavaScript 教程

1.2.1 W3C JavaScript教程

1.2.2 慕课网 JavaScript 入门篇 练习

2. 进阶框架篇

2.1. Bootstrap

2.1.1 Bootstrap官方文档

2.1.2 慕课网 玩转Bootstrap 基础 视频

2.2. CSS 框架

2.2.1 Less框架

2.2.2 慕课网 Less基础 视频

2.3. jQuery 框架

2.3.1 W3C jQuery教程

2.3.2 慕课网 jQuery基础课程 练习

2.4. AngularJS 框架

2.4.1 AngularJS 中文社区系列 教程

2.4.2 慕课网 AngularJS实战 视频

2.4.3 AngularJS API手册 英文

Ubuntu 下PHP开发环境配置脚本

1. 系统更新

apt-get update

2. 安装git

apt-get install libcurl4-openssl-dev  libexpat1-dev git

3. 安装 lnxcfg 脚本 ( bookmark, git command alias, vim and plugins.)

git clone https://github.com/guixue/lnxcfg.git
cd lnxcfg
make
vi ~/.bashrc 
添加
if [ -f ~/.mybashrc ]; then
    . ~/.mybashrc
fi
source ~/.bashrc

4. 安装 HTTP 服务器: nginx

apt-get install nginx

测试: hello.html 可以显示

5. 安装数据库: mysql-server

apt-get install mysql-server

mysql -u root -p 测试通过

6. 安装PHP:

6.1 PHP5.X

ubuntu 16.04 无法安装 php5.6

sudo apt-get purge `dpkg -l | grep php| awk '{print $2}' |tr "\n" " "`
sudo add-apt-repository ppa:ondrej/php
sudo apt-get install software-properties-common
sudo apt-get update
sudo apt-get install php5.6
apt-get install php5.6-cli php5.6-cgi mysql-server php5.6-mysql 
apt-get install php5.6-xml php5.6-gd
apt-get install php5.6-fpm
apt-get install spawn-fcgi
cd /usr/sbin
ln -s php-fpm5.6 php-fpm

6.2 PHP 7.x

sudo apt-get install php
apt-get install php-cli php-cgi php-mysql php-xml php-gd

7. 测试PHP 环境:

1) . 新增vhost 站点:

例如: /etc/nginx/sites-enabled/default.conf

server {
    listen 80;
    server_name [IP or domain Name];

    root  /var/www/sites/default/;

    location / {
        index index.html index.php;
        autoindex on;
    }
    
    include enable-php.conf;
    
    access_log logs/[domain Name].log;

}

注: /etc/nginx/enable-php.conf ,针对通用的所有的PHP解析:

location ~ \.php$ {
        fastcgi_intercept_errors on;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  fastcgi_script_name;
        include fastcgi_params;

}

测试: info.php 简单探针程序可以运行;

<?php

phpinfo();

info.php 测试通过

apt-get install phpmyadmin
# whereis phpmyadmin
# ln -s /usr/share/phpmyadmin phpadmin

SSH 配置

将静态资源压缩10倍+

背景

目前JS框架很多,发展很快,但是使用 Angularjs(ionic) 或 React 框架,合并的js源码动辄 几兆,浏览器首次加载太吃力,使用较多的是使用 uglify,minify 等工具后,静态文件能通常压缩2-3倍,很多情况下这还是不够,如何进一步压缩呢?

服务器Nginx原生支持 gzip on/off 的功能,此功能的意思是,自动为浏览器的所有文件实时压缩,可以节省传输带宽,提供传输速度。但对每次请求实时压缩,同时会增加了服务CPU的负荷,有时,反而得不偿失,所谓鱼和熊掌不可兼得。

有没有方案既吃鱼又啃熊掌吗?即:利用gzip节省带宽,又不多消耗CPU。

答案是: static gzip!

方案

实时压缩对于请求大于 1K 动态资源还是很有用处的。

对于静态资源来讲,我们需要的只是压缩,不要针对每次一请求实时处理。

如果我们需要压缩的文件(例如 all.js), 在部署的时候就产生了一份压缩好的文件,(如 all.js.gz),只需要在服务器请求 *.gz 文件的时候加上, http响应头:

Accept-Encoding:gzip, deflate

告诉浏览器,*.gz 是压缩文件,要解压缩,就可以啦。

这就是,static gzip,所以问题的解决在于,需要解决两个小步骤:

  • Step1:部署前使用工具将大的资源文件 gzip,添加.gz后缀;
  • Step2:服务器查找文件时,先查找是否有同名gz文件,如有优先读取gz文件。

Gzip Step1 部署前统一压缩

gulp

安装

npm install -save-dev gulp-gzip
gzip = require('gulp-gzip');


gulp.task('gzip', function() {
    //js gzip
    gulp.src('./www/lib/ionic/js/*.min.js')
      .pipe(gzip())
      .pipe(rename({extname: '.gz'}));

      //css gzip
      gulp.src('./www/lib/ionic/css/ionic.css')
        .pipe(gzip())
        .pipe(rename({extname: '.gz'}));
});

执行 gulp gzip 命令, 查看结果,可以节省 70%左右的网络带宽:

其他工具

例如webpack等,这里就省略了,按照 gulp的思路,去找对应 plugin 吧。

Gzip Step2 Web服务器添加Header

Nginx

nginx 去除了支持 gzip 的实时 压缩,也支持静态压缩,添加如下配置即可。

gzip_static on;

开启nginx_static后,对于任何文件都会先查找是否有对应的gz文件。

Apache

通过 deflate_Module和headers_Module 来实现,详情不标。

总结

以 ionic为例,在压缩前, 2.6M左右:

压缩后, 只有不到200K:

整个压缩比例 10倍以上。

后记

其实,nginx_static 还是会有一些I/O性能损耗,即,会对所有的文件都先查询一下是否存在同名gz文件。

如果修改为:
* 站点目录添加 .gzip_statics 配置文件列表;
* 根据站点根目录下的一个配置文件(server 启动时将配置文件加载到内存)的规则,来确定是否查找 gz文件。

附脚本:用gulp 压缩js和css

var gulp = require('gulp');

var     uglify = require('gulp-uglify');
var     rename = require('gulp-rename');
var     mincss = require('gulp-minify-css');
var     concat = require('gulp-concat');
var     gzip = require('gulp-gzip');

var dist_path = 'Public/static/dist/';

gulp.task('gzjs', function() {

    gulp.src([
          'Public/static/vendor/modernizr/modernizr.js',
     //........待压缩的列表,注意顺序
        ])
        .pipe(concat('common.js'))
        .pipe(gulp.dest(dist_path))
        .pipe(rename('common.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest(dist_path))
        .pipe(rename('common.min.js'))
        .pipe(gzip())
        .pipe(gulp.dest(dist_path));

});

 gulp.task('gzcss', function() {
     gulp.src([
         'Public/static/css/font-awesome.css',
         //........待压缩的 css 列表,注意顺序
        ])
         .pipe(concat('common.css'))
         .pipe(gulp.dest(dist_path))
         .pipe(rename('common.min.css'))
         .pipe(mincss())
         .pipe(gulp.dest(dist_path))
         .pipe(rename('common.min.css'))
         .pipe(gzip())
         .pipe(gulp.dest(dist_path));

 });

gulp.task('default', ['gzjs', 'gzcss']);

Express 学习实例

1. Express框架

1.1 运行原理

1.2 Express API

1.3 router的使用

app.route('/login')
    .get(function(req, res) {
        res.send('this is the login form');
    })
    .post(function(req, res) {
        console.log('processing');
        res.send('processing the login form!');
    });

2. Express 实例 Hello world

2.1. 环境安装

 mkdir demo
 npm init       //一路回车
 npm install --save express@4

2.2. 写一个例子

var express = require('express');
var app = express();

app.get('/hello', function(req, res){
  res.send('Hello World');
});


var server = app.listen(3000, function() {
    console.log('Listening on port %d', server.address().port);
});

2.3. 测试

浏览器用 http://localhost:3000/hello 会输出

Hello World

3. 使用 generator 创建实例

npm install -g express-generator
express --sessions --css stylus --ejs myapp
cd myapp
npm install
node app

浏览器用 http://localhost:3000/ 会输出 index 内容。

nginx 配置反向代理

站点配置如下:

/etc/nginx/sites-enabled# vi XXXX.conf
server {
    listen 80;
    server_name YOUR_DOMAIN.com;


    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

常用命令收集

Yxld0iiRyjm4ZXrq

MYSQL压缩备份

filename="backfile_prefix_`date +%y%m%d`.sql.gz"
database="database name"
username="username"
password="password"
mysqldump -hlocalhost -u$username -p$password $database|gzip >$filename

文件夹压缩


tar -zcvf ./test.tar.gz ./test

//解压
 tar -zxvf  ./etc.tar.gz

分卷压缩

  1. 将目录分卷压缩
zip -s 100m -x "*.DS_Store" -r split-foo.zip foo/

• -s 切分单元的大小,可选的单位有k(kB), m(MB), g(GB), t(TB),默认为m
• -r 或者 –recurse-paths 递归目录
• -x 或者 –exclude 忽略文件

  1. 切分已有zip文件
zip existing.zip --out new.zip -s 50m
  1. 解压分卷:
//-s 0 表示合并
zip -s 0 split.zip --out single.zip

//解压
unzip single.zip 

上传文件到服务器

scp -r file.txt username@192.168.0.1:/home/username/

chrome清除 dns

chrome://net-internals

//Mac 清除缓存
sudo dscacheutil -flushcache;sudo killall -HUP mDNSResponder; sudo dscacheutil -flushcache;sudo killall -HUP mDNSResponder; 

//最高版本
sudo dscacheutil -flushcache


# 

## Mac 下 vmware 无法打开虚拟机
先后显示两个对话框:

* 打不开 /dev/vmmon:无此文件或目录。
* 初始化显示器设备失败。

在命令行中输入:

    sudo kextunload /Library/Extensions/intelhaxm.kext




重复添加数据,SQL筛选

1. 问题

由于网络缓慢,或用户点击太快,造成重复添加记录。

2. 解决方案

  • Root Case 方案:

    • 用户提交后,将 form 里的 button disabled,
    • 后台每次新增数据时,验证是否已经存在。
  • 补救方案:

筛选重复记录,手动删除:

  Select * From TABNAME  Where tid 
  In (Select tid From TABNAME Group By tid Having Count(*)>1)

Thinkphp 中 json RPC 的跨域方案

1. 跨域支持

Web server 的配置(nginx)

   location ~ \.php$ {

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers Origin,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,X-Requested-With,Content-Type,Accept;
    add_header Access-Control-Allow-Methods POST;

    fastcgi_intercept_errors on; 
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  fastcgi_script_name;
    include /usr/local/etc/nginx/fastcgi.conf;
}

Thinkphp中的配置 ThinkPHP/Library/Vendor/jsonRPC/jsonRPCServer.php

if( $_SERVER['Access-Control-Request-Method'] != 'POST' &&   // support nginx cross-domain.
    $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] != 'POST') // support apache CORS cross-domain.
    {

        if (
            $_SERVER['REQUEST_METHOD'] != 'POST' || 
            empty($_SERVER['CONTENT_TYPE']) ||
                (   $_SERVER['CONTENT_TYPE'] != 'application/json' &&
                    $_SERVER['CONTENT_TYPE'] != 'application/json; charset=UTF-8'
                )
            ) 
        {
            // This is not a JSON-RPC request
            $dbg = json_encode($_SERVER);
            Log::err("Not a json rpc client_SERVER=$dbg");
            return false;
        }

    }

2 用 PHP 作为代理实现跨域

以上配置 nginx的 CORS,但是对 IE8以下的浏览器兼容不好,可以直接使用一个简单的php脚步作为代理
在调用者的根目录新建 API.php。

<?php 

function curl_post($url, $post_data, $timeout=3)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);


$headers = array("Content-type: application/json; charset=UTF-8",
                "Accept: application/json",
                "Cache-Control: no-cache",
                "Pragma: no-cache");

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$output = curl_exec($ch);

curl_close($ch);

return $output;
}



$host = "http://remote_server/API.php?c=".$_GET['c'];
$req = file_get_contents('php://input');

$out = curl_post($host, $req);

echo($out);

 ?>

TODO:

Thinkphp 只支持 JSON-RPC 1.0 规格,不支持 批量操作。
* http://www.kancloud.cn/thinkphp/json-rpc-2/43544

常用代码: 日期 与 转义

1 时间和日期

  • 使用 int 在数据库中,例如 create_time PHP 中填入时 用 time函数
$info['create_time'] = time();
  • 前台显示时 ,格式化显示
date("Y-m-d H:i:m", $val) 
  • 前端输入 2016-02-12 13:03 , 提交到数据库的要用strtotime代码为:
$info['datetime'] = strtotime($info['datetime']);

2 转义字符 (换行符转换)

  • br 换成 换行符
    function br2line ($string)
    {
        $string = preg_replace("/(\r\n|\n|\r)/", "", $string);
        return preg_replace("=<br */?>=i", "\n", $string);
    }
  • 换行符 换成 br, 注: 在输出json中常用,因为不能有换行。
    function line2br ($string)
    {
        return preg_replace("/(\r\n|\n|\r)/", "", nl2br($string));
    }

上传头像并压缩裁剪

1. 问题概述

我们做的一个报名系统,有个上传头像的功能,一开始前端同学忘记使用 lrz.js的压缩上传了。造成的结果是,客户上传的头像大多是 1M以上,造成空间与网络的浪费,体验也很长。

2. 解决方案

此问题的解决分两个方面:

  • 一个是 root case,即:开启前端压缩,利用canvas的 base64格式字节码上传到服务器。
  • 另一方面,之前已经上传的头像补救。

2.1 lrz.js图片压缩方案

lrz使用方法

2.2 利用命令行批量裁剪图片

这里用的工具是 imagemagick 里的 convert 命令, shell脚本如下, reszie.sh:

filepath="$1"
filelist=`ls $filepath`
for file in $filelist
do 
 echo  "$filepath/$file"
 convert -resize 300 "$filepath/$file" "$filepath/$file"
done

使用方法:

reszie.sh ./Upload