LAM(M)P:
L: linux
A: apache (httpd)
M: mysql, mariadb M:memcached
P: php, perl, python
先介绍下在centos7中快速安装:
#php为httpd的扩展安装
yum install httpd, php, php-mysql, mariadb-server
systemctl start httpd.service
systemctl start mariadb.service
#php-fpm安装
yum -y install httpd mariadb-server php-fpm php-mysql
systemctl start httpd
systemctl start mariadb
systemctl start php-fpm
httpd-2.4介绍
配置文件
/etc/httpd/conf/httpd.conf
/etc/httpd/conf.d/.conf
模块相关的配置文件:/etc/httpd/conf.modules.d/.conf
启动脚本
/usr/lib/systemd/system/httpd.service #脚本位置
systemctl enable|disable httpd.service #开机启动
systemctl {start|stop|restart|status} httpd.service #脚本控制
日志文件
/var/log/httpd/access_log:访问日志
/var/log/httpd/error_log:错误日志
MPM:Multipath processing Modules (多路处理模块)
1、prefork:多进程模型,每个进程响应一个请求;
- 一个主进程:负责生成子进程及回收子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
- n个子进程:每个子进程处理一个请求;
- 工作模型:会预先生成几个空闲进程,随时等待用于响应用户请求;最大空闲和最小空闲;
2、worker:多进程多线程模型,每线程处理一个用户请求; - 一个主进程:负责生成子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
- 多个子进程:每个子进程负责生成多个线程;
- 每个线程:负责响应用户请求;
- 并发响应数量:m*n
3、 event:事件驱动模型,多进程模型,每个进程响应多个请求; http2.4 event可以在生产上使用,但是prefork更加稳定 - 一个主进程 :负责生成子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
- 子进程:基于事件驱动机制直接响应多个请求;
httpd2.4 配置介绍
1、配置前言
主配置文件的最后一行引入 IncludeOptional conf.d/*.conf,所以私有设置尽量放着这个目录下,方便移除
语法测试 [root@ns1 conf.d]# httpd -t #重启 [root@ns1 www]# systemctl restart httpd #重载 [root@ns1 www]# systemctl reload httpd
2、端口设置
#默认端口在主配置文件上 端口添加不是覆盖 可重复使用
[root@ns1 conf.d]# vim /etc/httpd/conf.d/port.conf
Listen 8080
Listen 172.16.86.162:8081
3、长链接
KeepAlive 的值要根据网站的资源,跟请求时间得出一个合理值。 长时间占用会影响并发,tcp握手断开次数过多会增加服务器压力,对于web网站是一个很重要的优化值
KeepAlive On|Off
KeepAliveTimeout 15 #超时时间 默认秒 2.2版本只能到秒 2.4版本可以到毫秒 15ms
MaxKeepAliveRequests 100 #最大请求资源个数 时间跟数量哪个先到达就先断开
-----------------------------------------------------------
[root@ns1 conf.d]# vim /etc/httpd/conf.d/keepalive.conf
KeepAlive On
KeepAliveTimeout 15
MaxKeepAliveRequests 100
-----------------------------------------------------------
#测试
#如果off 请求完毕立马结束
#如果on 请求完毕后等待时间 或者资源数到最大值后退出
[root@ns1 conf.d]# telnet 192.168.1.102 80
Trying 192.168.1.102...
Connected to 192.168.1.102.
Escape character is '^]'.
GET /index.html HTTP/1.1
Host:192.168.1.102
4、MPM ab
#static静态编译模块无法任意卸载加载,固定的
#shared动态编译模块可以任意加载卸载,配置很方便
#静态编译模块说明
[root@node1 conf]# httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
#动态编译和静态编译
[root@node1 conf]# httpd -M
httpd: apr_sockaddr_info_get() failed for node1.marvin.com #httpd 不认识node1.marvin.com
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName # 这个是因为ServerName 完全限定名称没能得到反解
Loaded Modules:
core_module (static)
auth_basic_module (shared)
2.4的静态资源
[root@ns1 ~]# httpd -l #只有httpd一个
Compiled in modules:
core.c
mod_so.c
http_core.c
查看当前加载模块
[root@ns1 conf.d]# httpd -M|egrep '(event|worker|prefor)'
mpm_event_module (shared)
/_______________________________________________________
#配置选项
[root@ns1 conf.d]# vim /etc/httpd/conf.modules.d/00-mpm.conf
LoadModule mpm_worker_module modules/mod_mpm_worker.so
StartServers 8 服务启动后立即创建多少子进程
MinSpareServers 5 最小空闲子进程
MaxSpareServers 20 最大空闲子进程
ServerLimit 256 同时在生命周期内活动状态的最大子进程 这个值 ServerLimit <= MaxClients
MaxClients 256 最大启动子进程 如果最大子进程256 这里包含活动的 和 非活动的
MaxRequestsPerChild 4000 一个子进程最多能接4000次请求
StartServers 4 服务启动后立即创建多少子进程
MaxClients 300 每个子进程创建最大的线程数
MinSpareThreads 25 一共最小空闲线程
MaxSpareThreads 75 一共最大空闲线程
ThreadsPerChild 25 每个子进程启动后创建25个线程 默认配置 25*4 超出 75 然后在杀死一个进程
MaxRequestsPerChild 0 单个进程最大响应多少次 0不限制
官方说配置跟worker一样 event工作模式是每个进程能响应很大请求
StartServers 4 服务启动后立即创建多少子进程 最大个数跟cpu一样
MaxClients 300
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
[root@ns1 conf.d]# systemctl restart httpd
[root@ns1 conf.d]# httpd -M|egrep '(event|worker|prefor)'
mpm_worker_module (shared)
测压
mpm_prefork_module测压
1、测压mpm_prefork_module
marvindeMacBook-Pro:65 marvin$ ab -c 1000 -n 10000 http://192.168.1.102/manual/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.102 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Apache/2.4.6
Server Hostname: 192.168.1.102
Server Port: 80
Document Path: /manual/
Document Length: 8881 bytes #(供测试的URL返回的文档大小)
Concurrency Level: 1000 #并发 1000 请求10000次
Time taken for tests: 4.300 seconds #耗时
Complete requests: 10000 #总次数
Failed requests: 0 #失败次数
Total transferred: 91450000 bytes #报文首部(传输的总数据量)
HTML transferred: 88810000 bytes #body(HTML文档的总数据量)
Requests per second: 2325.48 [#/sec] (mean) #(平均每秒的请求数) 这个是非常重要的参数数值,服务器的吞吐量
Time per request: 430.019 [ms] (mean) #(所有并发用户(这里是1000)都请求一次的平均时间)
Time per request: 0.430 [ms] (mean, across all concurrent requests) #(单个用户都请求一次的平均时间)
Transfer rate: 20768.06 [Kbytes/sec] received #每秒获取的数据长度 (传输速率,单位:KB/s) 实际生产中这个带宽要 160Mbps
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 29 44.2 11 423 #链接
Processing: 15 241 642.9 46 4212 #处理请求
Waiting: 10 235 643.5 40 4211 #发送报文等待时间
Total: 22 270 648.1 61 4247 #最后一行是一个报文的最小 平均 中间 最大值
Percentage of the requests served within a certain time (ms)
50% 61
66% 152
75% 205
80% 215
90% 397
95% 1387
98% 2448
99% 4239
100% 4247 (longest request) #95%在合理时间内的话,有时候5%是可以牺牲下的
mpm_worker_module
marvindeMacBook-Pro:65 marvin$ ab -c 1000 -n 10000 http://192.168.1.102/manual/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.102 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Apache/2.4.6
Server Hostname: 192.168.1.102
Server Port: 80
Document Path: /manual/
Document Length: 8881 bytes
Concurrency Level: 1000
Time taken for tests: 4.313 seconds
Complete requests: 10000
Failed requests: 13
(Connect: 0, Receive: 0, Length: 13, Exceptions: 0)
Total transferred: 91417995 bytes
HTML transferred: 88778259 bytes
Requests per second: 2318.34 [#/sec] (mean)
Time per request: 431.343 [ms] (mean)
Time per request: 0.431 [ms] (mean, across all concurrent requests)
Transfer rate: 20697.06 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 45 70.4 13 1170
Processing: 10 224 520.6 54 4247
Waiting: 7 216 519.5 46 4244
Total: 21 269 532.4 94 4306
Percentage of the requests served within a certain time (ms)
50% 94
66% 204
75% 233
80% 274
90% 480
95% 907
98% 2416
99% 2613
100% 4306 (longest request)
mod_mpm_event
marvindeMacBook-Pro:65 marvin$ ab -c 1000 -n 10000 http://192.168.1.102/manual/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.102 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Apache/2.4.6
Server Hostname: 192.168.1.102
Server Port: 80
Document Path: /manual/
Document Length: 8881 bytes
Concurrency Level: 1000
Time taken for tests: 3.067 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 91450000 bytes
HTML transferred: 88810000 bytes
Requests per second: 3260.46 [#/sec] (mean) #吞吐量 明显大于上面2个
Time per request: 306.705 [ms] (mean)
Time per request: 0.307 [ms] (mean, across all concurrent requests)
Transfer rate: 29118.08 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 6 70 44.7 54 392
Processing: 10 193 248.7 115 2168
Waiting: 6 143 219.9 63 2167
Total: 26 263 254.5 205 2333
Percentage of the requests served within a certain time (ms)
50% 205
66% 243
75% 297
80% 329
90% 479
95% 704
98% 900
99% 1701
100% 2333 (longest request)
以上测压可以看到event的吞吐量最好,但是apache一般模式还是用prefork偏多,因为他相对稳定
5、目录访问控制
# Relax access to content within /var/www.
#这项说 /var/www 也可以做为文件跟目录,但是默认不目录在/var/www/html,需要设置DocumentRoot,或者个alias
#
Options Indexes FollowSymLinks
AllowOverride None
# Allow open access:
Require all granted
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
#Options None 关闭所有
#Options All 开启所有
#这两项说明 开启文件目录索引 链接文件可以被访问
Options Indexes FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
AllowOverride None
#基于IP控制:
# Require ip IP地址或网络地址
# Require not ip IP地址或网络地址
#基于主机名控制:
# Require host 主机名或域名
# Require not host 主机名或域名
#要放置于配置块中或配置块中;
#同意所有
Require all granted
#拒绝所有
#Require all denied
6、别名
Alias /cgi-bin/ "/var/www/cgi-bin/"
[root@ns1 httpd]# cd /var/www/cgi-bin/
[root@ns1 cgi-bin]# touch a.html
[root@ns1 cgi-bin]# echo 123 > a.html
[root@ns1 cgi-bin]# systemctl restart httpd
7、日志
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
CustomLog "logs/access_log" combined
[root@ns1 httpd]# cat logs/access_log
192.168.1.101 - - [12/May/2018:22:11:10 -0400] "GET / HTTP/1.1" 403 4897 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
---------------------------------------------------------------------------
LogFormat format strings:
%h:客户端IP地址;
%l:Remote User, 通常为一个减号(“-”);基于identd模块登入
%u:Remote user (from auth; may be bogus if return status (%s) is 401);非为登录访问时,其为一个减号; 基于auth登入有用
%t:服务器收到请求时的时间;
%r:First line of request,即表示请求报文的首行;记录了此次请求的“方法”,“URL”以及协议版本;
%>s:响应状态码;
%b:响应报文的大小,单位是字节;不包括响应报文的http首部;
%{Referer}i:请求报文中首部“referer”的值;即从哪个页面中的超链接跳转至当前页面的;
%{User-Agent}i:请求报文中首部“User-Agent”的值;即发出请求的应用程序;
%{headerkey}
日志存放位置
[root@ns1 httpd]# ll /etc/httpd
lrwxrwxrwx. 1 root root 19 May 11 21:15 logs -> ../../var/log/httpd
8、基本用户访问控制
basic 配置:
使用专用命令完成此类文件的创建及用户管理
htpasswd [options] /PATH/TO/HTTPD_PASSWD_FILE username
-c:自动创建此处指定的文件,因此,仅应该在此文件不存在时使用; #慎用
-m:md5格式加密
-s: sha格式加密
-D:删除指定用户
-b:批模式添加用户
htpasswd -b [options] /PATH/TO/HTTPD_PASSWD_FILE username password
------------------------------------------------------------------------------------
[root@ns1 httpd]# htpasswd -s -c test.users zander zander
[root@ns1 httpd]# htpasswd -b -m test.users tom tom
[root@ns1 httpd]# htpasswd -b -m test.users jerry jerry
[root@ns1 httpd]# htpasswd -b -m test.users jack 123456
[root@ns1 httpd]# cat test.users
jack:$apr1$4AM.U0Kk$9ZqiF4vHk/9R8TfpkxmPK1
tom:$apr1$L.PSF0Co$2V2Znhy6.3n10P4X9cTyP/
jerry:$apr1$GRULnii4$67yoYq8NuR5hnZJlAdq9F/
zander:{SHA}zS0U/xNGl8n4yzQjRDQ62OChq1s=
Options Indexes FollowSymLinks
AllowOverride None
AuthType Basic
AuthName "private area"
AuthDigestProvider file
AuthUserFile "/etc/httpd/test.users" #生产用.htpasswd
Require user jack tom jerry zander
#Require valid-user
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,cy;q=0.7
Authorization: Basic dG9tOnRvbQ== #base64 转码而已 base64("tom:tom") 所以是不安全的
Cache-Control: max-age=0
Connection: keep-alive
Host: 192.168.1.102
If-Modified-Since: Sun, 13 May 2018 03:36:07 GMT
If-None-Match: W/"3-56c0e11cec3ad"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
digest加密配置
#realm “digest” 必须跟 AuthName "digest" 要保持一直,否则验证不通过
[root@ns1 httpd]# htdigest -c test2.users "digest" tom
[root@ns1 httpd]# htdigest test2.users "digest" zander
Options Indexes FollowSymLinks
AllowOverride None
AuthType Digest
#AuthDigestDomain /
AuthName "digest"
AuthDigestProvider file
AuthUserFile "/etc/httpd/test2.users" #htdigest生产的文件 生产用.htpasswd
Require user jack tom jerry zander
#Require valid-user
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,cy;q=0.7
Authorization: Digest username="jack", realm="digest", nonce="lpFuDA5sBQA=2bcc3a585d202e95520cc3213cbe7ae4a978347d", uri="/", algorithm=MD5, response="7baab410ca5938d7886b4372ae832381", qop=auth, nc=00000007, cnonce="db374da2da3cd9b2"
Cache-Control: max-age=0
Connection: keep-alive
Host: 192.168.1.102
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
查看日志参数
[root@ns1 httpd]# cat logs/access_log #auth用户名已成功
192.168.1.101 - jack [12/May/2018:23:15:48 -0400] "GET /favicon.ico HTTP/1.1" 404 209 "http://192.168.1.102/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
9、虚拟主机
VirtualHost :81 VirtualHost ip:81 特别说明,这里最好要么全部ip,要么全部。
1、ip访问
[root@ns1 conf.d]# /etc/httpd/conf.d
[root@ns1 conf.d]# vim vhost.conf
ServerName www.ip.develop
DocumentRoot "/web/data/ip"
options None
AllowOverride None
Require all granted
ErrorLog "logs/ip_error_log"
CustomLog "logs/ip_access_log" combined
2、基于端口访问
[root@ns1 conf.d]# /etc/httpd/conf.d
[root@ns1 conf.d]# vim vhost.conf
Listen 81
ServerName www.port.develop
DocumentRoot "/web/data/port"
options None
AllowOverride None
Require all granted
ErrorLog "logs/port_error_log"
CustomLog "logs/port_access_log" combined
3、FQDN
#完全域名访问没必要加端口,这里只是实验而已,但是客户端域名解析必须能接到对对应ip地址
Listen 81
#
ServerName www.fqdn.develop
DocumentRoot "/web/data/fqdn"
options None
AllowOverride None
Require all granted
ErrorLog "logs/fqdn_error_log"
CustomLog "logs/fqdn_access_log" combined
-----------------------------------------------------------------
注意:如果是httpd-2.2,则使用基于FQDN的虚拟主机时,需要事先使用如下指令:
NameVirtualHost IP:PORT
9、status
LoadModule status_module modules/mod_status.so
httpd-2.2
SetHandler server-status
Order allow,deny
Allow from 172.16
httpd-2.4
SetHandler server-status
Require all granted #生产环境一定要注意
Listen 81
ServerName www.fqdn.develop
DocumentRoot "/web/data/fqdn"
options None
AllowOverride None
Require all granted
#/server-status 随意
SetHandler server-status #server-status 固定
Require all granted
ErrorLog "logs/port_error_log"
CustomLog "logs/port_access_log" combined
http://www.fqdn.develop:81/server-status
Apache Server Status for www.fqdn.develop (via 192.168.1.102)
Server Version: Apache/2.4.6 (CentOS)
Server MPM: worker
Server Built: Apr 20 2018 18:10:38
Current Time: Sunday, 13-May-2018 01:14:53 EDT
Restart Time: Sunday, 13-May-2018 01:11:03 EDT
Parent Server Config. Generation: 1
Parent Server MPM Generation: 0
Server uptime: 3 minutes 50 seconds
Server load: 0.00 0.01 0.05
Total accesses: 41 - Total Traffic: 141 kB
CPU Usage: u.01 s.01 cu0 cs0 - .0087% CPU load
.178 requests/sec - 627 B/second - 3521 B/request
1 requests currently being processed, 49 idle workers
........................._____W_________________________________
___________.....................................................
................................................................
................................................................
............................................
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request, 这个是worker模式 _表示可链接线程
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
Srv PID Acc M CPU SS Req Conn Child Slot Client VHost Request
1-0 97189 0/0/0 W 0.00 0 0 0.0 0.00 0.00 192.168.1.101 www.fqdn.develop:81 GET //server-status HTTP/1.1
1-0 97189 0/39/39 _ 0.02 184 0 0.0 0.14 0.14 192.168.1.101 www.port.develop:81 NULL
2-0 97191 0/2/2 _ 0.00 184 0 0.0 0.00 0.00 192.168.1.101 www.port.develop:81 NULL
Srv Child Server number - generation
PID OS process ID
Acc Number of accesses this connection / this child / this slot
M Mode of operation
CPU CPU usage, number of seconds
SS Seconds since beginning of most recent request
Req Milliseconds required to process most recent request
Conn Kilobytes transferred this connection
Child Megabytes transferred this child
Slot Total megabytes transferred this slot
10、压缩
压缩模块
[root@ns1 conf.d]# httpd -M |grep deflate
deflate_module (shared)
SetOutputFilter DEFLATE #对DEFLATE这类行进行压缩, 下面都是DEFLATE类型的
DeflateCompressionLevel 6 #9最高 1最低 6差不多行了
# Restrict compression to these MIME types
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/css
#以下几个是为了兼容 并非必须
# Netscape 4.x has some problems.
BrowserMatch ^Mozilla/4 gzip-only-text/html
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
# MSIE masquerades as Netscape, but it is fine
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
测试压缩
[root@ns1 ip]# ll
total 164
-rwxr-xr-x. 1 root root 155485 May 13 03:48 main.css
不开启压缩
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Length: 155485
Content-Type: text/css
Date: Sun, 13 May 2018 07:52:44 GMT
ETag: "25f5d-56c11973af074"
Keep-Alive: timeout=15, max=100
Last-Modified: Sun, 13 May 2018 07:48:11 GMT
Server: Apache/2.4.6 (CentOS)
开启压缩
[root@ns1 conf.d]# vim /etc/httpd/conf.d/compress.conf
setOutputFilter DEFLATE
DeflateCompressionLevel 6
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/css
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 17701 #明显少了很多
Content-Type: text/css
Date: Sun, 13 May 2018 07:54:30 GMT
ETag: "25f5d-56c11973af074-gzip"
Keep-Alive: timeout=15, max=100
Last-Modified: Sun, 13 May 2018 07:48:11 GMT
Server: Apache/2.4.6 (CentOS)
Vary: Accept-Encoding
11、https
私有证书请参考 https://blog.51cto.com/marvin89/2114273
Listen 443
#主要这里 配置多个的话 要么全部用ip 要么全部写*,不能混用
SSLEngine On
ServerName www.fqdn.develop:443
DocumentRoot "/web/data/fqdn"
SSLCertificateFile /etc/httpd/ssl/http.crt
SSLCertificateKeyFile /etc/httpd/ssl/http.key
SSLCACertificateFile /etc/httpd/ssl/http.cer
SSLVerifyClient require
SSLVerifyDepth 10
options None
AllowOverride None
Require all granted
ErrorLog "logs/port_error_log"
CustomLog "logs/port_access_log" combined
php集成安装
[root@ns1 port]# yum install php
[root@ns1 port]# rpm -ql php
/etc/httpd/conf.d/php.conf
[root@ns1 port]# cat /etc/httpd/conf.d/php.conf
#
# Cause the PHP interpreter to handle files with a .php extension.
#
SetHandler application/x-httpd-php
#
# Allow php to handle Multiviews
#
AddType text/html .php
#
# Add index.php to the list of files that will be served as directory
# indexes.
#
DirectoryIndex index.php
#
# Uncomment the following lines to allow PHP to pretty-print .phps
# files as PHP source code:
#
#
# SetHandler application/x-httpd-php-source
#
#
# Apache specific PHP configuration options
# those can be override in each configured vhost
#
php_value session.save_handler "files"
php_value session.save_path "/var/lib/php/session"
php-fpm安装
[root@ns1 ~]# yum install php-fpm
配置文件
[root@ns1 ~]# cd /etc/php-fpm.d/
[root@ns1 php-fpm.d]# ls
www.conf
[root@ns1 php-fpm.d]# cp www.conf{,.bak}
listen = 127.0.0.1:9000
;listen.backlog = -1 #-1 表示无限 半连接池
listen.allowed_clients = 127.0.0.1
pm = dynamic #static|dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500 #每个进程响应多少次之后杀掉
pm.status_path = /pm-status #内置状态页pm-status
ping.path = /ping #状态监测
ping.response = pong
;request_terminate_timeout = 0 #超时时间 0 不超时
#session
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
连接池:
pm = static|dynamic
static:固定数量的子进程;pm.max_children;
dynamic:子进程数据以动态模式管理;
pm.start_servers
pm.min_spare_servers
pm.max_spare_servers
;pm.max_requests = 500
[root@ns1 php-fpm.d]# ll -d /var/lib/php/session
drwxrwx---. 2 root apache 6 Apr 12 15:04 /var/lib/php/session
创建session目录,并确保运行php-fpm进程的用户对此目录有读写权限;
# mkdir /var/lib/php/session
# chown apache.apache /var/lib/php/session
启动脚本
[root@ns1 php-fpm.d]# systemctl start php-fpm
查看apache是否开启fcgi模块
[root@ns1 php-fpm.d]# httpd -M|grep cgi
proxy_fcgi_module (shared)
下面只要配置虚拟主机部分就行
(1) 配置httpd,添加/etc/httpd/conf.d/fcgi.conf配置文件,内容类似:
DirectoryIndex index.php
ProxyRequests Off
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/html/$1
(2) 虚拟主机配置
ServerName www.ip.develop
DocumentRoot "/web/data/ip"
ProxyRequests Off
ProxyPassMatch ^/(ping|pm-status)$ fcgi://127.0.0.1:9000/$1
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/web/data/ip/$1
DirectoryIndex index.php
options None
AllowOverride None
Require all granted
CustomLog "logs/ip_access_log" combined
mariadb
centos7默认安装Mariadb
yum install mysql-server
配置文件
[root@ns1 mysql]# vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
#添加关闭域名反解
skip-name-resolve=ON
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
数据库部分之后会做详细介绍,这里先略过了。
分享一段自动化安装脚本
python3运行环境,没有安装py3的朋友可以参考最下面一段安装脚本
目录结构:
install.py
#!/root/.virtualenvs/shellenv/bin/python
import os,sys,copy
import subprocess
import logging
import configparser
from concurrent.futures import ProcessPoolExecutor
class AppInstall:
package_path = '/www/packages'
log_path = '/www/packages/logs'
source_path = '/www/server/source'
link_path = '/www/server'
data_path = '/www/data'
mode='quiet'
def work(self,install='', mode='quiet'):
self.mode = mode
self.logname = install
self.current_dir = os.path.dirname(os.path.abspath(__file__))
self.init_workdir()
self.__logs()
print(install)
if install == 'apache':
self.start('conf/apache.yaml')
if install == 'php':
self.start('conf/php.yaml')
if install == 'php-fpm':
self.start('conf/php-fpm.yaml')
if install == 'mysql':
self.start('conf/mysql.yaml')
if install == 'nginx':
self.start('conf/nginx.yaml')
def start(self,configpath):
import yaml
config = yaml.load(open(configpath))
if not config:
self.__error(configpath+': is error ')
config = self.init_config(config)
os.chdir(self.package_path)
self.logger.info('-----------------------------start {name}---------------------------------'.format(name=config['name']))
if config.get('yum'):
self.do_yum(config['yum'])
if config.get('downloads') :
self.do_download(config['downloads'])
if config.get('cmds') :
self.foreach_cmds(config['cmds'])
if config.get('depends'):
for depend in config.get('depends'):
self.do_compile(depend['uncompress'], depend['uncompress_dir'], depend['compile'])
if config.get('compile'):
self.do_compile(config['uncompress'], config['uncompress_dir'], config['compile'])
if config.get('init').get('linkname'):
linkpath = self.link_path+'/'+config.get('init').get('linkname')
if not os.path.exists(linkpath):
self.__cmd('ln -sv {source_path}/{name}{version} {link_path}/{link_name}'.format(version=config['version'],
source_path=self.source_path,
link_path=self.link_path,
link_name=config.get('init').get('linkname'),
name=config['name']))
if config.get('init').get('cmds'):
self.foreach_cmds(config['init']['cmds'])
if config.get('init').get('systemctl'):
self.write_systemctl(config['init']['systemctl']['path'], config['init']['systemctl']['content'])
self.logger.info('-----------------------------finish {name}---------------------------------'.format(name=config['name']))
os.chdir(self.current_dir)
def init_config(self, config):
config = self.__init_denpends_config(config)
config_tmp = copy.deepcopy(config)
config_tmp = str(config_tmp)
config_tmp = config_tmp.replace('{version}', config["version"])
config_tmp = config_tmp.replace('{name}', config["name"])
config_tmp = config_tmp.replace('{source_path}', self.source_path)
config_tmp = config_tmp.replace('{link_path}', self.link_path)
config_tmp = config_tmp.replace('{data_path}', self.data_path)
config = eval(config_tmp)
config["downloads"]=[]
for key in config:
if key == 'download':
config["downloads"].append(config['download'])
if key == 'depends':
for i in config['depends']:
for j in i:
if j == 'download':
config["downloads"].append(i['download'])
return config
def __init_denpends_config(self, config):
if config.get('depends'):
depends = copy.deepcopy(config['depends'])
for i in depends:
config['depends'].remove(i)
for j in i :
i[j] = i[j].format(version=i['version'])
config['depends'].append(i)
return config
def foreach_cmds(self, cmds):
for cmd in cmds:
self.__cmd(cmd)
return True
def do_yum(self, yums):
for yum in yums:
self.__cmd(yum)
return True
def do_compile(self, uncompress, uncompress_dir, compile):
os.path.exists(uncompress_dir) and self.__cmd('rm -fr {uncompress_dir}'.format(uncompress_dir=uncompress_dir))
self.__cmd(uncompress)
if compile:
self.__cmd('cd '+uncompress_dir+' && ' + compile)
def do_download(self, downloads):
os.chdir(self.package_path)
for url in downloads:
arr_url = url.split(' -O ')
if len(arr_url) == 2:
filename = self.package_path + '/' + arr_url[-1].strip()
else:
filename = self.package_path + '/' + os.path.basename(url)
if not os.path.isfile(filename):
if not self.__cmd('wget '+url, False):
self.__remove(filename)
sys.exit(1)
return True
def init_workdir(self):
os.path.exists(self.package_path) or os.makedirs(self.package_path)
os.path.exists(self.link_path) or os.makedirs(self.link_path)
os.path.exists(self.source_path) or os.makedirs(self.source_path)
os.path.exists(self.data_path) or os.makedirs(self.data_path)
os.path.exists(self.log_path) or os.makedirs(self.log_path)
def write_systemctl(self, path, data={}):
config = configparser.ConfigParser()
config.optionxform = str
self.configparser = config
for key in data:
config[key] = data[key]
config.write(open(path, 'w'))
def __cmd(self, cmd, isexit=True):
print('doing............'+cmd)
if self.mode == 'quiet':
res = subprocess.getstatusoutput(cmd)
else:
tmp = os.system(cmd)
res=[]
res.append(tmp)
res.append('debug')
if res[0] != 0:
self.logger.error(cmd + ' ' + res[1])
if isexit:
sys.exit(1)
else:
return False
else:
self.logger.info(cmd)
return True
def __remove(self,filename):
os.path.isfile(filename) and os.remove(filename)
def __logs(self):
print(self.log_path+'/'+self.logname+'.logs')
logger = logging.getLogger('log1')
fh = logging.FileHandler(self.log_path+'/'+self.logname+'.logs')
ch = logging.StreamHandler()
fm = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
fh.setFormatter(fm)
ch.setFormatter(fm)
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)
logger.addHandler(ch)
self.logger = logger
def __error(self,data):
self.logger.error(data)
exit(1)
if __name__ == '__main__':
pydepends = ['pyyaml']
for i in pydepends:
os.system('/root/.virtualenvs/shellenv/bin/pip install requests -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com '+i)
pools = ProcessPoolExecutor(4)
# installs = ['apache', 'php-fpm', 'mysql']
installs = ['apache']
appobj = AppInstall()
for app in installs:
pools.submit(appobj.work,app, 'debug')
pools.shutdown(wait=True)
print('-----------------------Installed ^_^ All-----------------------')
conf/apache.yaml
name: apache
version: 2.4.33
download: http://mirrors.hust.edu.cn/apache/httpd/httpd-{version}.tar.gz
cmds:
- id apache || useradd -r -M -s /sbin/nologin apache
yum:
- yum -y groupinstall "Development tools"
- yum -y install pcre-devel wget zlib-devel openssl-devel expat-devel
- yum -y update openssl
uncompress: tar xf httpd-{version}.tar.gz
uncompress_dir: httpd-{version}
compile: ./configure --prefix={source_path}/{name}{version}
--sysconfdir={source_path}/{name}{version}/conf
--enable-so
--enable-ssl
--enable-fcgi
--enable-cgi
--enable-deflate
--enable-rewrite
--with-zlib
--with-pcre
--with-apr=/usr/local/apr
--with-apr-util=/usr/local/apr-util
--enable-modeles=most
--enable-mpms-shared=all
--with-mpm=event
&& make && make install
depends:
- name: apr
version: 1.6.3
download: http://mirrors.shu.edu.cn/apache/apr/apr-{version}.tar.gz
uncompress: tar xf apr-{version}.tar.gz
uncompress_dir: apr-{version}
compile: ./configure --prefix=/usr/local/apr && make && make install
- name: apr-util
version: 1.6.1
download: http://mirror.bit.edu.cn/apache/apr/apr-util-{version}.tar.bz2
uncompress: tar xf apr-util-{version}.tar.bz2
uncompress_dir: apr-util-{version}
compile: ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && make && make install
init:
linkname: apache
cmds:
- echo 'export PATH={link_path}/{name}/bin:$PATH'>/etc/profile.d/httpd.sh
- "cat {source_path}/{name}{version}/conf/httpd.conf|egrep '^IncludeOptional conf' || echo 'IncludeOptional conf/conf.d/*.conf'>>{source_path}/{name}{version}/conf/httpd.conf"
- '[ -d {source_path}/{name}{version}/conf/conf.d ] || mkdir {source_path}/{name}{version}/conf/conf.d'
- sed -i 's#^User daemon$#User apache#' {source_path}/{name}{version}/conf/httpd.conf
- sed -i 's#^Group daemon$#Group apache#' {source_path}/{name}{version}/conf/httpd.conf
systemctl:
path: /etc/systemd/system/myhttpd.service
content:
Unit:
Description: The Apache HTTP Server
After: network.target remote-fs.target nss-lookup.target
Documentation: man:httpd(8)
Documentation: man:apachectl(8)
Service:
Type: forking
PIDFILE: '{link_path}/{name}/logs/httpd.pid'
ExecStart: '{link_path}/{name}/bin/apachectl start'
ExecReload: '{link_path}/{name}/bin/apachectl graceful'
ExecStop: '{link_path}/{name}/bin/apachectl stop'
PrivateTmp: true
LimitNOFILE: infinity
Install:
WantedBy: multi-user.target
conf/php
name: php
version: 7.2.5
download: http://hk2.php.net/distributions/php-{version}.tar.gz
yum:
- yum -y groupinstall "Development tools"
- yum install -y freetype-devel libpng-devel gd-devel libcurl-devel libjpeg-turbo-devel libxslt-devel zlib-devel libxml2-devel libiconv-devel bzip2-devel libmcrypt-devel
uncompress: tar xf php-{version}.tar.gz
uncompress_dir: php-{version}
compile: ./configure --prefix={source_path}/{name}{version}
--enable-mysqlnd
--with-mysqli=mysqlnd
--with-openssl
--with-pdo-mysql=mysqlnd
--enable-mbstring
--with-freetype-dir
--with-jpeg-dir
--with-png-dir
--with-zlib
--with-iconv
--enable-zip
--with-libxml-dir
--with-gd
--enable-xml
--enable-sockets
--with-apxs2=/www/server/apache/bin/apxs
--with-config-file-path={source_path}/{name}{version}/conf
--with-config-file-scan-dir={source_path}/{name}{version}/php.d
--enable-maintainer-zts
--enable-opcache
--enable-session
--with-curl
--enable-maintainer-zts
--enable-fileinfo
&& make && make install
init:
linkname: php
cmds:
- mkdir {source_path}/{name}{version}/conf
- mkdir {source_path}/{name}{version}/conf.d
- cd php-{version} && cp php.ini-production {source_path}/{name}{version}/conf/php.ini
conf/php-fpm
name: php-fpm
version: 7.2.5
download: http://hk2.php.net/distributions/php-{version}.tar.gz
yum:
- yum -y groupinstall "Development tools"
- yum install -y freetype-devel libpng-devel gd-devel libcurl-devel libjpeg-turbo-devel libxslt-devel zlib-devel libxml2-devel libiconv-devel bzip2-devel libmcrypt-devel
uncompress: tar xf php-{version}.tar.gz
uncompress_dir: php-{version}
compile: ./configure --prefix={source_path}/{name}{version}
--enable-mysqlnd
--with-mysqli=mysqlnd
--with-openssl
--with-pdo-mysql=mysqlnd
--enable-mbstring
--with-freetype-dir
--with-jpeg-dir
--with-png-dir
--with-zlib
--with-iconv
--enable-zip
--with-libxml-dir
--with-gd
--enable-xml
--enable-sockets
--enable-fpm
--with-config-file-path={source_path}/{name}{version}/conf
--with-config-file-scan-dir={source_path}/{name}{version}/php.d
--enable-maintainer-zts
--enable-opcache
--enable-session
--with-curl
--enable-maintainer-zts
--enable-fileinfo
&& make && make install
init:
linkname: php-fpm
cmds:
- '[ -d /www/server/source/php-fpm7.2.5/conf ] || mkdir {source_path}/{name}{version}/conf'
- '[ -d /www/server/source/php-fpm7.2.5/conf.d ] || mkdir {source_path}/{name}{version}/conf.d'
- '[ -f {source_path}/{name}{version}/conf/php.ini ] || cp php-{version}/php.ini-production {source_path}/{name}{version}/conf/php.ini'
- '[ -f {source_path}/{name}{version}/etc/php-fpm.conf ] || cp {source_path}/{name}{version}/etc/php-fpm.conf.default {source_path}/{name}{version}/etc/php-fpm.conf'
- '[ -f {source_path}/{name}{version}/etc/php-fpm.d/www.conf ] || cp {source_path}/{name}{version}/etc/php-fpm.d/www.conf.default {source_path}/{name}{version}/etc/php-fpm.d/www.conf'
systemctl:
path: /etc/systemd/system/myphp-fpm.service
content:
Unit:
Description: Description=The PHP FastCGI Process Manager
After: syslog.target network.target
Service:
Type: forking
PIDFILE: '{link_path}/{name}/var/run/php-fpm.pid'
ExecStart: '{link_path}/{name}/sbin/php-fpm'
ExecReload: '/bin/kill -USR2 $MAINPID'
PrivateTmp: true
Install:
WantedBy: multi-user.target
conf/mysql
name: mysql
version: 5.7.22
download: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-{version}-linux-glibc2.12-x86_64.tar.gz
yum:
- yum -y groupinstall "Development tools"
- yum -y install readline-devel zlib-devel openssl-devel libaio*
cmds:
- 'tar xf mysql-{version}-linux-glibc2.12-x86_64.tar.gz && cp -r mysql-{version}-linux-glibc2.12-x86_64 {source_path}/{name}{version}'
- 'id mysql || useradd -r -s /sbin/nologin -M mysql'
- '[ -d {data_path}/mysql/data ] || mkdir {data_path}/mysql/data -pv'
- '[ -d {data_path}/mysql/log-bin ] || mkdir {data_path}/mysql/log-bin -pv'
- '[ -d {source_path}/{name}{version}/etc ] || mkdir {source_path}/{name}{version}/etc -pv'
- 'chown -R mysql:mysql {data_path}/mysql/'
- 'chown -R mysql:mysql {source_path}/{name}{version}'
- 'rm -fr {data_path}/mysql/data/*'
- '{source_path}/{name}{version}/bin/mysqld --explicit_defaults_for_timestamp --initialize --user=mysql --datadir={data_path}/mysql/data/ --basedir={source_path}/{name}{version}&>{source_path}/{name}{version}/tmpPasswd.txt'
- '{source_path}/{name}{version}/bin/mysql_ssl_rsa_setup --datadir={data_path}/mysql/data/'
- 'chown -R root.root {source_path}/{name}{version}/'
init:
linkname: mysql
cmds:
- '[ -f {source_path}/{name}{version}/bin/mysql.server ] || cp {source_path}/{name}{version}/support-files/mysql.server {source_path}/{name}{version}/bin/'
- sed -i 's#^basedir=$#basedir={link_path}/{name}#' {source_path}/{name}{version}/bin/mysql.server
- sed -i 's#^datadir=$#datadir={data_path}/mysql/data/#' {source_path}/{name}{version}/bin/mysql.server
- echo 'export PATH={link_path}/{name}/bin:$PATH'>/etc/profile.d/mysql.sh
systemctl:
path: /etc/systemd/system/mysql.service
content:
Unit:
Description: Description=Mysql database server
After: syslog.target network.target
Service:
Type: forking
User: mysql
Group: mysql
PIDFILE: '{data_path}/mysql/data/localhost.localdomain.pid'
ExecStart: '{link_path}/{name}/bin/mysql.server start'
ExecReload: '{link_path}/{name}/bin/mysql.server stop'
Install:
WantedBy: multi-user.target
以上脚本安装lamp,下载时间除外,安装大概12分钟
python3 自动化安装脚本
#!/usr/bin/python
#coding=utf-8
import os,sys
version='3.6.5'
package_path='/www/packages'
source_path='/www/server/source'
link_path='/www/server/python'
res1 = os.system('yum install zlib zlib-devel -y')
res2 = os.system('yum install wget -y')
res3 = os.system('yum groupinstall "Development tools" -y')
if res1 != 0 or res2 != 0 or res3 != 0:
print '依赖安装失败'
sys.exit(1)
if os.getuid() == 0:
pass
else:
print '需要root用户运行'
sys.exit(1)
if not os.path.exists(package_path):
os.makedirs(package_path)
if not os.path.exists(source_path):
os.makedirs(source_path)
os.chdir(package_path)
print os.getcwd()
downloadurl = 'https://www.python.org/ftp/python/{version}/Python-{version}.tgz'.format(version=version)
#
#下载
if not os.path.isfile('Python-{version}.tgz'.format(version=version)):
cmd = 'wget '+downloadurl
print cmd
res = os.system(cmd)
if res != 0:
os.path.exists('Python-{version}.tgz'.format(version=version)) and os.remove('Python-{version}.tgz'.format(version=version))
print '下载失败'
sys.exit(1)
#
os.path.exists('Python-{version}'.format(version=version)) and os.system('rm -fr Python-{version}'.format(version=version))
cmd = 'tar xf Python-{version}.tgz'.format(version=version)
res = os.system(cmd)
if res != 0:
print '解压失败'
sys.exit(1)
os.path.exists('{source_path}/python{version}'.format(version=version,source_path=source_path)) and os.system('rm -fr {source_path}/python{version}'.format(version=version,source_path=source_path))
cmd = 'cd Python-{version} && ./configure --prefix={source_path}/python{version} && make && make install'.format(version=version,source_path=source_path)
res = os.system(cmd)
if res != 0:
print '编译失败'
sys.exit(1)
if not os.path.exists('{link_path}/python{version}'.format(version=version,link_path=link_path)):
res = os.system('ln -sv {source_path}/python{version} {link_path}'.format(version=version,source_path=source_path,link_path=link_path))
if res != 0:
print 'ln -sv error'
sys.exit(1)
####------init----------
res = os.system('ln -sv {link_path}/bin/python3.6 /usr/local/bin/'.format(link_path=link_path))
if res != 0:
print 'ln -sv /usr/local/bin/python3.6 error'
sys.exit(1)
res = os.system('ln -sv {link_path}/bin/pip3.6 /usr/local/bin/'.format(link_path=link_path))
if res != 0:
print 'ln -sv /usr/local/bin/pip3.6 error'
sys.exit(1)
#
res = os.system('ln -sv {link_path}/bin/virtualenv /usr/local/bin/'.format(link_path=link_path))
if res != 0:
print 'ln -sv /usr/local/bin/virtualenv error'
sys.exit(1)
res = os.system('pip3.6 install requests -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com virtualenvwrapper')
if res != 0:
print 'pip3.6 install virtualenvwrapper error'
sys.exit(1)
else:
os.system('echo "export WORKON_HOME=$HOME/.virtualenvs" >> ~/.bashrc')
os.system('echo "export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3.6" >> ~/.bashrc')
os.system('echo "source /www/server/python/bin/virtualenvwrapper.sh" >> ~/.bashrc')
res = os.system('source ~/.bashrc && mkvirtualenv shellenv')
if res != 0:
print 'mkvirtualenv shellenv'
sys.exit(1)
print 'init python finish'