Author: 云厉

UNIX/Linux命令行提示符显示当前完整路径的方法

查看默认方式:

vim /etc/bashrc

PS1='\h:\W \u\$ '

我们先了解命令释义:

  • \u 当前用户账号
  • \h 当前主机名
  • \W 当前路径最后一个目录
  • \w 当前绝对路径(当前用户目录会以 ~代替)
  • $PWD 当前全路径
  • \$ 显示命令行’$'或者’#'符号

知道命令代表的意义后,
如果要修改命令提示符的显示方式,我们可以修改环境变量PS1

  1. 命令行提示符完全显示完整的工作目录名称:
    PS1='[\u@\h $PWD]\$ '

  2. 命令行提示符只列出最后一个目录:
    PS1='[\u@\h \W]\$ '

  3. 命令行提示符显示完整工作目录,当前用户目录会以 ~代替:
    PS1='[\u@\h \w]\$ '

修改完成后,执行: source /etc/bashrc 使配置生效即可。

当然,如果你不想改变全局,只想改变当前用户的,则 vim ~/.bashrc 即可

秒懂系列|Apache和NGINX退出自动重启

有时候,我们的Web服务器如Apache、NGINX可能因为某些原因退出了,这时候如果没有及时发现,就会影响服务,所以搞个自动重启是很有必要滴

Apache

#!/bin/sh
HTTPD_NUM=`ps aux | grep -P "(bin/httpd)|(./httpd)" | grep -v "vim" | grep -v "grep" | wc -l`
if [ ${HTTPD_NUM} -eq 0 ]; then
    /usr/local/apache/bin/apachectl restart
fi

Nginx

#!/bin/sh
NGINX_NUM=`ps aux | grep -P "nginx" | grep -v "vim" | grep -v "grep" | wc -l`
if [ ${NGINX_NUM} -eq 0 ]; then
    /usr/local/nginx/sbin/nginx
fi

加入crontab,每分钟检查一次

* * * * * /bin/bash /data/cron/apache_restart.sh > /dev/null 2 >& 1
* * * * * /bin/bash /data/cron/nginx_restart.sh > /dev/null 2 >&1

原理很简单,就是判断是否有进程,如果木有了,执行重启操作!

-bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

[code lang="shell"]
./configure --prefix=/usr/local/jpeg --enable-shared --enable-static
[/code]

-bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

今天在编译 jpeg-6b 的时候,出现一行这样的错误,

看见 ^M 就联想到了 Window 下的 dos 格式
[code lang="shell"]
vim ./configure
[/code]

:set ff
fileformat=dos

我X,果然是!

这是 Linux 和 Windows 换行符的差异导致的,
说明 configure 这个文件是作者在 Window 写的,并且没有将文件格式设置成 unix 格式(一般的编辑器都有这项设置),
所以在 Linux 打开时,在每行后面会加个 ctrl+m 就是 ^M
所以 /bin/sh 就变成了 /bin/sh^M
所以脚本就不能运行了
[code lang="shell"]dos2unix configure[/code]
我把文件格式转换之后,就OK了!

如果你的系统不支持 dos2unix,你也可以
[code lang="shell"]
vim ./configure
[/code]

:set ff=unix
:wq

用10条命令在1分钟内检查Linux服务器性能

如果你的Linux服务器突然负载暴增,告警短信快发爆你的手机,如何在最短时间内找出Linux性能问题所在?来看Netflix性能工程团队的这篇博文,看它们通过十条命令在一分钟内对机器性能问题进行诊断。

通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解。

  • uptime
  • dmesg | tail
  • vmstat 1
  • mpstat -P ALL 1
  • pidstat 1
  • iostat -xz 1
  • free -m
  • sar -n DEV 1
  • sar -n TCP,ETCP 1
  • top

其中一些命令需要安装sysstat包,有一些由procps包提供。这些命令的输出,有助于快速定位性能瓶颈,检查出所有资源(CPU、内存、磁盘IO等)的利用率(utilization)、饱和度(saturation)和错误(error)度量,也就是所谓的USE方法。

下面我们来逐一介绍下这些命令,有关这些命令更多的参数和说明,请参照命令的手册。

uptime

$ uptime
23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02

这个命令可以快速查看机器的负载情况。在Linux系统中,这些数据表示等待CPU资源的进程和阻塞在不可中断IO进程(进程状态为D)的数量。这些数据可以让我们对系统资源使用有一个宏观的了解。

命令的输出分别表示1分钟、5分钟、15分钟的平均负载情况。通过这三个数据,可以了解服务器负载是在趋于紧张还是区域缓解。如果1分钟平均负载很高,而15分钟平均负载很低,说明服务器正在命令高负载情况,需要进一步排查CPU资源都消耗在了哪里。反之,如果15分钟平均负载很高,1分钟平均负载较低,则有可能是CPU资源紧张时刻已经过去。

上面例子中的输出,可以看见最近1分钟的平均负载非常高,且远高于最近15分钟负载,因此我们需要继续排查当前系统中有什么进程消耗了大量的资源。可以通过下文将会介绍的vmstat、mpstat等命令进一步排查。

dmesg | tail

$ dmesg | tail
[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[...]
[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request. Check SNMP counters.

该命令会输出系统日志的最后10行。示例中的输出,可以看见一次内核的oom kill和一次TCP丢包。这些日志可以帮助排查性能问题。千万不要忘了这一步。

vmstat 1

$ vmstat 1
procs ---------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
34 0 0 200889792 73708 591828 0 0 0 5 6 10 96 1 3 0 0
32 0 0 200889920 73708 591860 0 0 0 592 13284 4282 98 1 1 0 0
32 0 0 200890112 73708 591860 0 0 0 0 9501 2154 99 1 0 0 0
32 0 0 200889568 73712 591856 0 0 0 48 11900 2459 99 0 0 0 0
32 0 0 200890208 73712 591860 0 0 0 0 15898 4840 98 1 1 0 0

vmstat(8) 命令,每行会输出一些系统核心指标,这些指标可以让我们更详细的了解系统状态。后面跟的参数1,表示每秒输出一次统计信息,表头提示了每一列的含义,这几介绍一些和性能调优相关的列:

r:等待在CPU资源的进程数。这个数据比平均负载更加能够体现CPU负载情况,数据中不包含等待IO的进程。如果这个数值大于机器CPU核数,那么机器的CPU资源已经饱和。
free:系统可用内存数(以千字节为单位),如果剩余内存不足,也会导致系统性能问题。下文介绍到的free命令,可以更详细的了解系统内存的使用情况。
si, so:交换区写入和读取的数量。如果这个数据不为0,说明系统已经在使用交换区(swap),机器物理内存已经不足。
us, sy, id, wa, st:这些都代表了CPU时间的消耗,它们分别表示用户时间(user)、系统(内核)时间(sys)、空闲时间(idle)、IO等待时间(wait)和被偷走的时间(stolen,一般被其他虚拟机消耗)。
上述这些CPU时间,可以让我们很快了解CPU是否出于繁忙状态。一般情况下,如果用户时间和系统时间相加非常大,CPU出于忙于执行指令。如果IO等待时间很长,那么系统的瓶颈可能在磁盘IO。

示例命令的输出可以看见,大量CPU时间消耗在用户态,也就是用户应用程序消耗了CPU时间。这不一定是性能问题,需要结合r队列,一起分析。

mpstat -P ALL 1

$ mpstat -P ALL 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
07:38:49 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
07:38:50 PM all 98.47 0.00 0.75 0.00 0.00 0.00 0.00 0.00 0.00 0.78
07:38:50 PM 0 96.04 0.00 2.97 0.00 0.00 0.00 0.00 0.00 0.00 0.99
07:38:50 PM 1 97.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 2.00
07:38:50 PM 2 98.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
07:38:50 PM 3 96.97 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.03

该命令可以显示每个CPU的占用情况,如果有一个CPU占用率特别高,那么有可能是一个单线程应用程序引起的。

pidstat 1

$ pidstat 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
07:41:02 PM UID PID %usr %system %guest %CPU CPU Command
07:41:03 PM 0 9 0.00 0.94 0.00 0.94 1 rcuos/0
07:41:03 PM 0 4214 5.66 5.66 0.00 11.32 15 mesos-slave
07:41:03 PM 0 4354 0.94 0.94 0.00 1.89 8 java
07:41:03 PM 0 6521 1596.23 1.89 0.00 1598.11 27 java
07:41:03 PM 0 6564 1571.70 7.55 0.00 1579.25 28 java
07:41:03 PM 60004 60154 0.94 4.72 0.00 5.66 9 pidstat
07:41:03 PM UID PID %usr %system %guest %CPU CPU Command
07:41:04 PM 0 4214 6.00 2.00 0.00 8.00 15 mesos-slave
07:41:04 PM 0 6521 1590.00 1.00 0.00 1591.00 27 java
07:41:04 PM 0 6564 1573.00 10.00 0.00 1583.00 28 java
07:41:04 PM 108 6718 1.00 0.00 0.00 1.00 0 snmp-pass
07:41:04 PM 60004 60154 1.00 4.00 0.00 5.00 9 pidstat

pidstat命令输出进程的CPU占用率,该命令会持续输出,并且不会覆盖之前的数据,可以方便观察系统动态。如上的输出,可以看见两个JAVA进程占用了将近1600%的CPU时间,既消耗了大约16个CPU核心的运算资源。

iostat -xz 1

$ iostat -xz 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
73.96 0.00 3.73 0.03 0.06 22.21
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvda 0.00 0.23 0.21 0.18 4.52 2.08 34.37 0.00 9.98 13.80 5.42 2.44 0.09
xvdb 0.01 0.00 1.02 8.94 127.97 598.53 145.79 0.00 0.43 1.78 0.28 0.25 0.25
xvdc 0.01 0.00 1.02 8.86 127.79 595.94 146.50 0.00 0.45 1.82 0.30 0.27 0.26
dm-0 0.00 0.00 0.69 2.32 10.47 31.69 28.01 0.01 3.23 0.71 3.98 0.13 0.04
dm-1 0.00 0.00 0.00 0.94 0.01 3.78 8.00 0.33 345.84 0.04 346.81 0.01 0.00
dm-2 0.00 0.00 0.09 0.07 1.35 0.36 22.50 0.00 2.55 0.23 5.62 1.78 0.03

iostat命令主要用于查看机器磁盘IO情况。该命令输出的列,主要含义是:

r/s, w/s, rkB/s, wkB/s:分别表示每秒读写次数和每秒读写数据量(千字节)。读写量过大,可能会引起性能问题。
await:IO操作的平均等待时间,单位是毫秒。这是应用程序在和磁盘交互时,需要消耗的时间,包括IO等待和实际操作的耗时。如果这个数值过大,可能是硬件设备遇到了瓶颈或者出现故障。
avgqu-sz:向设备发出的请求平均数量。如果这个数值大于1,可能是硬件设备已经饱和(部分前端硬件设备支持并行写入)。
%util:设备利用率。这个数值表示设备的繁忙程度,经验值是如果超过60,可能会影响IO性能(可以参照IO操作平均等待时间)。如果到达100%,说明硬件设备已经饱和。
如果显示的是逻辑设备的数据,那么设备利用率不代表后端实际的硬件设备已经饱和。值得注意的是,即使IO性能不理想,也不一定意味这应用程序性能会不好,可以利用诸如预读取、写缓存等策略提升应用性能。

free –m

$ free -m
total used free shared buffers cached
Mem: 245998 24545 221453 83 59 541
-/+ buffers/cache: 23944 222053
Swap: 0 0 0

free命令可以查看系统内存的使用情况,-m参数表示按照兆字节展示。最后两列分别表示用于IO缓存的内存数,和用于文件系统页缓存的内存数。需要注意的是,第二行-/+ buffers/cache,看上去缓存占用了大量内存空间。这是Linux系统的内存使用策略,尽可能的利用内存,如果应用程序需要内存,这部分内存会立即被回收并分配给应用程序。因此,这部分内存一般也被当成是可用内存。

如果可用内存非常少,系统可能会动用交换区(如果配置了的话),这样会增加IO开销(可以在iostat命令中提现),降低系统性能。

sar -n DEV 1

$ sar -n DEV 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
12:16:48 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
12:16:49 AM eth0 18763.00 5032.00 20686.42 478.30 0.00 0.00 0.00 0.00
12:16:49 AM lo 14.00 14.00 1.36 1.36 0.00 0.00 0.00 0.00
12:16:49 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
12:16:49 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
12:16:50 AM eth0 19763.00 5101.00 21999.10 482.56 0.00 0.00 0.00 0.00
12:16:50 AM lo 20.00 20.00 3.25 3.25 0.00 0.00 0.00 0.00
12:16:50 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

sar命令在这里可以查看网络设备的吞吐率。在排查性能问题时,可以通过网络设备的吞吐量,判断网络设备是否已经饱和。如示例输出中,eth0网卡设备,吞吐率大概在22 Mbytes/s,既176 Mbits/sec,没有达到1Gbit/sec的硬件上限。

sar -n TCP,ETCP 1

$ sar -n TCP,ETCP 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
12:17:19 AM active/s passive/s iseg/s oseg/s
12:17:20 AM 1.00 0.00 10233.00 18846.00
12:17:19 AM atmptf/s estres/s retrans/s isegerr/s orsts/s
12:17:20 AM 0.00 0.00 0.00 0.00 0.00
12:17:20 AM active/s passive/s iseg/s oseg/s
12:17:21 AM 1.00 0.00 8359.00 6039.00
12:17:20 AM atmptf/s estres/s retrans/s isegerr/s orsts/s
12:17:21 AM 0.00 0.00 0.00 0.00 0.00

sar命令在这里用于查看TCP连接状态,其中包括:

active/s:每秒本地发起的TCP连接数,既通过connect调用创建的TCP连接;
passive/s:每秒远程发起的TCP连接数,即通过accept调用创建的TCP连接;
retrans/s:每秒TCP重传数量;
TCP连接数可以用来判断性能问题是否由于建立了过多的连接,进一步可以判断是主动发起的连接,还是被动接受的连接。TCP重传可能是因为网络环境恶劣,或者服务器压力过大导致丢包。

top

$ top
top - 00:15:40 up 21:56, 1 user, load average: 31.09, 29.87, 29.92
Tasks: 871 total, 1 running, 868 sleeping, 0 stopped, 2 zombie
%Cpu(s): 96.8 us, 0.4 sy, 0.0 ni, 2.7 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 25190241+total, 24921688 used, 22698073+free, 60448 buffers
KiB Swap: 0 total, 0 used, 0 free. 554208 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20248 root 20 0 0.227t 0.012t 18748 S 3090 5.2 29812:58 java
4213 root 20 0 2722544 64640 44232 S 23.5 0.0 233:35.37 mesos-slave
66128 titancl+ 20 0 24344 2332 1172 R 1.0 0.0 0:00.07 top
5235 root 20 0 38.227g 547004 49996 S 0.7 0.2 2:02.74 java
4299 root 20 0 20.015g 2.682g 16836 S 0.3 1.1 33:14.42 java
1 root 20 0 33620 2920 1496 S 0.0 0.0 0:03.82 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:05.35 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:06.94 kworker/u256:0
8 root 20 0 0 0 0 S 0.0 0.0 2:38.05 rcu_sched

top命令包含了前面好几个命令的检查的内容。比如系统负载情况(uptime)、系统内存使用情况(free)、系统CPU使用情况(vmstat)等。因此通过这个命令,可以相对全面的查看系统负载的来源。同时,top命令支持排序,可以按照不同的列排序,方便查找出诸如内存占用最多的进程、CPU占用率最高的进程等。

但是,top命令相对于前面一些命令,输出是一个瞬间值,如果不持续盯着,可能会错过一些线索。这时可能需要暂停top命令刷新,来记录和比对数据。

总结

排查Linux服务器性能问题还有很多工具,上面介绍的一些命令,可以帮助我们快速的定位问题。例如前面的示例输出,多个证据证明有JAVA进程占用了大量CPU资源,之后的性能调优就可以针对应用程序进行。

FROM:http://www.infoq.com/cn/news/2015/12/linux-performance

HTML也可以实现文件包含

我们知道,很多编程语言都有包含文件的功能,所以代码结构相对比较灵活,
但HTML作为一种文本标记语言,默认是不支持文件包含的!
但是,我们可以通过配置Web服务器让HTML支持文件包含!

SSI(Server Side Include),通常称为"服务器端嵌入"或者叫"服务器端包含",是一种类似ASP基于服务器的网页制作技术。
默认扩展名是 .stm、.shtm 和 .shtml
但我们常用的是是html,如果要在扩展名为 html 的文件使用SSI,就需要对 Apache 进行配置

以 Apache2.2 为例,编辑 httpd.conf,

1、搜索 AddType 和 AddOutputFilter,源码如下:

# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
# AddType text/html .shtml
# AddOutputFilter INCLUDES .shtml

默认是被注释的,需要去掉注释,修改成如下:

# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
AddType text/html .html .shtml
AddOutputFilter INCLUDES .html .shtml

2、搜索 Options Indexes FollowSymLinks 在后面加上 INCLUDES

注意,SSI 确实可以利用 Shell 来执行命令,这个功能是极度危险的,因为它会执行任何包含在 exec 标记中的命令。
如果用户有可能修改你的网页内容,那么你一定要关闭这个功能。
可以在 Options 指令中加上 IncludesNOEXEC 参数,以关闭 exec 功能,同时又保留 SSI。

<Directory /usr/local/www/979137.com>
    Options Includes FollowSymLinks
    AllowOverride None
</Directory>

3、重启Apache,可以使用 include 语法了,如:

<!--#include virtual="/header.html" -->

include 元素能按 file 属性或 virtual 属性判断应该包含的文件。
file 属性是一个相对于当前目录的文件路径,即不能是一个绝对路径(以"/"开头)或包含"../"的路径。
virtual 属性可能更有用,它是一个相对于被提供的文档的URL ,可以以"/"开头,但必须与被提供的文档位于同一服务器上。

Linux实现IP和端口转发方法

应用场景举例:
实现下面两个Shell

mysql -h10.13.34.119 -P3306 -uroot -p123456
mysql -h10.13.34.120 -P3307 -uroot -p123456

都是同样访问 10.13.34.119:3306 这个数据库服务器
这时候我们就需要将 10.13.34.120:3307 映射到 10.13.34.119:3306 了

第一种:利用iptable

iptables,大家都知道,网络防火墙,就是用于实现Linux下访问控制的东东
先打开IP转发:

echo 1 > /proc/sys/net/ipv4/ip_forward

添加NAT规则,并重启iptables:

service iptables stop
iptables -t nat -A PREROUTING --dst 10.13.34.119 -p tcp --dport 3306 -j DNAT --to-destination 10.13.34.120:3307
iptables -t nat -A POSTROUTING --dst 10.13.34.120 -p tcp --dport 3307 -j SNAT --to-source 10.13.34.119
service iptables save
service iptables start

第二种:使用SSH协议转发

ssh的三个强大的端口转发命令:
- 转发到远端:ssh -C -f -N -g -L 本地端口:目标IP:目标端口 用户名@目标IP
- 转发到本地:ssh -C -f -N -g –R 本地端口:目标IP:目标端口 用户名@目标IP
- ssh -C -f -N -g -D listen_port user@Tunnel_Host

这里我们使用第一种,只需在 10.13.34.120 这个机器执行以下命令:

ssh -C -f -N -g root@10.121.34.119 -L 3307:10.121.34.119:3306

-C :压缩数据传输。
-f :后台认证用户/密码,通常和 -N 连用,不用登录到远程主机。
-N :不执行脚本或命令,通常与 -f 连用。
-g :在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。
-L :转发规则,本地端口:目标IP:目标端口

如此,当你使用

mysql -h10.13.34.120 -P3307 -uroot -p123456

时,就会自动转发到 10.121.34.119:3306

Discuz在新浪云空间实现URL伪静态

新浪云SAE云空间在分布式基础上,几乎实现了普通虚拟主机全兼容的环境,但还是有一点点区别,比如URL Rewrite,新浪云空间实现URL Rewrite是通过在根目录编写一个 .appconfig 来实现的,同时在规则上也有一些区别

官方提供了一个原生 .htaccess 到 .appconfig 的转换工具:
http://htaccess.applinzi.com
我试了下 Discuz 的 Rewrite,转换后,发现没什么软用

RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/topic-(.+)\.html$ portal.php?mod=topic&topic=$1&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/article-([0-9]+)-([0-9]+)\.html$ portal.php?mod=view&aid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/forum-(\w+)-([0-9]+)\.html$ forum.php?mod=forumdisplay&fid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ forum.php?mod=viewthread&tid=$1&extra=page\%3D$3&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/group-([0-9]+)-([0-9]+)\.html$ forum.php?mod=group&fid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/space-(username|uid)-(.+)\.html$ home.php?mod=space&$1=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/blog-([0-9]+)-([0-9]+)\.html$ home.php?mod=space&uid=$1&do=blog&id=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/archiver/(fid|tid)-([0-9]+)\.html$ archiver/index.php?action=$1&value=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^/data1/www/htdocs/711//1/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ plugin.php?id=$1:$2&%1[

下面是我改写的、亲测有效的 Rewrite 规则:

RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/topic-(.+)\.html$ portal.php?mod=topic&topic=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/article-([0-9]+)-([0-9]+)\.html$ portal.php?mod=view&aid=$2&page=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/forum-(\w+)-([0-9]+)\.html$ forum.php?mod=forumdisplay&fid=$2&page=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ forum.php?mod=viewthread&tid=$2&extra=page\%3D$4&page=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/group-([0-9]+)-([0-9]+)\.html$ forum.php?mod=group&fid=$2&page=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/space-(username|uid)-(.+)\.html$ home.php?mod=space&$2=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/blog-([0-9]+)-([0-9]+)\.html$ home.php?mod=space&uid=$2&do=blog&id=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/(fid|tid)-([0-9]+)\.html$ index.php?action=$2&value=$3&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ plugin.php?id=$2:$3&%1

php –with-mysqli=mysqlnd –with-pdo-mysql=mysqlnd

1、什么是mysqlnd驱动?

PHP手册上的描述:

MySQL Native Driver is a replacement for the MySQL Client Library (libmysql).
MySQL Native Driver is part of the official PHP sources as of PHP 5.3.0

mysqldnd即MySQL Native Driver简写,即是由PHP源码提供的mysql驱动连接代码,它的目的是代替旧的libmysql驱动。

传统的安装php的方式中,我们在编译PHP时,一般需要指定以下几项:

--with-mysql=/usr/local/mysql
--with-mysqli=/usr/local/mysql
--with-pdo-mysql=/usr/local/mysql

这实际上就是使用了MySQL官方自带的libmysql驱动,这是比较老的驱动,PHP5.3开始已经不建议使用它了,而建议使用mysqlnd

2、PDO与mysqlnd, libmysql又是何种关系?

PDO是一个应用层抽象类,底层和mysql server连接交互需要mysql驱动的支持。也就是说无论你使用了何种驱动,都可以使用PDO.
PDO提供了PHP应用程序层API接口,而mysqlnd,libmysql则负责与mysql server进行网络协议交互(它并不提供php应用程序层API功能)

3、为何要使用mysqlnd驱动?

PHP官方手册描述:

A.libmysql驱动是由mysql AB公司(现在是oracle公司)编写, 并按mysql license许可协议发布,所以在PHP中默认是被禁用的.
而mysqlnd是由php官方开发的驱动,以php license许可协议发布,故就规避了许可协议和版权的问题

B.因为mysqlnd内置于PHP源代码,故你在编译安装php时就不需要预先安装mysql server也可以提供mysql client API (mysql_connect, pdo , mysqli), 这将减化一些工作量.

C. mysqlnd是专门为php优化编写的驱动,它使用了PHP本身的特性,在内存管理,性能上比libmysql更有优势. php官方的测试是:libmysql将每条记录在内存中保存了两份,而mysqlnd只保存了一份

D. 一些新的或增强的功能
增强的持久连接
引入特有的函数mysqli_fetch_all()
引入一些性能统计函数mysqli_get_cache_stats(), mysqli_get_client_stats(),
mysqli_get_connection_stats(),
使用上述函数,可很容易分析mysql查询的性能瓶颈!
SSL支持(从php 5.3.3开始有效)
压缩协议支持
命名管道支持(php 5.4.0开始有效)

4、看到这里,你可能跃跃欲试,很想使用mysqlnd驱动

提示: 如果使用mysqlnd,并不需要预先安装mysql
编译php时,修改以下几个项参数即可
[code lang="shell"]--with-mysql=mysqlnd
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd [/code]

Starting MySQL… ERROR! The server quit without updating PID file

刚编译完 MySQL 遇到这个问题?? 别着急,下面是本人总结,据说看完的99%都解决了!

1、你初始化数据库了吗??[code]/usr/local/mysql/bin/mysql_install_db [/code]

2016-05-25 19:56:18 [WARNING] mysql_install_db is deprecated. Please consider switching to mysqld --initialize
2016-05-25 19:56:18 [ERROR] The data directory needs to be specified.

我的是 MySQL 5.7,新版已经改成用 mysqld --initialize 来初始化数据库了[code]/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql[/code]注意:
1)后面的参数一定要加上,--user代表运行用户,--basedir代表MySql安装目录,--datadir代表数据库数据所在目录,每个人的配置不一样,根据自己的编译参数修改一下。
2)执行前,请先清空编译前指定的datadir,默认是在安装目录的data/(我编译时指定在了/data/mysql),否则会报如下错误:

--initialize specified but the data directory has files in it. Aborting.
2016-05-25T12:07:27.006980Z 0 [ERROR] Aborting

2、可能是 datadir 目录没有写的权限
[code]chown -R mysql:mysql /data/mysql && chmod -R 755 /data/mysql[/code]
3、错误日志文件没有权限(根据你的编译参数和my.cnf查看你的错误文件路径)
[code][chown -R mysql:mysql /var/log/mysqld.log && chmod -R 755 /var/log/mysqld.log[/code]
4、可能进程里已经存在mysql进程[code]ps -ef | grep mysql[/code]如果有使用 “kill -9 进程号” 杀死,然后重新启动mysqld!

5、可能是第二次在机器上安装MySQL,有残余数据影响了服务的启动。
清空之前的 datadir 目录,和MySQL安装目录,如果存在mysql-bin.index,就赶快把它删除掉吧。

6、MySQL在启动时没有指定配置文件时会使用 /etc/my.cnf 配置文件,请打开这个文件查看在[mysqld]节下有没有指定数据目录(datadir)。
请在[mysqld]下设置这一行:[code]datadir = /data/mysql[/code]
7、skip-federated字段问题
检查一下/etc/my.cnf文件中有没有没被注释掉的 skip-federated 字段,如果有就立即注释掉吧。

8、selinux惹的祸,如果是centos系统,默认会开启selinux
关闭它,打开/etc/selinux/config,把SELINUX=enforcing改为SELINUX=disabled后存盘退出重启机器试试。

PHP也支持多线程:cURL并发请求

PHP cURL所有函数列表:
https://secure.php.net/manual/zh/ref.curl.php

以下是PHP中cURL多线程相关函数:

  • curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄
  • curl_multi_close — 关闭一组cURL句柄
  • curl_multi_exec — 运行当前 cURL 句柄的子连接
  • curl_multi_getcontent — 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流
  • curl_multi_info_read — 获取当前解析的cURL的相关传输信息
  • curl_multi_init — 返回一个新cURL批处理句柄
  • curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
  • curl_multi_select — 等待所有cURL批处理中的活动连接
  • curl_multi_setopt — 为 cURL 并行处理设置一个选项
  • curl_multi_strerror — Return string describing error code

一般来说,想到要用这些函数时,目的显然应该是要同时请求多个URL,而不是一个一个依次请求,否则不如自己循环去调curl_exec好了。

步骤总结如下:

1、调用 curl_multi_init,初始化一个批处理handle
2、循环调用 curl_multi_add_handle,往1中的批处理handle 添加curl_init来的子handle
3、持续调用 curl_multi_exec,直到所有子handle执行完毕。
4、根据需要循环调用 curl_multi_getcontent 获取结果
5、调用 curl_multi_remove_handle,并为每个字handle调用curl_close
6、调用 curl_multi_close

以下是一个通过并发请求抓取网页的demo

$urls = array(
    'https://979137.com/',
    'http://www.sina.com.cn/',
    'http://www.sohu.com/',
    'http://www.163.com/'
);

//1、初始化一个批处理handle
$mh = curl_multi_init();

//2、往批处理handle 添加curl_init来的子handle
foreach ($urls as $i => $url) {
    $conn[$i] = curl_init($url);
    curl_setopt($conn[$i], CURLOPT_HEADER, 0);   
    curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT, 60);
    curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($mh, $conn[$i]);
}

//3、并发执行,直到全部结束。
do {
    curl_multi_exec($mh, $active);
} while ($active);

//4、获取结果
foreach ($urls as $i => $url) {
    $data = curl_multi_getcontent($conn[$i]);
    echo ($data);
}

//5、移除子handle,并close子handle
foreach ($urls as $i => $url) {
    curl_multi_remove_handle($mh,$conn[$i]);
    curl_close($conn[$i]);
}

//6、关闭批处理handle
curl_multi_close($mh);

微信公众号:程序员到架构师

最新文章

Return Top