分类 成长笔记 下的文章

在使用 LNMP 一类的集成环境之后,对单独编译安装从来是对着文档装。尽管在 Mac 下装过无数次,也踩过无数坑,但总是记不住一些细节步骤。将本次安装过程全程记录下来,在将来也可以作个参考。

安装环境

  • 服务器:CentOS 6.8 64 mini
  • 终端:iTerm2
注:为了环境足够干净,本次安装过程为全新安装,如果之前环境安装过集成环境请重装。

安装约定

  • 文章中命令使用到的 $ 均代表 root 用户身份,执行命令时请忽略 $ 符号
  • 为了保证正常安装,我发现许多同学喜欢跳着看,除开 Apache 和 Nginx 部分,其他强烈不建议你跳着看,除非你能解决类似 Command not found 的错误
  • Apache 和 Nginx 建议二选一,本文为测试环境,会同时安装
  • 软件包下载地址:/lnmp/,若不存在请手动执行 mkdir /lnmp 创建
  • 源码包编译安装位置:/usr/local/softwareName
  • 数据库存储文件路径:/data/mysql
  • Nginx 站点目录:/www/

Linux

CentOS 也是安装中的一部分,也记录下安装的过程。以下只截图的重点部分,其他直接默认即可。

安装

虚拟机挂载镜像后,开机,选择 Install system with basic video driver,回车。这个是基础安装,没有界面的。

选择安装模式

然后刷屏模式。。

然后检查介质,直接 Tab 键选择 Skip 跳过检查,如果手残选择了 OK 那么恭喜你,慢慢等吧,没半个小时好不了。

检查安装介质

欢迎页面,直接回车。

选择语言,默认,继续回车。

接下来是抹掉磁盘的警告,直接按 Tab 键选择 Re-initialize all 然后回车。

安装

然后输入你的管理员密码,若是弱口令会提示密码不安全,你可以修改密码或者选择 Use Anyway 来忽略警告,当然我强烈不建议你使用弱口令。

选择安装磁盘,直接默认,然后按 Tab 键切换到 OK,然后回车。

选择磁盘

然后是确认写入的警告,按 Tab 键选择 Write changes to disk

确认安装

然后是漫长的安装过程,这个过程受机器配置的影响安装时间也不确定,慢慢等。

安装中

安装完成,回车重启。

重启服务器

重启完成后直接输入用户名(root),密码登录系统。

配置网络

由于我是虚拟机安装,刚安装完成还没有网络,所以得先修改下网卡配置。

$ vi /etc/sysconfig/network-scripts/ifcfg-eth0 #修改网卡配置

ONBOOT 改为 yes,然后执行命令让网卡配置重载。

$ service network restart #重启网络服务

修改完网卡,尝试使用 ping 命令测试网络是否通畅。

更换 yum 源

总所周知的原因,国内的 yum 下载速度不用多说。先安装需要用到的工具。

$ yum install -y wget curl vim #安装需要的工具

安装完工具,然后先备份下 yum 源

$ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

然后将阿里云的 yum 源下载到本地的 etc/yum.repos.d/,当然你也可以选择其他的源镜像,比如:163 或者 中科大 的镜像源。这里我直接以阿里云的为例。

你可以使用 wget 进行下载:

$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo

或者使用 curl 进行下载(二选一):

$ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo

然后清空缓存。

$ yum clean all
$ yum makecache

然后执行升级命令:

$ yum update

安装更新,键入 y 回车继续。这个过程的等待时间由你的服务器配置和带宽决定。

安装前的配置

防火墙配置

防火墙用于管理入栈和出栈流量,所以先配置放行端口,HTTP 协议端口:80、MySQL 数据库端口:3306、HTTPS 协议端口:443。当然,你也可以直接将防火墙关掉,但是强烈不建议这么做。

$ vim /etc/sysconfig/iptables #编辑防火墙规则

COMMIT 之前按下 i 键插入规则。

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

按下 Esc 键,键入 :wq 保存,然后重启防火墙。

$ service iptables restart

然后查看防火墙规则,是否有刚添加的规则。

$ iptables -L

如果有 http 或者 80 端口开放则配置完成。

关闭 SELinux

SELinux 是红帽(Red Hat)系列系统中的一个强制访问控制系统,你可以理解为 360 安全卫士,是必须关的一个东西。(除了百度,最讨厌的就是 360 了,当然还有金山。)

首先编辑 SELinux 的配置文件:

$ vim /etc/selinux/config #配置 SELinux

按下 i 插入,将 SELINUX=enforcing 前边加一个 # 注释掉,SELINUXTYPE=targeted 同样在前面加 # 注释掉,在尾部插入 SELINUX=disabled,然后按下 Esc 键入 :wq 保存。

然后执行命令使配置生效。

$ setenforce 0
注:这里有一个坑,执行命令后,配置可能还是未生效。最好的解决方案是:重启服务器。

安装编译工具和库文件

软件的安装编译需要用到的工具,直接复制安装,这个过程比较漫长。

$ yum install -y make apr* autoconf automake curl curl-devel gcc gcc-c++  cmake  gtk+-devel zlib-devel openssl openssl-devel pcre-devel gd kernel keyutils patch perl kernel-headers compat* cpp glibc libgomp libstdc++-devel keyutils-libs-devel  libarchive   libsepol-devel libselinux-devel krb5-devel libXpm* freetype freetype-devel freetype* fontconfig fontconfig-devel libjpeg* libpng* php-common php-gd gettext gettext-devel ncurses* libtool* libxml2 libxml2-devel patch policycoreutils bison

安装 libmcrypt

libmcrypt 是 PHP 的加密拓展库。这里我准备了一个下载地址:libmcrypt-2.5.8.tar.gz

你可以使用 wget 命令进行下载。 若不存在 /lnmp/ 目录请先使用 mkdir /lnmp 创建目录。

$ cd /lnmp/ # 切换到 /lnmp 目录,不存在则先 mkdir /lnmp 再执行
$ wget https://static.openapi.link/libmcrypt-2.5.8.tar.gz  # 下载 libmcrypt 包
$ tar zxvf libmcrypt-2.5.8.tar.gz  # 解压 libmcrypt 包
$ cd libmcrypt-2.5.8  # 进入 libmcrypt 解压的目录
$ ./configure  # 配置
$ make && make install  # 编译安装

这个过程大约在 10s-20s内完成,接下来开始安装 Nginx。

Nginx

创建 Nginx 用户组

首先,下载 Nginx,下载地址:Nginx-1.13.2.tar.gz,下载到 /lnmp/

$ cd /lnmp/
$ wget http://nginx.org/download/nginx-1.13.2.tar.gz
$ tar zxvf nginx-1.13.2.tar.gz
$ cd nginx-1.13.2

到这里,建议为 Nginx 创建一个运行的账户 www,且该账户不允许登录系统。

$ useradd www -s /sbin/nologin  # 创建一个运行账户

安装 Nginx

开始编译 Nginx 并安装。

$ ./configure --prefix=/usr/local/nginx --user=www --group=www --without-http_memcached_module --with-http_stub_status_module --with-http_ssl_module  # 配置
$ make && make install  # 编译并安装

配置

要将 Nginx 加入开机启动项,需要先下载一个管理脚本,下载地址:nginx,同样下载到 /lnmp/ 中。

$ cd /lnmp/
$ wget https://static.openapi.link/nginx  # 下载脚本

或者编写一个名为 nginx 脚本。

$ cd /lnmp/
$ vim nginx

将以下代码复制粘贴进该脚本中。

#!/bin/bash
# nginx Startup script for the Nginx HTTP Server
# it is v.0.0.2 version.
# chkconfig: - 85 15
# description: Nginx is a high-performance web and proxy server.
# It has a lot of features, but it's not for everyone.
# processname: nginx
# pidfile: /var/run/nginx.pid
# config: /usr/local/nginx/conf/nginx.conf
nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0
# Start nginx daemons functions.
start() {
if [ -e $nginx_pid ];then
echo "nginx already running...."
exit 1
fi
echo -n $"Starting $prog: "
daemon $nginxd -c ${nginx_config}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
return $RETVAL
}
# Stop nginx daemons functions.
stop() {
echo -n $"Stopping $prog: "
killproc $nginxd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /usr/local/nginx/logs/nginx.pid
}
reload() {
echo -n $"Reloading $prog: "
#kill -HUP `cat ${nginx_pid}`
killproc $nginxd -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|reload|status|help}"
exit 1
esac
exit $RETVAL

然后按下 Esc 键,键入 :wq 保存并退出。

设置将 Nginx 加入开机启动项,并赋予执行权限。

$ cp /lnmp/nginx /etc/init.d/  # 将脚本拷贝至服务项
$ chmod 755 /etc/init.d/nginx  # 赋予脚本执行权限
$ chkconfig nginx start  # 设置开机启动项
$ service nginx start  # 启动 Nginx
nginx already running....

此刻,通过本地浏览器访问该服务器 IP 地址,能看到 Welcome to nginx 说明安装成功。

Welcome to nginx

若访问失败,请检查 #防火墙配置 或检查是否有开启 Shadowsocks 类似的翻墙程序。

MySQL

创建 MySQL 用户组

MySQL 的安装同样需要新建一个 mysql 的用户(组),且不允许登录。

$ useradd mysql -s /sbin/nologin

创建 MySQL 数据库文件存放目录,并修改所属用户为 mysql

$ mkdir -p /var/mysql/data  # 创建数据库文件存放目录
$ chown -R mysql:mysql /var/mysql/data  # 设置该目录用户为 mysql

安装 MySQL

开始安装 MySQL,同样需先下载 MySQL,下载地址:mysql-5.5.28.tar.gz,下载到 /lnmp/ 目录下。

$ cd /lnmp/
$ wget https://static.openapi.link/mysql-5.5.28.tar.gz  # 下载 MySQL
$ tar zxvf mysql-5.5.28.tar.gz  # 解压
$ cd mysql-5.5.28  # 进入解压目录
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 -DENABLED_LOCAL_INFILE=1 \
-DMYSQL_DATADIR=/var/mysql/data \
-DMYSQL_USER=mysql -DMYSQL_TCP_PORT=3306
$ make && make install  # 编译安装

这个等待过程视机器性能而定,完成后配置 MySQL 的配置文件。

$ cd /usr/local/mysql
$ cp ./support-files/my-huge.cnf /etc/my.cnf  #拷贝配置文件
#键入 y 覆盖
$ vim /etc/my.cnf  #编辑配置文件,在 [mysqld] 部分增加

[mysql] 中添加数据库文件的保存路径。

datadir = /var/mysql/data

按下 Esc 键,键入 :wq 保存并退出,接着生成数据库文件,并将 MySQL 添加至服务项。

$ ./scripts/mysql_install_db --user=mysql  #生成mysql系统数据库
$ cp ./support-files/mysql.server /etc/init.d/mysql  #把 Mysql 加入系统启动

配置

$ vim /etc/init.d/mysql

找到 basedirdatadir,默认情况下,他们应该没有值,将配置修改。

basedir=/usr/local/mysql
datadir=/var/mysql/data

按下 Esc 键,键入 :wq 保存并退出,接着赋予脚本执行权限并加入开机启动项。

$ chmod 755 /etc/init.d/mysql  # 赋予执行权限
$ chkconfig mysql on  # 添加开机启动项
$ chown -R mysql /usr/local/mysql  # 将 /usr/local/mysql 所属用户修改为 mysql
$ service mysql start  # 启动 MySQL
Starting MySQL.. SUCCESS!

最后,将 MySQL 加入系统环境变量中,即可使用 mysql 命令。

$ vim /etc/profile

在文件末尾追加。

export PATH=$PATH:/usr/local/mysql/bin

按下 Esc 键,键入 :wq 保存并退出,然后将配置生效。

$ source /etc/profile

配置 MySQL 管理员密码。

$ mysql_secure_installation
...
Enter current password for root (enter for none):  # 输入 root 密码,没有,直接回车
...
Set root password? [Y/n]  # 输入 y 回车
...
New password:  # 设置密码
Re-enter new password:  # 确认密码
...
Remove anonymous users? [Y/n]  # 移除匿名用户,输入 y 回车
...
Disallow root login remotely? [Y/n]  # 不允许 root 用户远程登录,允许,输入 n 回车
...
Remove test database and access to it? [Y/n]  # 移除 test 数据库,这个随便
...
Reload privilege tables now?  # 重载,是,输入 y 回车
...
Thanks for using MySQL!

现在,在终端中输入 mysql 命令是否正常。

$ mysql -uroot -p
Enter password:
mysql>

按下 Ctrl + C 退出 MySQL,至此,MySQL 安装完成。

PHP7

首先下载 PHP7 的包,下载地址:php-7.1.11.tar.gz,下载到 /lnmp/ 目录下。

$ cd /lnmp/
$ wget -O php-7.1.11.tar.gz http://cn2.php.net/get/php-7.1.11.tar.gz/from/this/mirror  # 下载
$ tar zxvf php-7.1.11.tar.gz  # 解压
$ cd php-7.1.11
$ ./configure --prefix=/usr/local/php7 --with-config-file-path=/usr/local/php7/etc  --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-mysqlnd --with-mysql-sock=/usr/local/mysql/mysql.sock --with-gd --with-iconv --with-zlib --enable-xml --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --enable-mbregex --enable-fpm --enable-mbstring --enable-ftp --enable-gd-native-ttf --with-openssl --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --enable-session --with-mcrypt --with-curl --with-jpeg-dir --with-freetype-dir   --with-pdo-mysql=/usr/local/mysql/
$ make && make install  # 编译并安装

这个过程就有点长了,可以喝杯茶 ????,放松放松眼睛 ,或者给我留个言吧 _(:зゝ∠)__。

配置

一杯茶之后,继续。

$ cp php.ini-production /usr/local/php7/etc/php.ini  # 复制 php 配置文件到安装目录
$ rm -f /etc/php.ini  # 删除系统自带配置文件
$ ln -s /usr/local/php7/etc/php.ini /etc/php.ini  # 添加软链接
$ cp /usr/local/php7/etc/php-fpm.conf.default /usr/local/php7/etc/php-fpm.conf  # 拷贝模板配置文件为php-fpm配置文件
$ vim /usr/local/php7/etc/php-fpm.conf

找到 ;pid = run/php-fpm.pid 将前面的 ; 去掉。

$ cp /usr/local/php7/etc/php-fpm.d/www.conf.default /usr/local/php7/etc/php-fpm.d/www.conf  # 复制配置文件
$ vim /usr/local/php7/etc/php-fpm.d/www.conf  # 编辑配置文件

找到 user = nobodygroup = nobodynobody 均改为 www 用户(组)。

开机启动

$ cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm  #拷贝php-fpm到启动目录
$ chmod 0755 /etc/init.d/php-fpm  #修改权限
$ chkconfig php-fpm on  #设置开机启动
$ service php-fpm start  #启动php-fpm
Starting php-fpm  done

配置 Nginx 支持 PHP

$ vim /usr/local/nginx/conf/nginx.conf  # 编辑 nginx 配置文件

找到一下代码去掉前面的注释符号 #

location ~ .php$ {
    ...
    # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
    # 注释掉以上条代码添加下面代码
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

至此,PHP 与 Nginx 关联配置完成,你可以在 /usr/local/nginx/html/ 新建 index.php 中写入 PHP 代码测试。

配置主机

Nginx 默认的路径:/usr/local/nginx/html/ 这样的目录太深了不利于操作,我把他放到根目录以便查找。

$ ln -s /usr/local/nginx/html/ /www  # 设置软连接

然后配置虚拟主机。

$ vim /usr/local/nginx/conf/nginx.conf  # 编辑 Nginx 配置文件

最末尾的 } 之前一行 插入 include "vhost/*.conf";,并创建虚拟主机配置目录。

$ cd /usr/local/nginx/conf
$ mkdir vhost

若需要新增一个虚拟站点,则直接在 /usr/local/nginx/conf/vhost 目录下新建一个站点配置文件,并在 /www/ 下创建一个同名的目录即可。

格式如下:

server {
        listen       80;  # 监听端口
        server_name  www.example.com;  # 域名
        root         /www/www.example.com;  # 站点根目录
        index  index.php index.html index.htm;

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
}

Apache *

注:强烈不建议同时安装 Apache 和 Nginx。

首先你到官网下载 Apache,这里我安装的是 2.2.34 比较稳定的版本,我准备了一个地址:httpd-2.2.34.tar.gz

你可以使用 wget 命令进行下载。 若不存在 /lnmp/ 目录请先使用 mkdir /lnmp 创建目录。

$ cd /lnmp  # 切换到 /lnmp 目录,不存在则先 mkdir /lnmp 再执行
$ wget http://mirrors.shuosc.org/apache//httpd/httpd-2.2.34.tar.gz  #下载 httpd 包

然后解压并进入解压后的目录。

$ tar zxvf httpd-2.2.34.tar.gz  #解压 httpd 包
$ cd httpd-2.2.34  #进入 httpd 解压后的目录

配置安装位置并开始安装。

$ ./configure --prefix=/user/local/apache2  #配置安装目录
$ make && make install  #编译并安装

启动 Apache 服务器。

$ /usr/local/apache2/bin/apachectl start

关于 Apache 只简单介绍到这里,关于开机启动项、系统服务、虚拟主机(virtual host)等配置先立个 flag,有时间再更新。

世上三大最难懂:医生的处方、道士的符、程序员的正则

学了几年编程,也写了不少项目,业务逻辑经验攒了一堆,基础知识却落下不少。其中很多还非常重要,比如:进制换算、正则表达式、算法。当初学这些东西的时候,对高数的抗拒让我对带计算的东西也十分抵触。但是,身为码农,这些基础都不懂还怎么拿代码换烟钱?于是,决定恶补一下。

正则表达式

正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。 ——来自维基百科

使用场景

正则表达式起始日常生活中也用过,比如搜索的时候用的*匹配(好吧,那个应该准确的叫做通配符,反正差不多就这意思嘛),下面谈谈正则使用的场景:

  1. 手机号、邮箱、
  2. URL判断
  3. 配置文件、检索关键字
  4. 模板引擎

使用原则

由于正则会将通常一串字符挨个检索,如果没找到匹配项,会从开头一直匹配到结尾,所以说,正则表达式的效率非常低的,能用内置函数尽量用内置函数。不过,一些特定场景正则表达式有他独有的优势

总结:能不用就尽量不用。

语法定义

能不用就不用不代表不学习啊,万一哪天面试就考到你正则不可能瞎写一通吧。即便是做项目在网上复制的现成的也要明白个大概意思。

组成部分

其实组成部分是很多的,这里只做基础介绍。以能写出简单正则,能看懂正则意思为目的。

正则的组成:

  1. 定界符
  2. 原子
  3. 元字符
  4. 模式修正符

匹配规则:

  1. 从左到右
  2. 默认贪婪匹配(简述就是匹配成功后继续匹配,参见#贪婪模式

定界符

定界符是正则表达式的边界,这个没有严格规定,通常以/作为正则的定界符。规则是:不能使用0-9a-zA-Z\和空格。

原子

原子在化学中讲过吧,是最小的单位。而正则中的原子同理,也是正则中最小的单位,不可再分割了。

  • \d:包含0-9
  • \D:不包含0-9
  • \w:包含0-9a-zA-Z_
  • \W:不包含0-9a-zA-Z_
  • \s:包含空白字符、空格、\n\t\r
  • \S:不包含上诉空白字符
  • \b:词边界
  • \B:非词边界
  • []:原子列表,可匹配列表原子或字符出串
  • [^]:取反,写在原子列表里为取反
  • .:除\n以外任意字符

元字符

元字符是用来修饰原子的,不能单独存在,写在原子之后

  • *:匹配任意次
  • +:至少出现一次
  • ?:可有可无,最多一次
  • {}:指定次数

    • {10}:指定十次
    • {3,5}:指定3-5次
    • {3,}:至少3次
    • {0,3}:0-3次
  • ^:指定以某个原子开头(千万别记混[^]^的区别)
  • \A:与^相同
  • $:指定以什么结尾
  • \Z:与$相同
  • |:或
  • ():限制优先级,括号里为一个整体。子模式:参见#子模式

模式修正符

与元字符用于修饰原子,而模式修正符用于修正整个正则表达式。而模式修正符必须写在正则表达式的后面

  • i:忽略大小写
  • m:多行匹配
  • s:让.匹配到\n
  • x:忽略正则表达式中的空格
  • A:与\A^一样
  • U:正则贪婪模式取反

组合

原子与不同元字符组合可以达到很多的效果,而多个元字符可以同时修饰一个原子

  • .+?:取消贪婪匹配,只匹配一个字符
  • .*?:取消贪婪匹配,匹配出0个字符

贪婪模式

仅从应用角度分析,可以这样认为,贪婪模式,就是在整个表达式匹配成功的前提下,尽可能多的匹配,也就是所谓的“贪婪”,通俗点讲,就是看到想要的,有多少就捡多少,除非再也没有想要的了。 ——来自[正则基础之——贪婪与非贪婪模式
](http://blog.csdn.net/lxcnn/article/details/4756030)

子模式

我们可以使用小括号给整个匹配模式进行分组,默认情况下,每个分组会自动拥有一个组号,规则是,从左到右,以分组的左括号为标志,第一个出现的分组为组号1,第二个为组号2,以此类推。其中,分组0对应整个正则表达式。对整个正则匹配模式进行了分组以后,就可以进一步使用“向后引用”来重复搜索前面的某个分组匹配的文本。例如:\1代表分组1匹配的文本,\2代表分组2匹配的文本等等 ——来自正则表达式的子模式详解

样例

由于正则的字符实在"火星",所以需要多加练习才能真正明白其匹配规则,下面写几个样例,以后需要直接用。

判断手机号

分析

手机号一般为11位纯数字,1打头,第二位号码段主要以3,4,5,7,8为主(个人猜测),第三位到最后一位为0-9的随机数。

代码

/^1[34578]\d{9}$/

判断邮箱

分析

邮箱号格式是[email protected],字符串中包含一个@和一个.,其他字符分为三段,第一段以0-9a-zA-Z-_组成且至少一位,第二段以0-9a-zA-Z-组成且至少一位,第三段以a-zA-Z组成且至少两位(中文域名就算了吧)。

代码

/\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/

总结

在实际开发中所遇到的正则无非就那么几种,网上有很多大佬写好的直接可以用,而自己写的一些正则可以存下笔记,以便以后遇到相同的需求可以直接使用,毕竟效率最重要。

文档

个人用伪类在布居中比较频繁,因为觉得能用CSS完成的动画,尽量不用JS,总觉得JS或多或少会影响页面加载速度和流畅度,个人觉得比较经典,其中也有很多平常开发中遇到的一些小问题,也终于有了解释,所以写篇文章总结下。

伪类?

先来回顾伪类的使用方法,类/标签名:伪类类型便可以构造一个伪类:

selector:pseudo-class {
    property: value;
    ...
}

.class:pseudo-class {
    property: value;
    ...
}

常用的伪类:hoveractivevisitedlinkfirst-childlast-childnth-child(n)等等。

小问题

问题1

现在一个页面,需要实现a标签不同伪类下颜色不同,代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Pseudo - Secret Blog</title>
    <style type="text/css">
        a:hover {
            color: red;
        }

        a:visited {
            color: blue;
        }

        a:link {
            color: green;
        }

        a:active {
            color: yellow;
        }
    </style>
</head>
<body>
    <a href="#">Click it!</a>
</body>
</html>

效果演示:Pseudo - Secret Blog

有错么?代码看起来没错呀,我hover去哪儿呢?之前也遇到过类似的问题,代码没错啊,怎么没效果呢?

W3C中提到(CSS 伪类):

提示:在 CSS 定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。
提示:在 CSS 定义中,a:active 必须被置于 a:hover 之后,才是有效的。
提示:伪类名称对大小写不敏感。

上面提到hover必须放到linkvisited之后,而active又要放到hover之后,所有正确的书写顺序是:link -> visited -> hover -> active

问题2

first-childlast-child非常好用,使用方式各式各样,一般用于修改第一个或者最后一个的样式,下列代码大家来分析下,看看有什么错误:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Child - Secret Blog</title>
    <style type="text/css">
        ul li:first-child{
            color: red;
        }
        ul li:nth-child(2){
            color: blue;
        }
        ul li:nth-child(3){
            color: yellow;
        }
        ul li:last-child{
            color: green;
        }
    </style>
</head>
<body>
    <ul>
        <p>List</p>
        <li>First</li>
        <li>Second</li>
        <li>Third</li>
        <li>Last</li>
        <p>List End</p>
    </ul>
</body>
</html>

效果演示:child - Secret Blog

和预想的效果有差异?第一个不是红色字体而是是蓝色呢?第二个不是蓝色又是黄色的,还有最后一个的绿色也没了。

W3C解释(原文地址):

利用 :first-child 这个伪类,只有当元素是另一个元素的第一个子元素时才能匹配。例如,p:first-child 会选择作为另外某个元素第一个子元素的所有 p 元素。一般可能认为这会选择作为段落第一个子元素的元素,但事实上并非如此,如果要选择段落的第一个子元素,应当写为 p > *:first-child。

只有当元素是另一个元素的第一个子元素时才能匹配,通俗的讲,就是上面代码里,div li:frist-child并不是指向下面ul中的第一个li,因为li并不在ul中的一个元素。last-child同理。

nth-child的指向,仔细看一下就会发现,如果将p标签作为第一个的话,那么颜色就没错。而浏览器也正是这样解析的。

总结

CSS 中伪类是一个很奇怪的东西,很多错误发生在细节上却毫无察觉。

今天在Windows下安装了次Node.js环境,其中也涉及到了git的安装和初始化,或许是之前学习的时候太皮,很多命令、参数都忘得干干净净。这次不妨做个笔记,以后可能(一定)会用到。

环境

  • 操作系统:Windows 10 Version 10.0.15063
  • 安装工具:Bash On Ubantu On Windows(以下简称:WinBash)
注:因为WinBash还存在很多尚不明确的因素,安装环境受系统版本及网络影响。Ubantu、CentOS等Linux衍生系统安装方法类似。本次安装仅作参考。

注:若使用WinBash请先开启Windows开发者模式,开启方法请自行搜索。

开始

安装Git

使用apt-get经行安装,命令:

$ sudo apt-get install git

然后输入y,完成安装。

检查安装

可以执行git命令查看是否安装成功,命令:

$ git
usage: git [--version] [--help] [-C <path>] [-c name=value]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]
$ git --version
git version 2.7.4

配置Git

git安装完成,需要初始化用户信息,这通常是全局的,命令如下:

# 配置用户名
$ git config --global user.name "your_name"
# 配置邮箱地址
$ git config --global user.email "your_email"

生成&验证SSH公匙

公匙用于Github或服务器的免密登录的一个口令,一个公匙可多方登录,由于SSH的重要性,请勿泄露公匙。

公匙存在在~/.ssh目录下的id_rsa.pub,如果不存在先生成,存在则直接查看:

# 生成公匙
$ ssh-keygen -t rsa -C "[email protected]"
# 接下来直接敲三个回车
# 查看公匙
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwdB8G/vCpmZu3yI7N62GqykMcBhWZ5BI34rnBXM9CNtXASGD3Pg7erkn0kuOSzSm9RkoRtnmbA/D9TNqMxNtXUxHHjEw27yFPffit1b5Zjj651Kp.......... [email protected]

关于ssh-keygen命令参数解释:

  • -t:申明密匙类型,参数:"rsa1"(SSH-1)、"rsa"(SSH-2)、"dsa"(SSH-2)
  • -C:添加注释

验证SSH公匙

将SSH公匙添加到GithubCoding中的SSH公匙管理中,下一步操作即是验证公匙是否可用,命令:

# Github与Coding验证地址不同,以下以Github为例
$ git -T [email protected]

创建远程仓库

代码管理离不开远程仓库,远程仓库能随时同步代码、多人协助、版本回滚等。

远程仓库国内推荐使用CodingGithub,当然,类似的平台还有码云。在Github上,直接点击New repository建立仓库。

比如,我现在创建一个仓库名为test的仓库:

新建仓库

配置解释:

  • Repository name: 仓库名,不可于当前用户的其他仓库名重名
  • Public / Private: 项目是否公开,这里说明一下的是Github的私有项目是收费的
  • Add README: 是否初始化时建立README.md说明文件
  • Add .gitignore: 是否创建忽略.gitignore配置文件
  • Add license: 是否添加协议

Git基础

建立仓库

创建完成远程仓库,转向本地,初始化本地Git仓库:

# 创建目录
$ mkdir your_project/
# 切换到目录
$ cd your_project/
# 初始化仓库,创建.git目录,将此目录作为git工作空间
$ git init
Initialized empty Git repository in /Users/secret/Desktop/test/.git/

初始化完成本地仓库,需要将本地仓库和远程仓库进行关联:

首先需要获取远程仓库的地址,可以打开刚刚新建的test的仓库:

获取远程仓库链接

在输入框中的内容就是该仓库的远程地址,最右边可以一键复制。

现在将本地仓库与远程仓库进行关联:

$ git remote add origin [email protected]:isecret/test.git

存入缓存区并提交

可以先尝试创建一个文件,然将它添加到缓存中:

# 创建test.txt文件
$ touch test.txt
# 编辑该文件,你同样可以选择其他编辑器
$ vim test.txt
# 保存完成后,将其添加到缓存中
$ git add test.txt
# 提交本次修改
$ git commit -m 'Create and edited test.txt'
[master (root-commit) 40a635b] Create and edited test.txt
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

参数说明:

  • git add 文件名是将此文件加入缓存区,也可以使用git add .将此目录加入缓存区
  • git commit-m参数是给此次提交的动作给一个描述,比如修改了什么地方,修复了什么Bug等
  • git add .git commit -m '描述'可以合并写为git commit -am '描述'

查看提交记录

文件修改后提交至缓存区后,便会生成一个提交记录的HEAD信息及其描述,在后续使用可以回滚到当前版本。好比于修改代码,越改越乱的情况,就可以直接回到上一个版本重新来写。

# 查看提交版本,commit后边的内容便是版本号,最后一行是注释信息
$ git log
commit c172fa948ab343276c84ec3bbf11d0c0cd027b3c
Author: isecret <[email protected]>
Date:   Sun Jul 23 12:57:36 2017 +0800

    Create and edited test.txt

查看修改记录及状态

这个顾名思义,查看当前版本的改动。在Github上能高亮显示出,不过在命令行也能查看到。

首先,我先在text.txt中再增加一段Hello World,然后查看改动:

# 增加一段Hello World!
$ vim test.txt
Hello Git!Hello World!
$ git diff
diff --git a/test.txt b/test.txt
index 106287c..d149c10 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-Hello Git!
+Hello Git! Hello World!
# 插入:2,内容 Thanks for us!
$ vim test.txt
# 查看当前状态
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test.txt

no changes added to commit (use "git add" and/or "git commit -a")

参数说明:

  • 直接使用git diff用于查看当前未git add的内容修改
  • 已经git add但还没提交,使用git diff --cached查看内容修改
  • git diff HEAD是上面两条的合并
  • git diff HEAD1 HEAD2 src可以比较两个版本的src文件夹的差异
  • git status会列出还没添加到缓存区的文件/目录

分支

分支在Git中是一个很重要的概念,意味着你能脱离主线开发,在不影响主线的情况下还能继续工作。

而分支又简单分为基础操作、冲突合并、分支管理、bug分支、远程分支。

查看分支

# 查看当前所有分支
$ git branch -a
* master

折腾完hexo,开始处理一些小细节,之前调试主题的时候就发现NexT并没有对代码进行压缩处理,详情见:如何优化NexT主题?

为何要压缩代码?

首先,没有比较就没有伤害:

压缩前后对比图

这是主页压缩前后的对比图,主要将多余空格和换行给去掉,CSS和JS同理。

压缩的优势?列出以下四点,欢迎补充:

  • 减小了文件的体积
  • 减小了网络传输量和带宽占用
  • 减小了服务器的处理的压力
  • 提高了页面的渲染显示的速度

gulp能做什么?

gulp是一款基于Node.js的一款利用数据流自动化构建工具,利用其插件可以对文件进行IO操作,其中包括压缩代码等功能。

gulp的安装

注:安装此插件务必确认安装Node环境及包管理工具(npm或cnpm)

任何一款js插件,首先是参考文档说明。详见:官方文档

首先,需要安装gulp及其配套的插件。

$ cd blogdir/
$ cnpm install gulp --save
$ cnpm install gulp-htmlclean --save
$ cnpm install gulp-htmlmin --save
$ cnpm install gulp-minify-css --save
$ cnpm install gulp-uglify --save

注:cnpm为淘宝npm镜像,如果发现cnpm提示command not found,请自行安装或使用npm,使用方法与npm相同,不过将镜像存储在国内加快包下载速度。

完成后查看package.json是否包含上列安装的包:

"dependencies": {
    "gulp": "^3.9.1",
    "gulp-htmlclean": "^2.7.14",
    "gulp-htmlmin": "^3.0.0",
    "gulp-imagemin": "^3.3.0",
    "gulp-minify-css": "^1.2.4",
    "gulp-uglify": "^3.0.0",
    "hexo": "^3.2.0",
    "hexo-deployer-git": "^0.3.0",
    "hexo-generator-archive": "^0.1.4",
    "hexo-generator-category": "^0.1.3",
    "hexo-generator-index": "^0.2.0",
    "hexo-generator-tag": "^0.2.0",
    "hexo-renderer-ejs": "^0.2.0",
    "hexo-renderer-marked": "^0.2.10",
    "hexo-renderer-stylus": "^0.3.1",
    "hexo-server": "^0.2.0"
  }

然后新建gulpfile.js文件到hexo根目录,内容如下:

var gulp = require('gulp');

//Plugins模块获取
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');

// 压缩 public 目录 css文件
gulp.task('minify-css', function() {
    return gulp.src('./public/**/*.css')
        .pipe(minifycss())
        .pipe(gulp.dest('./public'));
});

// 压缩 public 目录 html文件
gulp.task('minify-html', function() {
  return gulp.src('./public/**/*.html')
    .pipe(htmlclean())
    .pipe(htmlmin({
         removeComments: true,
         minifyJS: true,
         minifyCSS: true,
         minifyURLs: true,
    }))
    .pipe(gulp.dest('./public'))
});

// 压缩 public/js 目录 js文件
gulp.task('minify-js', function() {
    return gulp.src('./public/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./public'));
});


// 执行 gulp 命令时执行的任务
gulp.task('default', [
    'minify-html','minify-css','minify-js'
]);

至此,安装完成。

gulp的使用

gulp的使用很简单,只需要在部署之前将代码压缩即可:

$ hexo clean
$ hexo g
INFO  Start processing
INFO  Files loaded in 723 ms
INFO  Generated: index.html
$ gulp
[13:18:33] Using gulpfile ~/blog/gulpfile.js
[13:18:33] Starting 'minify-html'...
[13:18:33] Starting 'minify-css'...
[13:18:33] Starting 'minify-js'...
$ hexo d
INFO  Deploying: git
INFO  Clearing .deploy_git folder...
INFO  Copying files from public folder...