CentOS系统Apache访问速度慢

原文链接:
http://www.cnblogs.com/kevingrace/p/6211887.html
http://www.2cto.com/os/201303/194028.html

网站初期,他没有做相应的优化,在后续网站并发突增,访问十分缓慢。
登陆服务器,具体现象为:
1)uptime查看负载较高;
2)ss -a(或netstat命令)查看连接数较多,并且WAIT_TIME比较多;
3)apache日志显示prefork工作模式下的并发连接数设置有问题;[mpm_prefork:error] [pid 13848] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
4)重启apache服务后,网站暂时访问稍快,但过一会后又十分缓慢。

针对上面的现象,做了一些优化操作后,网站高并发下访问正常,速度很快。操作记录如下:
1)修改apache的最大并发连接数(默认是256)
有日志报错可知,apache采用的是默认的prefork模式(使用apache2 -l或httpd -l命令也能查看处理 )
找到mpm_prefork.conf文件进行连接数的修改(若是work模式,就修改mpm_worker.conf)
[root@wang ~]# vim /etc/apache2/mods-available/mpm_prefork.conf
<IfModule mpm_prefork_module>
StartServers                     10
MinSpareServers               10
MaxSpareServers              20
ServerLimit                      2000
MaxRequestWorkers         1500
MaxConnectionsPerChild    10000
</IfModule>

说明:
手动添加ServerLimit,这个才是修改apache最大并发连接数的参数设置,一定要将它放在MaxRequestWorkers的前面,并且它的值也一定要大于MaxRequestWorkers的值。如上设置,apache的最大并发连接数设置为2000个。
其他的配置:
StartServers         定服务器启动时建立的子进程数量,prefork默认为5
MinSpareServers   指定空闲子进程的最小数量,默认为5。如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。
MaxSpareServers  设置空闲子进程的最大数量,默认为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不要设的太大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成”MinSpareServers+1″。
MaxRequestWorkers   最大数量的服务器进程允许开始;这个参数是这些中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。
MaxConnectionsPerChild   每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为”0″,子进程将永远不会结束。
将MaxRequestsPerChild设置成非零值有两个好处:
1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

重启apache服务(最好是先stop,然后再start)
在/etc/apache2/apache2.conf文件中添加ServerName localhost,去掉apache服务启动中的告警信息。
[root@wang ~]# /etc/init.d/apache2 stop
[root@wang ~]# /etc/init.d/apache2 start

2)修改内核参数,解决WAIT_TIME过多的问题
添加下面四行内容
[root@wang ~]# vim /etc/sysctl.conf
……
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30

[root@wang ~]# sysctl -p

调大系统最大打开的文件数
[root@wang ~]# ulimit -n 65535

Centos 添加SWAP(交换分区)

1.进入目录

cd /var/

2.获取要增加的SWAP文件块(这里以1GB为例)

dd if=/dev/zero of=swapfile bs=1024 count=1038336

3.创建SWAP文件

/sbin/mkswap swapfile

4.激活SWAP文件

/sbin/swapon swapfile

5.查看SWAP信息是否正确

/sbin/swapon –s

6.添加到fstab文件中让系统引导时自动启动

echo “/var/swapfile swap swap defaults 0 0” >>/etc/fstab

上面这步也可以修改/etc/fstab,末尾加入/var/swapfile swap swap defaults 0 0

add-swap

Centos7上搭建SVN服务器并实现自动同步至web目录

前言

由于最近跟学长一起合作完成一个小项目,然后我俩比较熟悉的版本控制是SVN,就考虑着在服务器上搭建一个SVN服务器。现在在这里给出简单的搭建过程。
(其实吧,能用Git就尽量用git吧,好处自己百度,有关搭建请参考我的另一篇博客搭建服务器上的GIT并实现自动同步到站点目录(www),这篇博客与git搭建的过程应该是基本一样的)

预期目的:

1、仓库放在 /var/svn/ 目录下,并且仓库名为 project

2、创建用户组lsgogroup,该组下添加两个成员lsgoweb1、lsgoweb2,密码直接用用户名,两用户可以checkout代码和提交代码

3、利用SVN的钩子实现当仓库的代码更新的时候自动同步至我们的web目录,在这里,我的web目录在 /home/www/ 下

一、搭建svn环境并创建仓库:

1、安装Subversion:

yum install -y subversion

2、检测是否安装成功(查看svn版本号)

svnserve --version

3、创建版本库

//先建目录
mkdir /var/svn
cd /var/svn
//创建版本库
svnadmin create /var/svn/project
cd project
//会看到自动生成的版本库文件
conf  db  format  hooks  locks  README.txt

至此,svn环境搭建成功。

二、创建用户组及用户:

1、 进入版本库中的配置目录conf,此目录有三个文件: svn服务综合配置文件(svnserve.conf)、 用户名口令文件(passwd)、权限配置文件(authz)。

2、修改权限配置文件:vim authz

3、配置用户名命令文件:vim passwd

4、配置SVN服务综合配置文件svnserve.conf

//找到以下配置项,将前面的#号去掉,然后做相应的配置
anon-access = none  //匿名用户访问权限:无
auth-access = write     //普通用户访问权限:读、写
password-db = passwd        //密码文件
authz-db = authz        //权限配置文件
realm = /var/svn/project    //版本库所在1

注意:所有以上的配置项都需要顶格,即前面不能预留空格,否则报错

5、启动svn服务:

svnserve -d -r /var/svn

如果提示:

svnserve: E000098: Can't bind server socket: Address already in use

证明现在svn已经被启动了,由于我们修改了配置文件,因此要重启svn服务

//查看svn服务详情
ps aux | grep svn
//将svn服务强制停止  其中790为svn服务的ID号,-9是kill的参数
kill -9 790

或者用

killall svnserve

再运行 svnserve -d -r /var/svn,进行启动服务

6、测试服务器:

//我们在web目录测试(/home/www)
cd /home/www
svn co svn://localhost/project

如果提示:Checked out revision 1.  表示checkout成功

我们添加新文件来测试是否提交成功

cd /home/www
touch index.php
svn add index.php   //成功的话会显示  A index.php
svn commit index.php -m "测试提交文件"

假如最后提示:

Adding         index.php
Transmitting file data .
Committed revision 2.

则表示我们svn服务器搭建成功!文件已经能够推送了。

7、本地拉取、推送

在本地首先要安装SVN吧,具体百度。。。

填写信息:

点击ok,提示输入用户名和密码

就填刚才我们创建的lsgoweb1或lsgoweb2,和对应的密码即可。

三、实现svn更新自动同步到web目录:

1、在web目录中checkout版本库

这一步算是比较关键的一步了,当时我搭建的时候试了无数次,就是缺少了这一步。把刚才checkout的版本库删掉,我们来一次比较正式的checkout:

svn co svn://localhost/project /home/www --username lsgoweb1(SVN账号) --lsgoweb1(SVN密码)

进入/var/svn/project/hooks下,建立post-commit文件:

cd /var/svn/project/hooks
vim post-commit

//在该文件里添加如下代码,保存
#!/bin/sh
#设定环境变量,如果没有设定可能会出现update报错
#设定语言,根据系统语言设置,如果是GBK就设置为 LANG=zh_CN.GBK
export LANG=en_US.utf8
SVN_PATH=/usr/bin/svn   //这里不用改
WEB_PATH=/home/www  //web目录,如果你的不同,可以改
//这里的用户随便一个就好
$SVN_PATH update $WEB_PATH --username 'lsgoweb1' --password 'lsgoweb1' --no-auth-cache

保存退出。

修改post-commit用户为www目录用户

chown apache:apache post-commit     //我的 /home/www 的用户组和所有者都是apache

给post-commit 执行权限:

chmod 755 post-commit

麻蛋,终于写完了。。。。

本博客主要参考了:  1、centos7.0搭建SVN服务器  2、CentOS创建SVN 服务器,并且设置自动同步到WEB目录  感谢原作者。

让PHP以ROOT权限执行系统命令的方法

原文地址:http://www.jb51.net/article/26232.htm

用来作为解决php以root权限执行一些普通用户不能执行的命令或应用的参考。
其实php里的popen()函数是可以解决这个问题的,但是由于某些版本的linux(如我使用的Centos 5)对系统安全的考虑,
使得这个问题解决起来麻烦了好多。先来看一个网友使用popen()函数的例子。

复制代码代码如下:
/* PHP中如何增加一个系统用户
下面是一段例程,增加一个名字为james的用户,
root密码是 louis。仅供参考
*/
$sucommand = “su root –command”;
$useradd = “/scripts/demo/runscripts.php”;
$rootpasswd = “louis”;
$user = “james”;
$user_add = sprintf(“%s %s”,$sucommand,$useradd);
$fp = @popen($user_add,”w”);
@fputs($fp,$rootpasswd);
@pclose($fp);

经过自己的测试,证实此段代码是不能实现(至少在我的系统里是这样的)作者想要获得的结果的。经过自己很长时间的google之后,
问题的关键是su root这个命令需要的密码必须以终端的方式输入,不能通过其它的方式(我也不知道还有没有其它的方式)获得。
又由于项目要求不能使用类似于sudo这种应用,无奈之下,我选择了网友提出的用编写C程序的方法来解决此问题。
首先写个C程序,命名为:run.c 放在目录/scripts/demo/下

复制代码代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
uid_t uid ,euid;
//char cmd[1024]; //变量暂时未使用
uid = getuid() ;
euid = geteuid();
printf(“my uid :%u\n”,getuid()); //这里显示的是当前的uid 可以注释掉.
printf(“my euid :%u\n”,geteuid()); //这里显示的是当前的euid
if(setreuid(euid, uid)) //交换这两个id
perror(“setreuid”);
printf(“after setreuid uid :%u\n”,getuid());
printf(“afer sertreuid euid :%u\n”,geteuid());
system(“/scripts/demo/runscripts.php”); //执行脚本
return 0;
}

编译该文件:
gcc -o run -Wall run.c
在该路径下生成run文件,这个可执行文件。如果现在用PHP脚本调用 该run的话,即使setreuid了 也是不行的。
接下来要做的是:给run赋予suid权限
# chmod u+s run
# ls
# -rwsr-xr-x 1 root root 5382 Jul 2 21:45 run
好了,已经设置上了,再写一个php页面调用它。

复制代码代码如下:
<?php
echo ‘<pre>’;
$last_line = system(‘/scripts/demo/run’, $retval);
echo ‘
</pre>
<hr />Last line of the output: ‘ . $last_line . ‘
<hr />Return value: ‘ . $retval;
?>

在浏览器中浏览。
my uid :48
my euid :0
after setreuid uid :0
afer sertreuid euid :48

——————————————————————————–
Last line of the output: afer sertreuid euid :48
——————————————————————————–
Return value: 0
该命令执行成功。
从显示结果可以看出: apache(daemon)的uid 为48(事实上很多linux系统下daemon的uid为2)。
调用setreuid后将有效用户id和实际用户id互换了。(必须在chmod u+s生效的情况下) 使apache当前的uid为0这样就能执行root命令了。
只需要更改 C文件中的system所要执行的命令就可以实现自己的PHP以root角色执行命令了。

在玩C 以前 玩过一段时间的PHP, 哪个时候需要用PHP 来运行root命令,一直未果,直到有一天搜索到了super这个插件.
随着玩C的日子多了.发现可以用C语言来包裹 要运行的外部命令. 实验了一下.成功了.
不需要任何外部工具就可以实现用PHP 执行root命令.
我下面就把方法发布给大家,有需求用php来运行root命令的朋友可以不用发愁了.
平台:Linux. 实验命令iptables 当前的目录是/var/www/html/http
写程序的时候 用root用户
大家都知道iptables 非root用户不能运行.
首先写个C程序
命名为:ipt.c

复制代码代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
uid_t uid ,euid;
uid = getuid() ;
euid = geteuid();
printf(“my uid :%u\n”,getuid()); //这里显示的是当前的uid 可以注释掉.
printf(“my euid :%u\n”,geteuid()); //这里显示的是当前的euid
if(setreuid(euid, uid)) //交换这两个id
perror(“setreuid”);
printf(“after setreuid uid :%u\n”,getuid());
printf(“afer sertreuid euid :%u\n”,geteuid());
system(“/sbin/iptables -L”); //执行iptables -L命令
return 0;
}

编译该文件 gcc -o ipt -Wall ipt.c
在该路径下生成ipt 这个可执行文件.
如果现在用PHP网页调用 该ipt的话,即使setreuid了 也是不行的.
接下来要做的是chmod u+s ./ipt
ls 一下
-rwsr-xr-x 1 root root 5382 Jul 2 21:45 ipt
s位已经设置上了.
再写一个php页面调用它.

复制代码代码如下:
<?php
echo ‘<pre>’;
$last_line = system(‘/var/www/html/http/ipt’, $retval);
echo ‘
</pre>
<hr />Last line of the output: ‘ . $last_line . ‘
<hr />Return value: ‘ . $retval;
?>

在浏览器中浏览.

[color=Red]Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all — anywhere anywhere state RELATED,ESTABLISHED
Chain OUTPUT (policy ACCEPT)
target prot opt source destination [/color]
[color=Blue]my uid :48
my euid :0
after setreuid uid :0
afer sertreuid euid :48[/color]

——————————————————————————–
Last line of the output: afer sertreuid euid :48
——————————————————————————–
Return value: 0

该命令执行成功..
众所周知: apache的uid 为48. 调用setreuid后 将有效用户id 和实际用户id互换了.(必须在chmod u+s生效的情况下) 使apache当前的 uid为0 这样就能执行root命令了。

大家只需要更改 C文件中的 system所要执行的命令就可以实现自己的PHP执行root命令了.

linux下使用crontab定时备份MYSQL数据库的方法

原文地址:http://my.oschina.net/u/919074/blog/223920

只需按照下面3步做,一切都在你的掌控之下:

第一步:在服务器上配置备份目录代码:

——————————————————————————–

mkdir /var/lib/mysqlbackup

cd /var/lib/mysqlbackup

——————————————————————————–

第二步:编写备份脚本代码:

——————————————————————————–

vi dbbackup.sh

——————————————————————————–

粘帖以下代码,务必更改其中的username,password和dbname。

代码:

——————————————————————————–

#!/bin/sh

mysqldump -uuser -ppassword dbname | gzip > /var/lib/mysqlbackup/dbname`date +%Y-%m-%d_%H%M%S`.sql.gz

cd  /var/lib/mysqlbackup

rm -rf `find . -name ‘*.sql.gz’ -mtime 10`  #删除10天前的备份文件

——————————————————————————–

第三步:更改备份脚本权限

代码:

——————————————————————————–

chmod +x dbbackup.sh

——————————————————————————–

第四步:用crontab定时执行备份脚本代码:

——————————————————————————–

crontab -e

——————————————————————————–

若每天晚上21点00备份,添加如下代码,

代码:

——————————————————————————–

00 21 * * * /var/lib/mysqlbackup/dbbackup.sh

注:

1、任务调度设置文件的写法
可用crontab -e命令来编辑,编辑的是/var/spool/cron下对应用户的cron文件,也可以直接修改/etc/crontab文件
具体格式如下:
Minute Hour Day Month Dayofweek   command
分钟     小时   天     月       天每星期       命令
每个字段代表的含义如下:
Minute             每个小时的第几分钟执行该任务
Hour               每天的第几个小时执行该任务
Day                 每月的第几天执行该任务
Month             每年的第几个月执行该任务
DayOfWeek     每周的第几天执行该任务
Command       指定要执行的程序
在这些字段里,除了“Command”是每次都必须指定的字段以外,其它字段皆为可选

字段,可视需要决定。对于不指定的字段,要用“*”来填补其位置。
举例如下:
5       *       *           *     *     ls             指定每小时的第5分钟执行一次ls命令
30     5       *           *     *     ls             指定每天的 5:30 执行ls命令
30     7       8         *     *     ls             指定每月8号的7:30分执行ls命令
30     5       8         6     *     ls             指定每年的6月8日5:30执行ls命令
30     6       *           *     0     ls             指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,

以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

30     3     10,20     *     *     ls     每月10号及20号的3:30执行ls命令[注:“,”用来连接多个不连续的时段]

25     8-11 *           *     *     ls       每天8-11点的第25分钟执行ls命令[注:“-”用来连接连续的时段]

*/15   *       *           *     *     ls         每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

30   6     */10         *     *     ls       每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls 命令。 ]

每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件

50   7       *             *     *     root     run-parts     /etc/cron.daily   [ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]

2、新增调度任务可用两种方法:
1)、在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。
2)、直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。

CentOS中禁止用户ssh和sftp登陆

在linux中出于安全的需要,我们会禁止某些用户SSH登陆系统进行操作。我这里以centos操作系统为例记录下如何进行处理。

1、打开sshd的配置文件

  1. vi/etc/ssh/sshd_config

2、修改该配置文件,增加或修改如下行

  1. # 禁止用户user1登陆,多个空格分隔
  2. DenyUsers user1
  3. # 禁止用户组group1的所有用户登录,多个空格分隔
  4. DenyGroups group1

3、保存配置后,重启sshd

  1. /etc/rc.d/init.d/sshd restart

完成上面的配置后,就可以禁止用户或用户组的用户进行登录了,第2步中的两个是可以只填一个的,可以根据需要进行调整。配置完毕后,在其他linux机器上使用如下命令进行测试:

  1. # 使用ssh测试
  2. [root@ServerA ~]# ssh user1@192.168.1.168
  3. user1@192.168.1.168’s password:
  4. Permission denied, please try again.
  5. # 使用sftp测试
  6. [root@ServerA ~]# sftp user1@192.168.1.168
  7. user1@192.168.1.168’s password:
  8. Permission denied, please try again.

可以看到,确实被系统禁止了,从而也就完成了我们想要的控制了。但这个有一个缺陷是,无法禁止只允许sftp而不允许ssh,如果要这样做,估计只能够单独搭建ftp服务器,比如vsftp,后续再考虑这个。

给VSFTP增加用户,只能访问指定目录

1 增加组 groupadd ftpgroup
2 修改/etc/vsftpd/vsftpd.conf
将底下三行
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd.chroot_list
改为
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list
3 增加用户 useradd -g ftpgroup -d /var/ftp/pub/ftpuser_file  -M ftpuser
4 设置用户口令 passwd ftpuser
5 编辑文件: /etc/vsftpd/chroot_list
内容为ftp用户名,每个用户占一行,如:
peter
john
6 重新启动vsftpd
[root@home vsftpd]# /sbin/service vsftpd restart

无法查看目录,提示:vsftpd Transfer done (but failed to open directory)

系统是CentOS,是RH派系的。把vsftpd安装配置好了,以为大功告成,但客户端访问提示如下错误:
vsftpd Transfer done (but failed to open directory)
原因是CentOS系统安装了SELinux,因为默认下是没有开启FTP的支持,所以访问时都被阻止了。
//首先查看SELinux设置
# getsebool -a|grep ftp
发现ftpd_disable_trans –> off 或者 ftp_home_dir–>off

解决方法:
//使用setsebool命令开启
# setsebool ftpd_disable_trans 1
或者
# setsebool ftp_home_dir 1
再次查看当前状态是否是on的状态
# getsebool -a|grep ftp
ftpd_disable_trans –> on
或者
ftp_home_dir–>on

//setsebool使用-P参数,无需每次开机都输入这个命令
# setsebool -P ftpd_disable_trans 1
或者
# setsebool -P ftp_home_dir 1
# service vsftpd restart

CentOS/Linux安装配置ftp服务器

1.安装vsftp
# yum -y install vsftpd
2.启动vsftp
# service vsftpd start
3.安装ftp客户端
# yum install –y ftp
4.测试连接ftp
# ftp localhost
5.输入用户名密码

默认用户名、密码均为ftp

6. 添加ftp用户
# useradd -G ftp -d /目录名 -M 用户名
# passwd 用户名
# chown 用户名.ftp /目录名 -R
# chmod 750 /目录名 -R

7.测试用新添加的用户名连接ftp,至此成功。

若在此发生无法列出目录的错误,请参考本博客的另外一篇文章:http://renrenstudy.com/linux/centos-vsftpd-selinux/

笔者在测试上传功能时,老是报出错误:vsftpd 553 Could not create file。后来,发现是由于ftp下的命令与linux终端稍有不同。

put /root/Downloads/team.zip ./

上面这句代码在linux终端下表示将team.zip上传至当前目录,但在ftp命令行状态下是不行的。正确方法应如下:

put /root/Downloads/team.zip team.zip

也就是,必须指定目标文件名,而不是指定目标目录。