有效修改max open files/ulimit -n

使用ulimit -a 可以查看当前系统的所有限制值,使用ulimit -n 可以查看当前的最大打开文件数。

新装的linux默认只有1024,当作负载较大的服务器时,很容易遇到error: too many open files。因此,需要将其改大。

使用 ulimit -n 65535 可即时修改,但重启后就无效了。(注ulimit -SHn 65535 等效 ulimit -n 65535,-S指soft,-H指hard)

有如下三种修改方式:

1.在/etc/rc.local 中增加一行 ulimit -SHn 65535
2.在/etc/profile 中增加一行 ulimit -SHn 65535
3.在/etc/security/limits.conf最后增加如下两行记录
* soft nofile 65535
* hard nofile 65535

具体使用哪种,试试哪种有效吧,我在 CentOS中使用第1种方式无效果,使用第3种方式有效果,而在Debian中使用第2种有效果

sed学习

文章内容可能有部分复制自其它博客或者贴文,作者就无法一一放上去了……抱歉!

1、用sed打印行号
# sed = test | sed 'N;s/n/:/'     (test为文本文件,s/n/:/为替换语句)

linux 技巧:使用 screen 管理你的远程会话

田 强 (tianq@cn.ibm.com), 软件工程师, IBM中国软件开发中心

简介: 你是不是经常需要远程登录到Linux服务器?你是不是经常为一些长时间运行的任务头疼?还在用 nohup 吗?那么来看看 screen 吧,它会给你一个惊喜!

你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是不是经常为一些长时间运行的任务而头疼,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为他们执行的时间太长了。必须等待它执行完毕,在此期间可不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

元凶:SIGHUP 信号

让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。

在Linux/Unix中,有这样几个概念:

  • 进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
  • 会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
  • 会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。

根据POSIX.1定义:

  • 挂断信号(SIGHUP)默认的动作是终止程序。
  • 当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
  • 如果会话期首进程终止,则该信号发送到该会话期前台进程组。
  • 一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。

因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。

我们来看一个例子。打开两个SSH终端窗口,在其中一个运行top命令。

[root@tivf09 root]# top

在另一个终端窗口,找到top的进程ID为5180,其父进程ID为5128,即登录shell。

[root@tivf09 root]# ps -ef|grep top
root      5180  5128  0 01:03 pts/0    00:00:02 top
root      5857  3672  0 01:12 pts/2    00:00:00 grep top

使用pstree命令可以更清楚地看到这个关系:

[root@tivf09 root]# pstree -H 5180|grep top
|-sshd-+-sshd---bash---top

使用ps-xj命令可以看到,登录shell(PID 5128)和top在同一个会话期,shell为会话期首进程,所在进程组PGID为5128,top所在进程组PGID为5180,为前台进程组。

[root@tivf09 root]# ps -xj|grep 5128
 5126  5128  5128  5128 pts/0     5180 S        0   0:00 -bash
 5128  5180  5180  5128 pts/0     5180 S        0   0:50 top
 3672 18095 18094  3672 pts/2    18094 S        0   0:00 grep 5128

关闭第一个SSH窗口,在另一个窗口中可以看到top也被杀掉了。

[root@tivf09 root]# ps -ef|grep 5128
root     18699  3672  0 04:35 pts/2    00:00:00 grep 5128

如果我们可以忽略SIGHUP信号,关掉窗口应该就不会影响程序的运行了。nohup命令可以达到这个目的,如果程序的标准输出/标准错误是终端,nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令只是使得程序忽略SIGHUP信号,还需要使用标记&把它放在后台运行。

nohup <command> [argument…] &

虽然nohup很容易使用,但还是比较“简陋”的,对于简单的命令能够应付过来,对于复杂的需要人机交互的任务就麻烦了。

其实我们可以使用一个更为强大的实用程序screen。流行的Linux发行版(例如Red Hat Enterprise Linux 4)通常会自带screen实用程序,如果没有的话,可以从GNU screen的官方网站下载。

[root@tivf06 ~]# rpm -qa|grep screen
xscreensaver-4.18-5.rhel4.11
screen-4.0.2-5

开始使用Screen

简单来说,Screen是一个可以在多个进程之间多路复用一个物理终端的窗口管理器。Screen中有会话的概念,用户可以在一个screen会话中创建多个screen窗口,在每一个screen窗口中就像操作一个真实的telnet/SSH连接窗口那样。在screen中创建一个新的窗口有这样几种方式:

1.直接在命令行键入screen命令

[root@tivf06 ~]# screen

Screen将创建一个执行shell的全屏窗口。你可以执行任意shell程序,就像在ssh窗口中那样。在该窗口中键入exit退出该窗口,如果这是该screen会话的唯一窗口,该screen会话退出,否则screen自动切换到前一个窗口。

2.Screen命令后跟你要执行的程序。

[root@tivf06 ~]# screen vi test.c

Screen创建一个执行vi test.c的单窗口会话,退出vi将退出该窗口/会话。

3.以上两种方式都创建新的screen会话。我们还可以在一个已有screen会话中创建新的窗口。在当前screen窗口中键入C-a c,即Ctrl键+a键,之后再按下c键,screen 在该会话内生成一个新的窗口并切换到该窗口。

screen还有更高级的功能。你可以不中断screen窗口中程序的运行而暂时断开(detach)screen会话,并在随后时间重新连接(attach)该会话,重新控制各窗口中运行的程序。例如,我们打开一个screen窗口编辑/tmp/abc文件:

[root@tivf06 ~]# screen vi /tmp/abc

之后我们想暂时退出做点别的事情,比如出去散散步,那么在screen窗口键入C-a d,Screen会给出detached提示:
暂时中断会话
暂时中断会话

半个小时之后回来了,找到该screen会话:

[root@tivf06 ~]# screen -ls
There is a screen on:
        16582.pts-1.tivf06      (Detached)
1 Socket in /tmp/screens/S-root.

重新连接会话:

[root@tivf06 ~]# screen -r 16582

看看出现什么了,太棒了,一切都在。继续干吧。

你可能注意到给screen发送命令使用了特殊的键组合C-a。这是因为我们在键盘上键入的信息是直接发送给当前screen窗口,必须用其他方式向screen窗口管理器发出命令,默认情况下,screen接收以C-a开始的命令。这种命令形式在screen中叫做键绑定(key binding),C-a叫做命令字符(command character)。

可以通过C-a ?来查看所有的键绑定,常用的键绑定有:

C-a ? 显示所有键绑定信息
C-a w 显示所有窗口列表
C-a C-a 切换到之前显示的窗口
C-a c 创建一个新的运行shell的窗口并切换到该窗口
C-a n 切换到下一个窗口
C-a p 切换到前一个窗口(与C-a n相对)
C-a 0..9 切换到窗口0..9
C-a a 发送 C-a到当前窗口
C-a d 暂时断开screen会话
C-a k 杀掉当前窗口
C-a [ 进入拷贝/回滚模式

Screen常用选项

使用键绑定C-a ?命令可以看到, 默认的命令字符(Command key)为C-a,转义C-a(literal ^a)的字符为a:
Screen 常用选项
Screen 常用选项

因为screen把C-a看作是screen命令的开始,所以如果你想要screen窗口接收到C-a字符,就要输入C-a a。Screen也允许你使用-e选项设置自己的命令字符和转义字符,其格式为:

-exy x为命令字符,y为转义命令字符的字符

下面命令启动的screen会话指定了命令字符为C-t,转义C-t的字符为t,通过C-t ?命令可以看到该变化。

[root@tivf18 root]# screen -e^tt

自定义命令字符和转义字符
自定义命令字符和转义字符

其他常用的命令选项有:

-c file 使用配置文件file,而不使用默认的$HOME/.screenrc
-d|-D [pid.tty.host] 不开启新的screen会话,而是断开其他正在运行的screen会话
-h num 指定历史回滚缓冲区大小为num行
-list|-ls 列出现有screen会话,格式为pid.tty.host
-d -m 启动一个开始就处于断开模式的会话
-r sessionowner/ [pid.tty.host] 重新连接一个断开的会话。多用户模式下连接到其他用户screen会话需要指定sessionowner,需要setuid-root权限
-S sessionname 创建screen会话时为会话指定一个名字
-v 显示screen版本信息
-wipe [match] 同-list,但删掉那些无法连接的会话

下例显示当前有两个处于detached状态的screen会话,你可以使用screen -r <screen_pid>重新连接上:

[root@tivf18 root]# screen –ls
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Detached)
2 Sockets in /root/.screen.

[root@tivf18 root]# screen –r 8736

如果由于某种原因其中一个会话死掉了(例如人为杀掉该会话),这时screen -list会显示该会话为dead状态。使用screen -wipe命令清除该会话:

[root@tivf18 root]# kill -9 8462
[root@tivf18 root]# screen -ls
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Dead ???)
Remove dead screens with 'screen -wipe'.
2 Sockets in /root/.screen.

[root@tivf18 root]# screen -wipe
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Removed)
1 socket wiped out.
1 Socket in /root/.screen.

[root@tivf18 root]# screen -ls
There is a screen on:
        8736.pts-1.tivf18       (Detached)
1 Socket in /root/.screen.

[root@tivf18 root]#

-d –m 选项是一对很有意思的搭档。他们启动一个开始就处于断开模式的会话。你可以在随后需要的时候连接上该会话。有时候这是一个很有用的功能,比如我们可以使用它调试后台程序。该选项一个更常用的搭配是:-dmS sessionname

启动一个初始状态断开的screen会话:

[root@tivf06 tianq]# screen -dmS mygdb gdb execlp_test

连接该会话:

[root@tivf06 tianq]# screen -r mygdb

管理你的远程会话

先来看看如何使用screen解决SIGHUP问题,比如现在我们要ftp传输一个大文件。如果按老的办法,SSH登录到系统,直接ftp命令开始传输,之后。。如果网络速度还可以,恭喜你,不用等太长时间了;如果网络不好,老老实实等着吧,只能传输完毕再断开SSH连接了。让我们使用screen来试试。

SSH登录到系统,在命令行键入screen。

[root@tivf18 root]# screen

在screen shell窗口中输入ftp命令,登录,开始传输。不愿意等了?OK,在窗口中键入C-a d:
管理你的远程会话
管理你的远程会话

然后。。退出SSH登录?随你怎样,只要别杀掉screen会话。

是不是很方便?更进一步,其实我们可以利用screen这种功能来管理你的远程会话,保存你所有的工作内容。你是不是每次登录到系统都要开很多窗口,然后每天都要重复打开关闭这些窗口?让screen来帮你“保存”吧,你只需要打开一个ssh窗口,创建需要的screen窗口,退出的时候C-a d“保存”你的工作,下次登录后直接screen -r <screen_pid>就可以了。

最好能给每个窗口起一个名字,这样好记些。使用C-a A给窗口起名字。使用C-a w可以看到这些窗口名字,可能名字出现的位置不同。使用putty:
putty
putty

使用telnet:
telnet
telnet

更多Screen功能

Screen提供了丰富强大的定制功能。你可以在Screen的默认两级配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如设定screen选项,定制绑定键,设定screen会话自启动窗口,启用多用户模式,定制用户访问权限控制等等。如果你愿意的话,也可以自己指定screen配置文件。

以多用户功能为例,screen默认是以单用户模式运行的,你需要在配置文件中指定multiuser on 来打开多用户模式,通过acl*(acladd,acldel,aclchg...)命令,你可以灵活配置其他用户访问你的screen会话。更多配置文件内容请参考screen的man页。

参考资料

关于作者

田强,中国软件开发中心 Tivoli 部门软件工程师,负责 IBM 产品TMF(Tivoli Management Framework)的维护和客户支持工作,热爱 Linux。

require(),include(),require_once()和include_once()的异同


require()和include()有许多相似之处,也有些不同。理解它们的不同点非常重要,否则很容易犯错误。我把这两个语句放在一起介绍,读者可以比较学习。
1.require()语句
require()语句用于指定的文件代替语句本身,就象C语言中的include()语句一样。如果php配置文件php.ini中的URL fopen wrappers 是打开的(默认情况下是打开的),就可以使用URL来指定文件的位置从而实现远程文件的调用。
有一点就是使用require()和include()语句时要特别的注意。那就是在被包含的文件中,处理器是按照html模式来解释其中的内容的,处理完被包含的内容后又恢复到php模式。所以如果需要在被包含文件中使用php语法,就要使用正确的php开始和结束标记来把这些语句包含进去。
require()和include()知识php中的一种语言特性,而不是函数。它们和函数有许多不同的地方。
比如:require()所包含的文件中不能包含控制结构,而且不能使用return这样的语句。在require()所包含的文件中使用return语句会产生处理错误。
不象include()语句,require()语句会无条件地读取它所包含的文件的内容,而不管这些语句是否执行。所以如果你想按照不同的条件包含不同的文件,就必须使用include()语句。当然,如果require()所在位置的语句不被执行,require()所包含的文件中的语句也不会被执行。
require()不能在循环体中根据条件的不同而包含不同的文件。require()语句只会在第一次执行时调用它所包含的文件中的内容替换本身这条语句,当再次被执行时只能执行第一次所包含的语句。但是include()语句可以在循环体中来包含不同的文件。
require()语句中的变量继承require()语句所在位置的变量作用域。所有在require()语句的位置可以访问的变量,在require()语句所包含的文件中都可以访问。如果require()语句位于一个函数内部,那么被包含文件内的语句都相当于定义在函数内部。
require()语句在PHP程序执行前就会将使用require引用的文件读入,因此require通常放到程序的开始处。因此要特别注意一点,require语句有一点强,不管程序是否真的需要引用的文件,只要你使用require语句,它都会把他们包含进来!即使你是在条件控制语句中使用这个函数进行包含,那怕是那个条件不为真,引用文件也会被包含进来!形成了僵尸,在运行过程中这些僵尸是不起任何可见作用的,但是很明显它会加重负担,所以这一点要特别注意!如果使用require语句发生了包含错误,那么程序将输出出错信息并停止运行!!如果require()语句通过声明文件的URL来包含远程文件,而且远程服务器按照php代码来解释该文件的话,本地php文件中所包含的内容是在远程服务器上处理以后的结果。例如:
/*
这个例子假设some_server服务器可以解释.php文件,而不对.txt文件进行解释。在远程文件中
需要变量$varfirst和$varsecond
*/
/*不能正确执行,远程服务器不处理.txt文件*/
require(“http://some_server/file.txt?varfirst=1&varsecond=2″);

/*不正确,这样只能在本地机上寻找file.php文件*/
require(“file.php?varfirst=1&varsecond=2″);

/*正确的语句*/
require(“http://some_server/file.php?varfirst=1&varsecond=2″);

$varfirst=1;
$varsecond=2;
require(“file.txt”); /*正确的语句*/
require(“file.php”); /*正确的语句*/
本来在php3.0中,require()所包含的文件可以使用return语句,但条件是return语句不能出现在{}内部,而必须出现在被包含文件的全局范围内。在php4.0中已经取消了require()的这个功能,但是仍然可以使用include()来实现。

2.include()语句
include()语句和require()语句有许多相同的地方。凡是在上边require()语句中没有明确说明不能适用于include()的部分外,require()语句的功能完全适用于include()语句。下边介绍require()语句所没有的include()语句的功能和特点。
include语句只有在被执行时才会读入要包含的文件。在错误处理方便,使用include语句,如果发生包含错误,程序将跳过include语句,虽然会显示错误信息但是程序还是会继续执行!
php处理器会在每次遇到include()语句时,对它进行重新处理,所以可以根据不同情况的,在条件控制语句和循环语句中使用include()来包含不同的文件。
例如:
<?php
$files=array(‘first.php’,'second.php’,'third.php’);
for($i=0;$i<count($files);$i++)
{
include $files[$i];
}
?>
在php3.0和php4.0中include()语句所包含的文件中都可以使用return语句来返回一个值,并停止执行被包含文件下面的内容。但php3.0和php4.0在处理这样的情况时有所不同。在php3.0中return语句不能包含在{}内,除非它在一个函数中,因为这时它表示函数的返回值而不是文件的返回值。而在php4.0中就没有了这样的限制,用户甚至可以在文件中返回一个数字,就象函数的返回值一样。这样的语句在

php3.0中通常会报告错误。以下举例说明:
假设被包含的文件为test.inc和主文件main.php位于一个目录中。test.inc的内容如下:
test.inc
<?php
echo “Before the return<br>\n”;
if(1)
{
return 27;
}
echo “After the return<br>\n”;
?>

假设在main.php文件中包含下面的语句:
<?php
$retval=include(‘test.inc’);
echo “File returned:’$retval’<br>\n”;
?>
php3.0解释器会在第二行报告错误,而不能得到include()语句的返回值。但在php4.0中会得到下面的结果:
Before the return
File returned: ’27′
下边假设main.php改为:
<?php
include(‘test.inc’);
echo “Back in main.html<br>\n”;
?>
在php4.0中的输出结果是:
Before the return
Back in main.html

在php5.0中的输出结果也是:
Before the return
Back in main.html

在php3.0中的输出结果是:
Before the return
27Back in main.html

Parse error:parse error in /apache/htdocs/phptest/main.html on line 5

出现上面的错误是因为return语句位于{}内部而且不是一个函数内部。如果把{}去掉,使它位于test.inc的最外层,输出结果是:
Before the return
27Back in main.html
之所以出现27,是因为在php3.0中不支持include()返回。

3.require_once()和include_once()语句
require_once()和include_once()语句分别对应于require()和include()语句。require_once()和include_once()语句主要用于需要包含多个文件时,可以有效地避免把同一段代码包含进去而出现函数或变量重复定义的错误。例如:如果创建两个文件util.inc和fool.inc,程序代码分别为:
util.inc:
<?php
define(PHPVERSION,floor(phpversion()));
echo “GLOBALS ARE NICE<br>\n”;
function goodTea()
{
return “Olong tea tasts good!”;
}
?>
和fool.inc:
<?php
require (“util.inc”);
function showVar($var)
{
if(PHPVERSION==4)
{
print_r($var);
}
else
{
var_dump($var);
}
}
?>
然后在error_require.php中包含这两个文件:
<?php
require(“fool.inc”);
require(“util.inc”);//此句会产生一个错误
$foo=array(“1″,array(“complex”,”quaternion”));
echo “this is requiring util.inc again which is also<br>\n”;
echo “required in fool.inc\n”;
echo “Running goodTea:”.goodTea().”<br>\n”;
echo “Printing foo:<br>\n”;
showVar($foo);
?>
当运行error_require.php时,输出结果如下:
GLOBALS ARE NICE
GLOBALS ARE NICE

Fatal error:Cannot redeclare goodTea() in util.inc on line 4

如果使用require_once()语句来代替 require()语句,就不会出现上面的错误。我们把error_require.php和fool.inc中的require()语句改为require_once()语句并重命名为error_require_once.php,这是显示结果如下:
GLOBALS ARE NICE
this is requiring util.inc again which is also
required in fool.inc Running goodTea:Olong tea tastes good!
Printing foo:
Array([0] => 1 [1] => Array ([0] => complex [1] = quaternion))

include_once()语句的语法和include()语句类似,主要区别也是避免多次包含一个文件而引起函数或变量的重复定义。

require_once语句有一个引用链,它可以保证文件加入你的程序仅仅只有一次,而且会避开变量值和函数名之间的冲突。

和require_once语句一样,include_once语句把include的功能扩展了。在程序执行期间,将指定的文件包含进来,如果从文件引用进来的程序先前已经包含过的时候,include_once()就不会把它再包含进来。也就是仅仅可以引用同一个文件一次!

include_once() 语句在脚本执行期间包含并运行指定文件。此行为和 include() 语句类似,唯一区别是如果该文件中的代码已经被包含了,则不会再次包含。如同此语句名字暗示的那样,只会包含一次。

include_once() 应该用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题。

使用 require_once() 和 include_once() 的更多例子见最新的 PHP 源程序发行包中的 PEAR 代码。

返回值和 include() 相同。如果文件已被包含,本函数返回 TRUE。

注: include_once() 是 PHP 4.0.1pl2 中新加入的。

注: 要注意 include_once() 和 require_once() 在大小写不敏感的操作系统中(例如 Windows)的行为

可能不是所期望的。
例子:  include_once() 在 Windows 下不区分大小写

<?php
include_once(“a.php”); // this will include a.php
include_once(“A.php”); // this will include a.php again on Windows! (PHP 4 only)
?>

此行为在 PHP 5 中改了,路径先被规格化,因此 C:\PROGRA~1\A.php 和 C:\Program Files\a.php 的实现一样,文件只会被包含一次。

如果要包含的文件不存在,include提示notice,然后继续执行下面的语句,require提示致命错误并且退出。

win32平台下它们都是先包含后执行,所以被包含文件里最好不要再有include或require语句,这样会造成目录混乱。或许Linux下情况不同,暂时还没测试。

如果一个文件不想被包含多次可以使用include_once或require_once## 读取,可以写入文档数据。
<?php
function r($file_name) {
$filenum=@fopen($file_name,”r”);
@flock($filenum,LOCK_SH);
$file_data=@fread($filenum,filesize($file_name));
@fclose($filenum);
return $file_data;
}
function w($file_name,$data,$method=”w”){
$filenum=@fopen($file_name,$method);
flock($filenum,LOCK_EX);
$file_data=fwrite($filenum,$data);
fclose($filenum);
return $file_data;
}
?>

更改Zend Studio/Eclipse代码风格主题

最近决定把几个IDE的代码样式统一一下,Visual Studio的还算好改,PHP目前用得不多,不过也打算给Zend Studio换身新装。

网上搜索的一些更改Zend Studio主题的多是修改或者导入主题配置文件,可选主题不多而且略显麻烦,今天在Zend官方网站上找到一个比较好的解决办法。详细参见Zend文档《Working with Eclipse Color Theme》。原文是英文,比较麻烦,而且大家肯定去找菜单Window | Preferences | General | Appearance | Color Theme选项,很抱歉,你有可能不能发现这个选项。因为原文有个Prerequisites,要求先安装Eclipse Color Theme插件。只有先装了这个插件才能找到Color Theme这个选项,而且这个插件提供网站上还有好多不错的主题文件可以安装,下面简单介绍一下安装方法,哦,对了,Zend Studio是基于Eclipse的,所以同样的方法适用于Eclipse。

我这里仅介绍通过更新站点安装方式。首先点击Help | Install New Software…,然后根据下图所示填写Work with为http://eclipse-color-theme.github.com/update/ ,点击Add…,选中Eclipse Color Theme及其子项,其他默认,然后点击Next:

Install Details这一步直接点击Next:

许可协议,阅读后选择I accept….然后点击Next:

接下来是安装进度:

如果出现下面的Security Warning安全警告,直接选择OK:

然后安装完毕提示重启IDE,保持未完成的工作后点击Yes:

然后去找菜单Window | Preferences | General | Appearance | Color Theme选项,如下图:

选择喜欢的主题点击OK,当然你也可以去其官方网站上下载自己喜欢的主题然后选择Import a theme。

PHP5.3后(set_magic_quotes_runtime(),ereg() )已经关闭。

运行php程序出现以下错误
Deprecated: Function set_magic_quotes_runtime() is deprecated

导致这个提示的原因是在PHP5.3后此特性(set_magic_quotes_runtime())已经关闭。
而且在PHP6中已经完全移除此特性。
你可以注释或者删除掉出错的行,或者是在set_magic_quotes_runtime()前面加@符号。

也可以用替换方法:

find:
set_magic_quotes_runtime(0);

replace with:
ini_set("magic_quotes_runtime", 0);

PHP 5.3 ereg() 无法正常使用,提示“Function ereg() is deprecated Error”。问题根源是php中有两种正则表示方法,一个是posix,一个是perl,php6打算废除posix的正则表示方法所以后来就加了个 preg_match。此问题解决办法很简单,在ereg前加个过滤提示信息符号即可:把ereg()变成@ereg()。这样屏蔽了提示信息,但根本问 题还是没有解决,php在5.2版本以前ereg都使用正常,在5.3以后,就要用preg_match来代替ereg。所以就需要变成这样,原来:

ereg(“^[0-9]*$”,$page)

变成:

preg_match(“/^[0-9]*$/”,$page)

特别提醒:posix与perl的很明显的表达区别就是是否加斜杠,所以与ereg相比,后者在正则的前后分别增加了两个”/”符号,不能缺少。
Tips:此问题在php5.2之前版本不会出现。

Function ereg() is deprecated in drupal-6.15\includes\file.inc on line 904
open the file.inc in a good text editor other than notepad, go to the line number 904 to see the following line. Then comment the line and in the next line type the replaced code. this will solve the instalation issues and also most of other issues related to the same issue.

Change

elseif ($depth >= $min_depth && ereg($mask, $file)) {
to
elseif ($depth >= $min_depth && mb_ereg($mask, $file)) {
mb_ereg fortunatly is not deprecated

MySql中distinct的用法(转)

在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的。所以我花了很多时间来研究这个问题,网上也查不到解决方案,期间把容容拉来帮忙,结果是我们两人都郁闷了。。。。。。。。。

下面先来看看例子:

table
id name
1 a
2 b
3 c
4 c
5 b

库结构大概这样,这只是一个简单的例子,实际情况会复杂得多。

比如我想用一条语句查询得到name不重复的所有数据,那就必须使用distinct去掉多余的重复记录。

select distinct name from table
得到的结果是:

name
a
b
c

好像达到效果了,可是,我想要得到的是id值呢?改一下查询语句吧:

select distinct name, id from table

结果会是:

id name
1 a
2 b
3 c
4 c
5 b

distinct怎么没起作用?作用是起了的,不过他同时作用了两个字段,也就是必须得id与name都相同的才会被排除。。。。。。。

我们再改改查询语句:

select id, distinct name from table

很遗憾,除了错误信息你什么也得不到,distinct必须放在开头。难到不能把distinct放到where条件里?能,照样报错。。。。。。。

很麻烦吧?确实,费尽心思都没能解决这个问题。没办法,继续找人问。

拉住公司里一JAVA程序员,他给我演示了oracle里使用distinct之后,也没找到mysql里的解决方案,最后下班之前他建议我试试group by。

试了半天,也不行,最后在mysql手册里找到一个用法,用group_concat(distinct name)配合group by name实现了我所需要的功能,兴奋,天佑我也,赶快试试。

报错。。。。。。。。。。。。郁闷。。。。。。。连mysql手册也跟我过不去,先给了我希望,然后又把我推向失望,好狠哪。。。。

再仔细一查,group_concat函数是4.1支持,晕,我4.0的。没办法,升级,升完级一试,成功。。。。。。

终于搞定了,不过这样一来,又必须要求客户也升级了。

突然灵机一闪,既然可以使用group_concat函数,那其它函数能行吗?

赶紧用count函数一试,成功,我。。。。。。。想哭啊,费了这么多工夫。。。。。。。。原来就这么简单。。。。。。

现在将完整语句放出:

select *, count(distinct name) from table group by name

结果:

id name count(distinct name)
1 a 1
2 b 1
3 c 1

最后一项是多余的,不用管就行了,目的达到。。。。。

唉,原来mysql这么笨,轻轻一下就把他骗过去了,郁闷也就我吧,现在拿出来希望大家不要被这问题折腾。

哦,对,再顺便说一句,group by 必须放在 order by 和 limit之前,不然会报错,差不多了,我继续忙碌。。。。。