虽说都是 *nix 系统,但一个简单的
函数居然用法都不一样。
例如,今天是 2008-6-18
FreeBSD:
输入:date -v -1d +%Y%m%d
输出:20080617
Linux:
输入:date --date='yesterday' +%Y%m%d
输出:20080617
看到这里,会发现,Linux 的局限性,他只能输出昨天的,但前天和大前天的之类的日期就没办法了。
因此,我喜欢FreeBSD就很自然了,呵呵。
函数居然用法都不一样。
例如,今天是 2008-6-18
FreeBSD:
输入:date -v -1d +%Y%m%d
输出:20080617
Linux:
输入:date --date='yesterday' +%Y%m%d
输出:20080617
看到这里,会发现,Linux 的局限性,他只能输出昨天的,但前天和大前天的之类的日期就没办法了。
因此,我喜欢FreeBSD就很自然了,呵呵。
shell 时用$?查看是否执行成功,成功是0,而在函数里是只要有没有成功,那么整个函数的$?就会是1,于是用它和||结合起来可以实现Shell函数是否成功执行的一个判断并提示。
cat fun.sh
sh fun.sh
hello world...\n
ls: cannot access /tmp2: No such file or directory
ls /tmp2 failed
今天重新再翻看了一下shell程序相关的资料。准备重新将shell再提高一下。
将http://seo-dic.com.cn/archives/2496 提到的《Advanced Bash-Scripting Guide》《高级bash脚本编程指南》上附带的源码重新再看一次。
为了方便查看。我将所有的源代码全部导到一个文件中,再一一查看。省去了每次只打开一个脚本的麻烦。同时,将几个经常用的shell脚本函数稍做了下列举。希望后面可以用得到。
find -type f -name "*.sh" -exec cat {} >>sh.all \;
检查目录是否存在,若不存在,则创建相应目录。
# Check for and create datadir if necessary:
if test ! -d $datadir
then
mkdir $datadir
fi
shell参数判断,若不符合则显示使用方式及退出。
E_BADARGS=65
case $# in
0|1) # The vertical bar means "or" in this context.
echo "Usage: `basename $0` old_file_suffix new_file_suffix"
exit $E_BADARGS # If 0 or 1 arg, then bail out.
;;
esac
另例:
E_OPTERR=65
if [ "$#" -eq 0 ]
then # Script needs at least one command-line argument.
echo "Usage $0 -[options a,b,c]"
exit $E_OPTERR
fi
检查是用户是否是root权限的方式:
ROOT_UID=0 # Root has $UID 0.
E_WRONG_USER=65 # Not root?
E_NOSUCHUSER=70
SUCCESS=0
if [ "$UID" -ne "$ROOT_UID" ]
then
echo; echo "Only root can run this script."; echo
exit $E_WRONG_USER
else
echo
echo "You should know better than to run this script, root."
echo "Even root users get the blues... "
echo
fi
进行用户目录判断:
LOG_DIR=/var/log
ROOT_UID=0 # Only users with $UID 0 have root privileges.
LINES=50 # Default number of lines saved.
E_XCD=66 # Can't change directory?
E_NOTROOT=67 # Non-root exit error.
cd $LOG_DIR
if [ `pwd` != "$LOG_DIR" ] # or if [ "$PWD" != "$LOG_DIR" ]
# Not in /var/log?
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi # Doublecheck if in right directory, before messing with log file.
cat fun.sh
sh fun.sh
hello world...\n
ls: cannot access /tmp2: No such file or directory
ls /tmp2 failed
今天重新再翻看了一下shell程序相关的资料。准备重新将shell再提高一下。
将http://seo-dic.com.cn/archives/2496 提到的《Advanced Bash-Scripting Guide》《高级bash脚本编程指南》上附带的源码重新再看一次。
为了方便查看。我将所有的源代码全部导到一个文件中,再一一查看。省去了每次只打开一个脚本的麻烦。同时,将几个经常用的shell脚本函数稍做了下列举。希望后面可以用得到。
find -type f -name "*.sh" -exec cat {} >>sh.all \;
检查目录是否存在,若不存在,则创建相应目录。
# Check for and create datadir if necessary:
if test ! -d $datadir
then
mkdir $datadir
fi
shell参数判断,若不符合则显示使用方式及退出。
E_BADARGS=65
case $# in
0|1) # The vertical bar means "or" in this context.
echo "Usage: `basename $0` old_file_suffix new_file_suffix"
exit $E_BADARGS # If 0 or 1 arg, then bail out.
;;
esac
另例:
E_OPTERR=65
if [ "$#" -eq 0 ]
then # Script needs at least one command-line argument.
echo "Usage $0 -[options a,b,c]"
exit $E_OPTERR
fi
检查是用户是否是root权限的方式:
ROOT_UID=0 # Root has $UID 0.
E_WRONG_USER=65 # Not root?
E_NOSUCHUSER=70
SUCCESS=0
if [ "$UID" -ne "$ROOT_UID" ]
then
echo; echo "Only root can run this script."; echo
exit $E_WRONG_USER
else
echo
echo "You should know better than to run this script, root."
echo "Even root users get the blues... "
echo
fi
进行用户目录判断:
LOG_DIR=/var/log
ROOT_UID=0 # Only users with $UID 0 have root privileges.
LINES=50 # Default number of lines saved.
E_XCD=66 # Can't change directory?
E_NOTROOT=67 # Non-root exit error.
cd $LOG_DIR
if [ `pwd` != "$LOG_DIR" ] # or if [ "$PWD" != "$LOG_DIR" ]
# Not in /var/log?
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi # Doublecheck if in right directory, before messing with log file.
前几天接手一台parking服务器,发现其流量经常达到上百M,为了进行流量分流。同时启用另两台机器做分流机。
因数据经整改后。可生成静态页面。所以对分流的服务器的系统就没什么要求了。只要可以显示静态网页的服务器即可。
选了两台电信机房及一台浙江机房的服务器。共三台,其中一台,可跑asp程序,用以生成静态页,其他两台一台是windows系统,另一台是linux系统。分别使用iis及apache实现web服务。
主服务器A 从服务器为B、C
架构为
A->B
A->C
数据通过contab及at指令,定时从A服务器自动用rsync实现数据同步。
因流量过大,经观察需要做的细化步骤有:
1.对IIS服务器要将所有的可能加载的dll工具等如7i24/iistracer等全部卸载。同时因是使用做parking服务器,将其所有的404页面做跳转到首页。
2.取消所有的动态执行权限。
3.对iis要注意观察是否会造成类似的CC全链接攻击。
4.对apache需进行重编译。许可超过256个链接数。
5.加入监控。实现跟踪自动化。
经过这几天的跟踪发现几点结论:
1.虽然我使用的目标服务器提供的web服务是基础是基于dns轮循查询方法上的。但从服务器的流量观察来看。每天都有一台机器要承受较大的流量的。即dns轮循实现的负载均衡不见得是实际的流量及响应均衡。
这点的证据是:浙江电信B与厦门电信C的流量明显不对等。
2.因A服务器同时提供udp53端口的查询功能。将所有域名的的dns解析记录直接都轮流指到A/B/C同时A服务器还提供asp服务cpu的负载稍高。
3.经过几天的观察,发现每天能响应的域名查询量差异较大。高时的流量ip>5万低时,只有2万多。
以此备注。rsync在对静态数据的同步化方面,用途明显。适合轻量级的数据同步。
因数据经整改后。可生成静态页面。所以对分流的服务器的系统就没什么要求了。只要可以显示静态网页的服务器即可。
选了两台电信机房及一台浙江机房的服务器。共三台,其中一台,可跑asp程序,用以生成静态页,其他两台一台是windows系统,另一台是linux系统。分别使用iis及apache实现web服务。
主服务器A 从服务器为B、C
架构为
A->B
A->C
数据通过contab及at指令,定时从A服务器自动用rsync实现数据同步。
因流量过大,经观察需要做的细化步骤有:
1.对IIS服务器要将所有的可能加载的dll工具等如7i24/iistracer等全部卸载。同时因是使用做parking服务器,将其所有的404页面做跳转到首页。
2.取消所有的动态执行权限。
3.对iis要注意观察是否会造成类似的CC全链接攻击。
4.对apache需进行重编译。许可超过256个链接数。
5.加入监控。实现跟踪自动化。
经过这几天的跟踪发现几点结论:
1.虽然我使用的目标服务器提供的web服务是基础是基于dns轮循查询方法上的。但从服务器的流量观察来看。每天都有一台机器要承受较大的流量的。即dns轮循实现的负载均衡不见得是实际的流量及响应均衡。
这点的证据是:浙江电信B与厦门电信C的流量明显不对等。
2.因A服务器同时提供udp53端口的查询功能。将所有域名的的dns解析记录直接都轮流指到A/B/C同时A服务器还提供asp服务cpu的负载稍高。
3.经过几天的观察,发现每天能响应的域名查询量差异较大。高时的流量ip>5万低时,只有2万多。
以此备注。rsync在对静态数据的同步化方面,用途明显。适合轻量级的数据同步。
一、构造字符串
直接构造
STR_ZERO=hello
STR_FIRST="i am a string"
STR_SECOND='success'
重复多次
#repeat the first parm($1) by $2 times
strRepeat()
{
local x=$2
if [ "$x" == "" ]; then
x=0
fi
local STR_TEMP=""
while [ $x -ge 1 ];
do
STR_TEMP=`printf "%s%s" "$STR_TEMP" "$1"`
x=`expr $x - 1`
done
echo $STR_TEMP
}
举例:
STR_REPEAT=`strRepeat "$USER_NAME" 3`
echo "repeat = $STR_REPEAT"
二、赋值与拷贝
直接赋值
与构造字符串一样
USER_NAME=terry
从变量赋值
ALIASE_NAME=$USER_NAME
三、联接
直接联接两个字符串
STR_TEMP=`printf "%s%s" "$STR_ZERO" "$USER_NAME"`
使用printf可以进行更复杂的联接
四、求长
求字符数(char)
COUNT_CHAR=`echo "$STR_FIRST" | wc -m`
echo $COUNT_CHAR
求字节数(byte)
COUNT_BYTE=`echo "$STR_FIRST" | wc -c`
echo $COUNT_BYTE
求字数(word)
COUNT_WORD=`echo "$STR_FIRST" | wc -w`
echo $COUNT_WORD
五、比较
相等比较
str1 = str2
不等比较
str1 != str2
举例:
if [ "$USER_NAME" = "terry" ]; then
echo "I am terry"
fi
小于比较
#return 0 if the two string is equal, return 1 if $1 < $2, else 2strCompare() { local x=0 if [ "$1" != "$2" ]; then x=2 localTEMP=`printf "%s\n%s" "$1" "$2"` local TEMP2=`(echo "$1"; echo "$2") |sort` if [ "$TEMP" = "$TEMP2" ]; then x=1 fi fi echo $x }
六、测试
判空
-z str
判非空
-n str
是否为数字
# return 0 if the string is num, otherwise 1
strIsNum()
{
local RET=1
if [ -n "$1" ]; then
local STR_TEMP=`echo "$1" | sed 's/[0-9]//g'`
if [ -z "$STR_TEMP" ]; then
RET=0
fi
fi
echo $RET
}
举例:
if [ -n "$USER_NAME" ]; then
echo "my name is NOT empty"
fi
echo `strIsNum "9980"`
七、分割
以符号+为准,将字符分割为左右两部分
使用sed
举例:
命令 date --rfc-3339 seconds 的输出为
2007-04-14 15:09:47+08:00
取其+左边的部分
date --rfc-3339 seconds | sed 's/+[0-9][0-9]:[0-9][0-9]//g'
输出为
2007-04-14 15:09:47
取+右边的部分
date --rfc-3339 seconds | sed 's/.*+//g'
输出为
08:00
以空格为分割符的字符串分割
使用awk
举例:
STR_FRUIT="Banana 0.89 100"
取第3字段
echo $STR_FRUIT | awk '{ print $3; }'
八、子字符串
字符串1是否为字符串2的子字符串
# return 0 is $1 is substring of $2, otherwise 1
strIsSubstring()
{
local x=1
case "$2" in
*$1*) x=0;;
esac
echo $x
}
Shell字符串截取
一、Linux shell 截取字符变量的前8位,有方法如下:
1.expr substr “$a” 1 8
2.echo $a|awk ‘{print substr(,1,8)}’
3.echo $a|cut -c1-8
4.echo $
5.expr $a : ‘\(.\\).*’
6.echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字符串截取
1、第一种方法:
* ${varible##*string} 从左向右截取最后一个string后的字符串
* ${varible#*string}从左向右截取第一个string后的字符串
* ${varible%%string*}从右向左截取最后一个string后的字符串
* ${varible%string*}从右向左截取第一个string后的字符串
“*”只是一个通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2、第二种方法:${varible:n1:n2}:截取变量varible从n1到n2之间的字符串。
可以根据特定字符偏移和长度,使用另一种形式的变量扩展,来选择特定子字符串。试着在 bash 中输入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
这种形式的字符串截断非常简便,只需用冒号分开来指定起始字符和子字符串长度。
三、按照指定要求分割:
比如获取后缀名
ls -al | cut -d “.” -f2
shell (bash) 比较运算符
运算符 描述 示例
文件比较运算符
-e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
-d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
-x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 [size=-1](请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string 如果 string 长度为零,则为真 [ -z "$myvar" ]
-n string 如果 string 长度非零,则为真 [ -n "$myvar" ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ "$myvar" = "one two three" ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ "$myvar" != "one two three" ]
算术比较运算符
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]
直接构造
STR_ZERO=hello
STR_FIRST="i am a string"
STR_SECOND='success'
重复多次
#repeat the first parm($1) by $2 times
strRepeat()
{
local x=$2
if [ "$x" == "" ]; then
x=0
fi
local STR_TEMP=""
while [ $x -ge 1 ];
do
STR_TEMP=`printf "%s%s" "$STR_TEMP" "$1"`
x=`expr $x - 1`
done
echo $STR_TEMP
}
举例:
STR_REPEAT=`strRepeat "$USER_NAME" 3`
echo "repeat = $STR_REPEAT"
二、赋值与拷贝
直接赋值
与构造字符串一样
USER_NAME=terry
从变量赋值
ALIASE_NAME=$USER_NAME
三、联接
直接联接两个字符串
STR_TEMP=`printf "%s%s" "$STR_ZERO" "$USER_NAME"`
使用printf可以进行更复杂的联接
四、求长
求字符数(char)
COUNT_CHAR=`echo "$STR_FIRST" | wc -m`
echo $COUNT_CHAR
求字节数(byte)
COUNT_BYTE=`echo "$STR_FIRST" | wc -c`
echo $COUNT_BYTE
求字数(word)
COUNT_WORD=`echo "$STR_FIRST" | wc -w`
echo $COUNT_WORD
五、比较
相等比较
str1 = str2
不等比较
str1 != str2
举例:
if [ "$USER_NAME" = "terry" ]; then
echo "I am terry"
fi
小于比较
#return 0 if the two string is equal, return 1 if $1 < $2, else 2strCompare() { local x=0 if [ "$1" != "$2" ]; then x=2 localTEMP=`printf "%s\n%s" "$1" "$2"` local TEMP2=`(echo "$1"; echo "$2") |sort` if [ "$TEMP" = "$TEMP2" ]; then x=1 fi fi echo $x }
六、测试
判空
-z str
判非空
-n str
是否为数字
# return 0 if the string is num, otherwise 1
strIsNum()
{
local RET=1
if [ -n "$1" ]; then
local STR_TEMP=`echo "$1" | sed 's/[0-9]//g'`
if [ -z "$STR_TEMP" ]; then
RET=0
fi
fi
echo $RET
}
举例:
if [ -n "$USER_NAME" ]; then
echo "my name is NOT empty"
fi
echo `strIsNum "9980"`
七、分割
以符号+为准,将字符分割为左右两部分
使用sed
举例:
命令 date --rfc-3339 seconds 的输出为
2007-04-14 15:09:47+08:00
取其+左边的部分
date --rfc-3339 seconds | sed 's/+[0-9][0-9]:[0-9][0-9]//g'
输出为
2007-04-14 15:09:47
取+右边的部分
date --rfc-3339 seconds | sed 's/.*+//g'
输出为
08:00
以空格为分割符的字符串分割
使用awk
举例:
STR_FRUIT="Banana 0.89 100"
取第3字段
echo $STR_FRUIT | awk '{ print $3; }'
八、子字符串
字符串1是否为字符串2的子字符串
# return 0 is $1 is substring of $2, otherwise 1
strIsSubstring()
{
local x=1
case "$2" in
*$1*) x=0;;
esac
echo $x
}
Shell字符串截取
一、Linux shell 截取字符变量的前8位,有方法如下:
1.expr substr “$a” 1 8
2.echo $a|awk ‘{print substr(,1,8)}’
3.echo $a|cut -c1-8
4.echo $
5.expr $a : ‘\(.\\).*’
6.echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字符串截取
1、第一种方法:
* ${varible##*string} 从左向右截取最后一个string后的字符串
* ${varible#*string}从左向右截取第一个string后的字符串
* ${varible%%string*}从右向左截取最后一个string后的字符串
* ${varible%string*}从右向左截取第一个string后的字符串
“*”只是一个通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2、第二种方法:${varible:n1:n2}:截取变量varible从n1到n2之间的字符串。
可以根据特定字符偏移和长度,使用另一种形式的变量扩展,来选择特定子字符串。试着在 bash 中输入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
这种形式的字符串截断非常简便,只需用冒号分开来指定起始字符和子字符串长度。
三、按照指定要求分割:
比如获取后缀名
ls -al | cut -d “.” -f2
shell (bash) 比较运算符
运算符 描述 示例
文件比较运算符
-e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
-d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
-x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 [size=-1](请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string 如果 string 长度为零,则为真 [ -z "$myvar" ]
-n string 如果 string 长度非零,则为真 [ -n "$myvar" ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ "$myvar" = "one two three" ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ "$myvar" != "one two three" ]
算术比较运算符
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]
比较操作符
整数比较
-eq 等于 if [ "$a"-eq "$b"]
-ne 不等于 if [ "$a"-ne "$b"]
-gt 大于 if [ "$a"-gt "$b"]
-ge 大于等于 if [ "$a"-ge "$b"]
-lt 小于 if [ "$a"-lt "$b"]
-le 小于等于 if [ "$a"-le "$b"]
>,<=,>,>= 只能在双括号里使用 if ((”$a”< “$b”))
字符串比较
= 等于 if [ "$a"= "$b"]
== 等于 它和=是同义词
!= 不相等 if [ "$a"!= "$b"]
< 小于,依照ASCII字符排列顺序,if [ "$a"\< "$b"] 注意 ”<”字 符在[ ] 结构里需要转义,或者if [[ "$a"< "$b"]]
> 大于,依照ASCII字符排列顺序,if [ "$a"\> "$b"] 注意 ”>”字 符在[ ] 结构里需要转义,或者if [[ "$a"> "$b"]]
-z 字符串为”null”,即是指字符串长度为零。
-n 字符串不为”null”,即长度不为零.
注意:
1.应该总是用引号把测试字符串引起来,以免引起不必要的错误
2.操作符在[[…]]结构里使用模式匹配.
[[ "$a"== z* ]] # 如果变量$a以字符”z”开始(模式匹配)则为真.
[[ "$a"== "z*"]] # 如果变量$a与z*(字面上的匹配)相等则为真.
整数比较
-eq 等于 if [ "$a"-eq "$b"]
-ne 不等于 if [ "$a"-ne "$b"]
-gt 大于 if [ "$a"-gt "$b"]
-ge 大于等于 if [ "$a"-ge "$b"]
-lt 小于 if [ "$a"-lt "$b"]
-le 小于等于 if [ "$a"-le "$b"]
>,<=,>,>= 只能在双括号里使用 if ((”$a”< “$b”))
字符串比较
= 等于 if [ "$a"= "$b"]
== 等于 它和=是同义词
!= 不相等 if [ "$a"!= "$b"]
< 小于,依照ASCII字符排列顺序,if [ "$a"\< "$b"] 注意 ”<”字 符在[ ] 结构里需要转义,或者if [[ "$a"< "$b"]]
> 大于,依照ASCII字符排列顺序,if [ "$a"\> "$b"] 注意 ”>”字 符在[ ] 结构里需要转义,或者if [[ "$a"> "$b"]]
-z 字符串为”null”,即是指字符串长度为零。
-n 字符串不为”null”,即长度不为零.
注意:
1.应该总是用引号把测试字符串引起来,以免引起不必要的错误
2.操作符在[[…]]结构里使用模式匹配.
[[ "$a"== z* ]] # 如果变量$a以字符”z”开始(模式匹配)则为真.
[[ "$a"== "z*"]] # 如果变量$a与z*(字面上的匹配)相等则为真.
freebsd 命令行下截图的方法
引用:
sudo vidcontrol -p dump.scr
ttyv0是控制台的名字,dump.scr是截屏输出的名字。
如果需要转换成图形格式,需要用一个叫scr2png的工具:
scr2png dump.png
这个工具可以从port安装 (graphics/scr2png) 今天在 delphij 的回帖中看到的,就记录下来分享了。。哈哈
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/18630/showart_1419878.html
引用:
sudo vidcontrol -p dump.scr
ttyv0是控制台的名字,dump.scr是截屏输出的名字。
如果需要转换成图形格式,需要用一个叫scr2png的工具:
scr2png dump.png
这个工具可以从port安装 (graphics/scr2png) 今天在 delphij 的回帖中看到的,就记录下来分享了。。哈哈
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/18630/showart_1419878.html
通过网友介绍,认识了两款在windows下面非常强大但是免费的mysql客户端。
一个是轻量级的选手,HeidiSQL,下载地址是http://www.heidisql.com/download.php,软件只有4M左右,易于使用,如果猜得没错,应该是用delphi或是bcb开发的。
另外一款是重量级选手,是toad for mysql,下载地址为http://www.toadsoft.com/tda/tdaindex.html,这个系列有其它几个数据库系统支持,如oracle,DB2和sql server,安装包比较大,但是安装之后,发现这个工具还是值得深入使用的。可定制性很强,而且还支持换肤,他的官方介绍是home of the world's #1 tool for database developers and DBAs!口气很大,看样子应该表现也不差吧。这两款都是在windows下面的软件,暂时未发现是否有linux下面的版本。对于windows下面的用户,也算有福了。
一个是轻量级的选手,HeidiSQL,下载地址是http://www.heidisql.com/download.php,软件只有4M左右,易于使用,如果猜得没错,应该是用delphi或是bcb开发的。
另外一款是重量级选手,是toad for mysql,下载地址为http://www.toadsoft.com/tda/tdaindex.html,这个系列有其它几个数据库系统支持,如oracle,DB2和sql server,安装包比较大,但是安装之后,发现这个工具还是值得深入使用的。可定制性很强,而且还支持换肤,他的官方介绍是home of the world's #1 tool for database developers and DBAs!口气很大,看样子应该表现也不差吧。这两款都是在windows下面的软件,暂时未发现是否有linux下面的版本。对于windows下面的用户,也算有福了。
DOS命令 (一)MD——建立子目录 1.功能:创建新的子目录 2.类型:内部命令 3.格式:MD[盘符:][路径名]〈子目录名〉 4.使用说明: (1)“盘符”:指定要建立子目录的磁盘驱动器字母 ...
DOS命令
(一)MD——建立子目录
1.功能:创建新的子目录
2.类型:内部命令
3.格式:MD[盘符:][路径名]〈子目录名〉
4.使用说明:
(1)“盘符”:指定要建立子目录的磁盘驱动器字母,若省略,则为当前驱动器;
(2)“路径名”:要建立的子目录的上级目录名,若缺省则建在当前目录下。
例:(1)在C盘的根目录下创建名为FOX的子目录;(2)在FOX子目录下再创建USER子目录。
C:、>MD FOX (在当前驱动器C盘下创建子目录FOX)
C:、>MD FOX 、USER (在FOX 子目录下再创建USER子目录)
(二)CD——改变当前目录
1.功能:显示当前目录
2.类型:内部命令
3.格式:CD[盘符:][路径名][子目录名]
4.使用说明:
(1)如果省略路径和子目录名则显示当前目录;
(2)如采用“CD、”格式,则退回到根目录;
(3)如采用“CD.。”格式则退回到上一级目录。
例:(1)进入到USER子目录;(2)从USER子目录退回到子目录;(3)返回到根目录。
C:、>CD FOX 、USER(进入FOX子目录下的USER子目录)
C:、FOX、USER>CD.。 (退回上一级根目录)
C:、FOX>CD、 (返回到根目录)
C:、>
(三)RD——删除子目录命令
1.功能:从指定的磁盘删除了目录。
2.类型:内部命令
3.格式:RD[盘符:][路径名][子目录名]
4.使用说明:
(1)子目录在删除前必须是空的,也就是说需要先进入该子目录,使用DEL(删除文件的命令)将其子目录下的文件删空,然后再退回到上一级目录,用RD命令删除该了目录本身;
(2)不能删除根目录和当前目录。
例:要求把C盘FOX子目录下的USER子目录删除,操作如下:
第一步:先将USER子目录下的文件删空;
C、>DEL C:、FOX、USER、*。*
第二步,删除USER子目录。
C、>RD C:、FOX、USER
(四)DIR——显示磁盘目录命令
1.功能:显示磁盘目录的内容。
2.类型:内部命令
3.格式:DIR [盘符][路径][/P][/W]
4. 使用说明:/P的使用;当欲查看的目录太多,无法在一屏显示完屏幕会一直往上卷,不容易看清,加上/P参数后,屏幕上会分面一次显示23行的文件信息,然后暂停,并提示;Press any key to continue
/W的使用:加上/W只显示文件名,至于文件大小及建立的日期和时间则都省略。加上参数后,每行可以显示五个文件名。
(五)PATH——路径设置命令
1.功能:设备可执行文件的搜索路径,只对文件有效。
2.类型:内部命令
3.格式:PATH[盘符1]目录[路径名1]{[;盘符2:],〈目录路径名2〉…}
4.使用说明:
(1)当运行一个可执行文件时,DOS会先在当前目录中搜索该文件,若找到则运行之;若找不到该文件,则根据PATH命令所设置的路径,顺序逐条地到目录中搜索该文件;
(2)PATH命令中的路径,若有两条以上,各路径之间以一个分号“;”隔开;
(3)PATH命令有三种使用方法:
PATH[盘符1:][路径1][盘符2:][路径2]…(设定可执行文件的搜索路径)
PATH:(取消所有路径)
PATH:(显示目前所设的路径)
(六)TREE——显示磁盘目录结构命令
1.功能:显示指定驱动器上所有目录路径和这些目录下的所有文件名。
2.类型:外部命令
3.格式:TREE[盘符:][/F][》PRN]
4.使用说明:
(1)使用/F参数时显示所有目录及目录下的所有文件,省略时,只显示目录,不显示目录下的文件;
(2)选用>PRN参数时,则把所列目录及目录中的文件名打印输出。
(七)DELTREE——删除整个目录命令
1.功能:将整个目录及其下属子目录和文件删除。
2.类型:外部命令
3.格式:DELTREE[盘符:]〈路径名〉
4.使用说明:该命令可以一步就将目录及其下的所有文件、子目录、更下层的子目录一并删除,而且不管文件的属性为隐藏、系统或只读,只要该文件位于删除的目录之下,DELTREE都一视同仁,照删不误。使用时务必小心!!!
五、磁盘操作类命令
(一)FORMAT——磁盘格式化命令
1.功能:对磁盘进行格式化,划分磁道和扇区;同时检查出整个磁盘上有无带缺陷的磁道,对坏道加注标记;建立目录区和文件分配表,使磁盘作好接收DOS的准备。
2.类型:外部命令
3.格式:FORMAT〈盘符:〉[/S][/4][/Q]
4.使用说明:
(1)命令后的盘符不可缺省,若对硬盘进行格式化,则会如下列提示:WARNING:ALL DATA ON NON ——REMOVABLE DISK
DRIVE C:WILL BE LOST !
Proceed with Format (Y/N)?
(警告:所有数据在C盘上,将会丢失,确实要继续格式化吗?)
(2)若是对软盘进行格式化,则会如下提示:Insert mew diskette for drive A;
and press ENTER when ready…
(在A驱中插入新盘,准备好后按回车键)。
(3)选用[/S]参数,将把DOS系统文件IO.SYS 、MSDOS.SYS及COMMAND.COM复制到磁盘上,使该磁盘可以做为DOS启动盘。若不选用/S参数,则格式化后的磙盘只能读写信息,而不能做为启动盘;
(4)选用[/4]参数,在1.2MB的高密度软驱中格式化360KB的低密度盘;
(5)选用[/Q]参数,快速格式化,这个参数并不会重新划分磁盘的磁道貌岸然和扇区,只能将磁盘根目录、文件分配表以及引导扇区清成空白,因此,格式化的速度较快。
(6)选用[/U]参数,表示无条件格式化,即破坏原来磁盘上所有数据。不加/U,则为安全格式化,这时先建立一个镜象文件保存原来的FAT表和根目录,必要时可用UNFORRMAT恢复原来的数据。
(二)UNFORMAT恢复格式化命令
1.功能:对进行过格式化误操作丢失数据的磁盘进行恢复。
2.类型:外部命令
3.格式:UNFORMAT〈盘符〉[/L][/U][/P][/TEST]
4.使用说明:用于将被“非破坏性”格式化的磁盘恢复。根目录下被删除的文件或子目录及磁盘的系统扇区(包括FAT、根目录、BOOT扇区及硬盘分区表)受损时,也可以用UNFORMAT来抢救。
(1)选用/L参数列出找到的子目录名称、文件名称、大孝日期等信息,但不会真的做FORMAT工作。
(2)选用/P参数将显示于屏幕的报告(包含/L参数所产生的信息)同时也送到打印机。运行时屏幕会显示:“Print out will be sent to LPT1”
(3)选用/TEST参数只做模拟试验(TEST)不做真正的写入动作。使用此参数屏幕会显示:“Simulation only”
(4)选用/U参数不使用MIRROR映像文件的数据,直接根据磁盘现状进行UNFORMAT。
(5)选用/PSRTN;修复硬盘分区表。
若在盘符之后加上/P、/L、/TEST之一,都相当于使用了/U参数,UNFORMAT会“假设”此时磁盘没有MIRROR映像文件。
注意:UNFORMAT对于刚FORMAT的磁盘,可以完全恢复,但FORMAT后若做了其它数据的写入,则UNFORMAT就不能完整的救回数据了。UNFORMAT并非是万能的,由于使用UNFORMAT会重建FAT与根目录,所以它也具有较高的危险性,操作不当可能会扩大损失,如果仅误删了几个文件或子目录,只需要利用UNDELETE就够了。
DOS命令
(一)MD——建立子目录
1.功能:创建新的子目录
2.类型:内部命令
3.格式:MD[盘符:][路径名]〈子目录名〉
4.使用说明:
(1)“盘符”:指定要建立子目录的磁盘驱动器字母,若省略,则为当前驱动器;
(2)“路径名”:要建立的子目录的上级目录名,若缺省则建在当前目录下。
例:(1)在C盘的根目录下创建名为FOX的子目录;(2)在FOX子目录下再创建USER子目录。
C:、>MD FOX (在当前驱动器C盘下创建子目录FOX)
C:、>MD FOX 、USER (在FOX 子目录下再创建USER子目录)
(二)CD——改变当前目录
1.功能:显示当前目录
2.类型:内部命令
3.格式:CD[盘符:][路径名][子目录名]
4.使用说明:
(1)如果省略路径和子目录名则显示当前目录;
(2)如采用“CD、”格式,则退回到根目录;
(3)如采用“CD.。”格式则退回到上一级目录。
例:(1)进入到USER子目录;(2)从USER子目录退回到子目录;(3)返回到根目录。
C:、>CD FOX 、USER(进入FOX子目录下的USER子目录)
C:、FOX、USER>CD.。 (退回上一级根目录)
C:、FOX>CD、 (返回到根目录)
C:、>
(三)RD——删除子目录命令
1.功能:从指定的磁盘删除了目录。
2.类型:内部命令
3.格式:RD[盘符:][路径名][子目录名]
4.使用说明:
(1)子目录在删除前必须是空的,也就是说需要先进入该子目录,使用DEL(删除文件的命令)将其子目录下的文件删空,然后再退回到上一级目录,用RD命令删除该了目录本身;
(2)不能删除根目录和当前目录。
例:要求把C盘FOX子目录下的USER子目录删除,操作如下:
第一步:先将USER子目录下的文件删空;
C、>DEL C:、FOX、USER、*。*
第二步,删除USER子目录。
C、>RD C:、FOX、USER
(四)DIR——显示磁盘目录命令
1.功能:显示磁盘目录的内容。
2.类型:内部命令
3.格式:DIR [盘符][路径][/P][/W]
4. 使用说明:/P的使用;当欲查看的目录太多,无法在一屏显示完屏幕会一直往上卷,不容易看清,加上/P参数后,屏幕上会分面一次显示23行的文件信息,然后暂停,并提示;Press any key to continue
/W的使用:加上/W只显示文件名,至于文件大小及建立的日期和时间则都省略。加上参数后,每行可以显示五个文件名。
(五)PATH——路径设置命令
1.功能:设备可执行文件的搜索路径,只对文件有效。
2.类型:内部命令
3.格式:PATH[盘符1]目录[路径名1]{[;盘符2:],〈目录路径名2〉…}
4.使用说明:
(1)当运行一个可执行文件时,DOS会先在当前目录中搜索该文件,若找到则运行之;若找不到该文件,则根据PATH命令所设置的路径,顺序逐条地到目录中搜索该文件;
(2)PATH命令中的路径,若有两条以上,各路径之间以一个分号“;”隔开;
(3)PATH命令有三种使用方法:
PATH[盘符1:][路径1][盘符2:][路径2]…(设定可执行文件的搜索路径)
PATH:(取消所有路径)
PATH:(显示目前所设的路径)
(六)TREE——显示磁盘目录结构命令
1.功能:显示指定驱动器上所有目录路径和这些目录下的所有文件名。
2.类型:外部命令
3.格式:TREE[盘符:][/F][》PRN]
4.使用说明:
(1)使用/F参数时显示所有目录及目录下的所有文件,省略时,只显示目录,不显示目录下的文件;
(2)选用>PRN参数时,则把所列目录及目录中的文件名打印输出。
(七)DELTREE——删除整个目录命令
1.功能:将整个目录及其下属子目录和文件删除。
2.类型:外部命令
3.格式:DELTREE[盘符:]〈路径名〉
4.使用说明:该命令可以一步就将目录及其下的所有文件、子目录、更下层的子目录一并删除,而且不管文件的属性为隐藏、系统或只读,只要该文件位于删除的目录之下,DELTREE都一视同仁,照删不误。使用时务必小心!!!
五、磁盘操作类命令
(一)FORMAT——磁盘格式化命令
1.功能:对磁盘进行格式化,划分磁道和扇区;同时检查出整个磁盘上有无带缺陷的磁道,对坏道加注标记;建立目录区和文件分配表,使磁盘作好接收DOS的准备。
2.类型:外部命令
3.格式:FORMAT〈盘符:〉[/S][/4][/Q]
4.使用说明:
(1)命令后的盘符不可缺省,若对硬盘进行格式化,则会如下列提示:WARNING:ALL DATA ON NON ——REMOVABLE DISK
DRIVE C:WILL BE LOST !
Proceed with Format (Y/N)?
(警告:所有数据在C盘上,将会丢失,确实要继续格式化吗?)
(2)若是对软盘进行格式化,则会如下提示:Insert mew diskette for drive A;
and press ENTER when ready…
(在A驱中插入新盘,准备好后按回车键)。
(3)选用[/S]参数,将把DOS系统文件IO.SYS 、MSDOS.SYS及COMMAND.COM复制到磁盘上,使该磁盘可以做为DOS启动盘。若不选用/S参数,则格式化后的磙盘只能读写信息,而不能做为启动盘;
(4)选用[/4]参数,在1.2MB的高密度软驱中格式化360KB的低密度盘;
(5)选用[/Q]参数,快速格式化,这个参数并不会重新划分磁盘的磁道貌岸然和扇区,只能将磁盘根目录、文件分配表以及引导扇区清成空白,因此,格式化的速度较快。
(6)选用[/U]参数,表示无条件格式化,即破坏原来磁盘上所有数据。不加/U,则为安全格式化,这时先建立一个镜象文件保存原来的FAT表和根目录,必要时可用UNFORRMAT恢复原来的数据。
(二)UNFORMAT恢复格式化命令
1.功能:对进行过格式化误操作丢失数据的磁盘进行恢复。
2.类型:外部命令
3.格式:UNFORMAT〈盘符〉[/L][/U][/P][/TEST]
4.使用说明:用于将被“非破坏性”格式化的磁盘恢复。根目录下被删除的文件或子目录及磁盘的系统扇区(包括FAT、根目录、BOOT扇区及硬盘分区表)受损时,也可以用UNFORMAT来抢救。
(1)选用/L参数列出找到的子目录名称、文件名称、大孝日期等信息,但不会真的做FORMAT工作。
(2)选用/P参数将显示于屏幕的报告(包含/L参数所产生的信息)同时也送到打印机。运行时屏幕会显示:“Print out will be sent to LPT1”
(3)选用/TEST参数只做模拟试验(TEST)不做真正的写入动作。使用此参数屏幕会显示:“Simulation only”
(4)选用/U参数不使用MIRROR映像文件的数据,直接根据磁盘现状进行UNFORMAT。
(5)选用/PSRTN;修复硬盘分区表。
若在盘符之后加上/P、/L、/TEST之一,都相当于使用了/U参数,UNFORMAT会“假设”此时磁盘没有MIRROR映像文件。
注意:UNFORMAT对于刚FORMAT的磁盘,可以完全恢复,但FORMAT后若做了其它数据的写入,则UNFORMAT就不能完整的救回数据了。UNFORMAT并非是万能的,由于使用UNFORMAT会重建FAT与根目录,所以它也具有较高的危险性,操作不当可能会扩大损失,如果仅误删了几个文件或子目录,只需要利用UNDELETE就够了。
$().ready(
function()
{
var a = $('<div style="display:none"><div class="car_img1" id="bloomup2"><iframe src="/con/default/act/cardkindsintro" frameborder="0" scrolling="no" style="width:659px; height:438px"></iframe></div></div>');
$('body').append(a);//添加到body元素的最后.
}
);
function()
{
var a = $('<div style="display:none"><div class="car_img1" id="bloomup2"><iframe src="/con/default/act/cardkindsintro" frameborder="0" scrolling="no" style="width:659px; height:438px"></iframe></div></div>');
$('body').append(a);//添加到body元素的最后.
}
);
Cookie注意事项
1、SetCookie()之前不能有任何html输出,它认了第二,没有哪个元素敢认第一,就是空格,空白行都不行。
2、 SetCookie()后,你在当前页调用echo $_COOKIE["name"]不会有输出。必须刷新或到下一个页面才可以看到Cookie值。原因很简单。SetCookie()执行之后,往客户端发送一个cookie,你不刷新或浏览下一个页面,客户端怎么把cookie给你送回去呀?浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到 Cookie过期为止。
bool setcookie (string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure]]]]] )
其中中括号内可以省略
$name 参数为Cookie变量名
$value 参数为COOkie值
$expire Cookie的失效时间 ,$expire是标准的UNIX时间标记,可以用time()函数或者mktime()函数获取,单位为秒,如:time()+3600*24*30表示Cookie的有效期为一个月,如果不进行设置默认为会话期间,即关闭浏览器时Cookie失效!
$path Cookie在服务器的有效路径
$domain Cookie有效域名
$secure 指明Cookie是否仅通过安全的HTTPS值为0或1,如果为1,则cookie只能在HTTPS连接有效;如果值为默认值0,则在HTTP和HTTPS连接上均有效
阅读全文
1、SetCookie()之前不能有任何html输出,它认了第二,没有哪个元素敢认第一,就是空格,空白行都不行。
2、 SetCookie()后,你在当前页调用echo $_COOKIE["name"]不会有输出。必须刷新或到下一个页面才可以看到Cookie值。原因很简单。SetCookie()执行之后,往客户端发送一个cookie,你不刷新或浏览下一个页面,客户端怎么把cookie给你送回去呀?浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到 Cookie过期为止。
bool setcookie (string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure]]]]] )
其中中括号内可以省略
$name 参数为Cookie变量名
$value 参数为COOkie值
$expire Cookie的失效时间 ,$expire是标准的UNIX时间标记,可以用time()函数或者mktime()函数获取,单位为秒,如:time()+3600*24*30表示Cookie的有效期为一个月,如果不进行设置默认为会话期间,即关闭浏览器时Cookie失效!
$path Cookie在服务器的有效路径
$domain Cookie有效域名
$secure 指明Cookie是否仅通过安全的HTTPS值为0或1,如果为1,则cookie只能在HTTPS连接有效;如果值为默认值0,则在HTTP和HTTPS连接上均有效
阅读全文
cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业。由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动、关闭这个服务:
/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置
你也可以将这个服务在系统启动的时候自动启动:
在/etc/rc.d/rc.local这个脚本的末尾加上:
现在Cron这个服务已经在进程里面了,我们就可以用这个服务了,Cron服务提供以下几种接口供大家使用:
1、直接用crontab命令编辑
cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:
比如说root查看自己的cron设置:crontab -u root -l
再例如,root想删除fred的cron设置:crontab -u fred -r
在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e
进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt
这个格式的前一部分是对时间的设定,后面一部分是要执行的命令,如果要执行的命令太多,可以把这些命令写到一个脚本里面,然后在这里直接调用这个脚本就可以了,调用的时候记得写出命令的完整路径。时间的设定我们有一定的约定,前面五个*号代表五个数字,数字的取值范围和含义如下:
分钟 (0-59)
小時 (0-23)
日期 (1-31)
月份 (1-12)
星期 (0-6)//0代表星期天
除了数字还有几个个特殊的符号就是"*"、"/"和"-"、",",*代表所有的取值范围内的数字,"/"代表每的意思,"*/5"表示每5个单位,"-"代表从某个数字到某个数字,","分开几个离散的数字。以下举几个例子说明问题:
每天早上6点
每两个小时
晚上11点到早上8点之间每两个小时,早上八点
每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
1月1日早上4点
0 4 1 1 * command line
每次编辑完某个用户的cron设置后,cron自动在/var/spool/cron下生成一个与此用户同名的文件,此用户的cron信息都记录在这个文件中,这个文件是不可以直接编辑的,只可以用crontab -e 来编辑。cron启动后每过一份钟读一次这个文件,检查是否要执行里面的命令。因此此文件修改后不需要重新启动cron服务。
2、编辑/etc/crontab 文件配置cron
cron服务每分钟不仅要读一次/var/spool/cron内的所有文件,还需要读一次/etc/crontab,因此我们配置这个文件也能运用 cron服务做一些事情。用crontab配置是针对某个用户的,而编辑/etc/crontab是针对系统的任务。此文件的文件格式是:
大家注意"run-parts"这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了。
--------------------------------------
基本格式 :
* * * * * command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
crontab文件的一些例子:
30 21 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每晚的21:30重启lighttpd 。
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每月1、10、22日的4 : 45重启lighttpd 。
10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每周六、周日的1 : 10重启lighttpd 。
0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启lighttpd 。
0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每星期六的11 : 00 pm重启lighttpd 。
* */1 * * * /usr/local/etc/rc.d/lighttpd restart
每一小时重启lighttpd
* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart
晚上11点到早上7点之间,每隔一小时重启lighttpd
0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart
每月的4号与每周一到周三的11点重启lighttpd
0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart
一月一号的4点重启lighttpd
/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置
你也可以将这个服务在系统启动的时候自动启动:
在/etc/rc.d/rc.local这个脚本的末尾加上:
/sbin/service crond start
现在Cron这个服务已经在进程里面了,我们就可以用这个服务了,Cron服务提供以下几种接口供大家使用:
1、直接用crontab命令编辑
cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:
crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务
比如说root查看自己的cron设置:crontab -u root -l
再例如,root想删除fred的cron设置:crontab -u fred -r
在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e
进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt
这个格式的前一部分是对时间的设定,后面一部分是要执行的命令,如果要执行的命令太多,可以把这些命令写到一个脚本里面,然后在这里直接调用这个脚本就可以了,调用的时候记得写出命令的完整路径。时间的设定我们有一定的约定,前面五个*号代表五个数字,数字的取值范围和含义如下:
分钟 (0-59)
小時 (0-23)
日期 (1-31)
月份 (1-12)
星期 (0-6)//0代表星期天
除了数字还有几个个特殊的符号就是"*"、"/"和"-"、",",*代表所有的取值范围内的数字,"/"代表每的意思,"*/5"表示每5个单位,"-"代表从某个数字到某个数字,","分开几个离散的数字。以下举几个例子说明问题:
每天早上6点
0 6 * * * echo "Good morning." >> /tmp/test.txt //注意单纯echo,从屏幕上看不到任何输出,因为cron把任何输出都email到
root的信箱了。每两个小时
0 */2 * * * echo "Have a break now." >> /tmp/test.txt
晚上11点到早上8点之间每两个小时,早上八点
0 23-7/2,8 * * * echo "Have a good dream:)" >> /tmp/test.txt
每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3 command line
1月1日早上4点
0 4 1 1 * command line
每次编辑完某个用户的cron设置后,cron自动在/var/spool/cron下生成一个与此用户同名的文件,此用户的cron信息都记录在这个文件中,这个文件是不可以直接编辑的,只可以用crontab -e 来编辑。cron启动后每过一份钟读一次这个文件,检查是否要执行里面的命令。因此此文件修改后不需要重新启动cron服务。
2、编辑/etc/crontab 文件配置cron
cron服务每分钟不仅要读一次/var/spool/cron内的所有文件,还需要读一次/etc/crontab,因此我们配置这个文件也能运用 cron服务做一些事情。用crontab配置是针对某个用户的,而编辑/etc/crontab是针对系统的任务。此文件的文件格式是:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root //如果出现错误,或者有数据输出,数据作为邮件发给这个帐号
HOME=/ //使用者运行的路径,这里是根目录
# run-parts
01 * * * * root run-parts /etc/cron.hourly //每小时执行/etc/cron.hourly内的脚本
02 4 * * * root run-parts /etc/cron.daily //每天执行/etc/cron.daily内的脚本
22 4 * * 0 root run-parts /etc/cron.weekly //每星期执行/etc/cron.weekly内的脚本
42 4 1 * * root run-parts /etc/cron.monthly //每月去执行/etc/cron.monthly内的脚本
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root //如果出现错误,或者有数据输出,数据作为邮件发给这个帐号
HOME=/ //使用者运行的路径,这里是根目录
# run-parts
01 * * * * root run-parts /etc/cron.hourly //每小时执行/etc/cron.hourly内的脚本
02 4 * * * root run-parts /etc/cron.daily //每天执行/etc/cron.daily内的脚本
22 4 * * 0 root run-parts /etc/cron.weekly //每星期执行/etc/cron.weekly内的脚本
42 4 1 * * root run-parts /etc/cron.monthly //每月去执行/etc/cron.monthly内的脚本
大家注意"run-parts"这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了。
--------------------------------------
基本格式 :
* * * * * command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
crontab文件的一些例子:
30 21 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每晚的21:30重启lighttpd 。
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每月1、10、22日的4 : 45重启lighttpd 。
10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每周六、周日的1 : 10重启lighttpd 。
0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启lighttpd 。
0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每星期六的11 : 00 pm重启lighttpd 。
* */1 * * * /usr/local/etc/rc.d/lighttpd restart
每一小时重启lighttpd
* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart
晚上11点到早上7点之间,每隔一小时重启lighttpd
0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart
每月的4号与每周一到周三的11点重启lighttpd
0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart
一月一号的4点重启lighttpd
进一步学习请看vim发布的帮助文档
VIM常用操作
k
h l
J
当前光标位置插入 i
所在行首位置插入 I
当前光标位置后面插入 a
在行尾编辑 A
当前行下面另起一新行 o
当前行上面另起一新行 O
删除换行符 J (即把一行连接到当前行)
删除光标所在字符 x
删除光标所在前一个字符 X
删除整行 dd
删除到行尾 D
删除当前光标所在字符后编辑 s
退格 Ctrl-h
删除当前行后编辑 S
撤消 u ,可以撤消多次
重做 Ctrl + R
重复上一个改变 . (Dot)
查前当前字的man页 相当于执行 : !man
屏幕左下角非空白处 L
屏幕中间非空白处 M
屏幕左上角非空白处 H
向后移动一个word的开头 W, w (这两个有稍微的区别,W 以空白区分字)
向前移动一个word B, b(这两个有稍微的区别)
移到当前word的最后一个字符 e
移动到当前行行尾 $
移动到当前行的第一个 ^
非空白字符上
移动到当前行的第一个字符上 0 (zero)
单字符搜索命令(向右) f : 命令"fx"在当前行上查找下一个字符x
单字符搜索命令(向左) F
跳转到匹配的括号去 % 包括 { } [ ] ( ) 具体可以处理哪 些括号可以
由'matchpairs'选项来定义: help mps
跳转到第一行 gg (or 1G)
跳转到最后一行 G
跳转到第 n 行 nG 如 5G
跳转到文件的百分之N行 N% 如 90%跳到接近文件尾的地方
移动到当前窗口的中间 M
当前在文件中的位置 CTRL-G
向上滚动半屏 CTRL-U
向下滚动半屏 CTRL-D
向上滚动一屏 CTRL-B
向下滚动一屏 CTRL-F
将光标所在行调整至页面中间 zz
下卷一行 Ctrl+e
上卷一行 Ctrl+y
简单搜索(向后) 如 /include 搜索单词 "include"
简单搜索(向前) 如 ?include
查找当前单词的下一个位置 *
查找当前单词的上一个位置 #
Visual模式
V (整行的选择)
Ctrl-v 选择一个区域内容
Shift-v 选择一个矩行区域
光标后粘贴 p
光标前粘贴 P
复制一行 Y
复制 y (需加一行辅助如 y3w 复制3个单词)
寄存器复制(a-z) 如复制3行放到寄存器 a中 "a3Y
寄存器粘贴 "aP
复制到剪切版 "+y
剪切到剪切版 "+x
从剪切版粘贴 "+gp
只读方式打开文件 Vim -R filename
折叠
环境变量 foldmethod 有6种值 manual、indent、expr、syntax、diff、marker
对着折叠的行展开 0 (Zero)
创建折叠区域 zf 后加上移动指令,如 zfj、 zf5k等
在括号处zf%,创建从当前行起到对应的匹配的括号上去((),{},[],<>等)。
折叠 zc
对所在范围内所有嵌套的 zC
折叠点展开折叠
展开折叠 zo
对所在范围内所有嵌套的 zO
处展开折叠
到当前打开的折叠的开始处。 [z
到当前打开的折叠的末尾处。 ]z
向下移动。到达下一个折叠的 zj
开始处。关闭的折叠也被计入。
向上移动到前一折叠的结束处。 zk
关闭的折叠也被计入。
删除 (delete) 在光标下的 zd (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
折叠。
循环删除 (Delete) 光标下 zD (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
的折叠,即嵌套删除折叠。
除去 (Eliminate) 窗口里 zE (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
“所有”的折叠
窗口操作
水平分隔 split
垂直分隔 vsplit
新建一个窗口 new
关闭当前窗口 close
关闭其它窗口 only
增加当前窗口高度 Ctrl+W +
减小当前窗口高度 Ctrl+W -
指定固定高度 {height}Ctrl+W _
切换活动窗口 Ctrl+W w 或 Ctrl+W Ctrl+W
到左边窗口 Ctrl+W h
到右边窗口 Ctrl+W l
到上边窗口 Ctrl+W k
到下边窗口 Ctrl+W j
到顶部窗口 Ctrl+W t
到底部窗口 Ctrl+W b
排版
向右缩进 >>
向左缩进 <<
右移当前行所在的{....} >i}
内的所有代码(不含"{"和"}")
一个shiftwidth个空格
<i{ 相反 <i} 一样效果
右移当前行所在的{....} >a}
内的所有代码(含"{"和"}")
一个shiftwidth个空格
<a{ 相反 <a} 一样效果
大小写转换
行小写 guu
行大写 gUU
行翻转 g~~
标签页Vim在7以后的版本,开始支持标签页的功能
新建一个标签 :tabnew
转到下一个标签 :tabnext
转到上一个标签 :tabprevious
标签 mark--方便跳来跳去
m 标签指令,mx把当前位置标为x, x 可为 a-z A-Z
'x 跳至标签为 x 所在行的行首非空白处
`x 跳至标签为 x 所在行标签时的位置
编辑多个文件
:n 下一个文件
:N 上一个文件
:first 第一个文件
:last 最后一个文件
:qa 全部退出
映射表
:map Normal, Visual and Operator-pending
:vmap Visual
:nmap Normal
:omap Operator-pending
:map! Insert and Command-line
:imap Insert
:cmap Command-line
<silent> 不在命令行上显示该映射
例子:
映射< 为 <>
:imap < x<Esc>r<a><Esc>ha
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xuzhihong_gdut/archive/2009/01/15/3788220.aspx
VIM常用操作
k
h l
J
当前光标位置插入 i
所在行首位置插入 I
当前光标位置后面插入 a
在行尾编辑 A
当前行下面另起一新行 o
当前行上面另起一新行 O
删除换行符 J (即把一行连接到当前行)
删除光标所在字符 x
删除光标所在前一个字符 X
删除整行 dd
删除到行尾 D
删除当前光标所在字符后编辑 s
退格 Ctrl-h
删除当前行后编辑 S
撤消 u ,可以撤消多次
重做 Ctrl + R
重复上一个改变 . (Dot)
查前当前字的man页 相当于执行 : !man
屏幕左下角非空白处 L
屏幕中间非空白处 M
屏幕左上角非空白处 H
向后移动一个word的开头 W, w (这两个有稍微的区别,W 以空白区分字)
向前移动一个word B, b(这两个有稍微的区别)
移到当前word的最后一个字符 e
移动到当前行行尾 $
移动到当前行的第一个 ^
非空白字符上
移动到当前行的第一个字符上 0 (zero)
单字符搜索命令(向右) f : 命令"fx"在当前行上查找下一个字符x
单字符搜索命令(向左) F
跳转到匹配的括号去 % 包括 { } [ ] ( ) 具体可以处理哪 些括号可以
由'matchpairs'选项来定义: help mps
跳转到第一行 gg (or 1G)
跳转到最后一行 G
跳转到第 n 行 nG 如 5G
跳转到文件的百分之N行 N% 如 90%跳到接近文件尾的地方
移动到当前窗口的中间 M
当前在文件中的位置 CTRL-G
向上滚动半屏 CTRL-U
向下滚动半屏 CTRL-D
向上滚动一屏 CTRL-B
向下滚动一屏 CTRL-F
将光标所在行调整至页面中间 zz
下卷一行 Ctrl+e
上卷一行 Ctrl+y
简单搜索(向后) 如 /include 搜索单词 "include"
简单搜索(向前) 如 ?include
查找当前单词的下一个位置 *
查找当前单词的上一个位置 #
Visual模式
V (整行的选择)
Ctrl-v 选择一个区域内容
Shift-v 选择一个矩行区域
光标后粘贴 p
光标前粘贴 P
复制一行 Y
复制 y (需加一行辅助如 y3w 复制3个单词)
寄存器复制(a-z) 如复制3行放到寄存器 a中 "a3Y
寄存器粘贴 "aP
复制到剪切版 "+y
剪切到剪切版 "+x
从剪切版粘贴 "+gp
只读方式打开文件 Vim -R filename
折叠
环境变量 foldmethod 有6种值 manual、indent、expr、syntax、diff、marker
对着折叠的行展开 0 (Zero)
创建折叠区域 zf 后加上移动指令,如 zfj、 zf5k等
在括号处zf%,创建从当前行起到对应的匹配的括号上去((),{},[],<>等)。
折叠 zc
对所在范围内所有嵌套的 zC
折叠点展开折叠
展开折叠 zo
对所在范围内所有嵌套的 zO
处展开折叠
到当前打开的折叠的开始处。 [z
到当前打开的折叠的末尾处。 ]z
向下移动。到达下一个折叠的 zj
开始处。关闭的折叠也被计入。
向上移动到前一折叠的结束处。 zk
关闭的折叠也被计入。
删除 (delete) 在光标下的 zd (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
折叠。
循环删除 (Delete) 光标下 zD (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
的折叠,即嵌套删除折叠。
除去 (Eliminate) 窗口里 zE (仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。)
“所有”的折叠
窗口操作
水平分隔 split
垂直分隔 vsplit
新建一个窗口 new
关闭当前窗口 close
关闭其它窗口 only
增加当前窗口高度 Ctrl+W +
减小当前窗口高度 Ctrl+W -
指定固定高度 {height}Ctrl+W _
切换活动窗口 Ctrl+W w 或 Ctrl+W Ctrl+W
到左边窗口 Ctrl+W h
到右边窗口 Ctrl+W l
到上边窗口 Ctrl+W k
到下边窗口 Ctrl+W j
到顶部窗口 Ctrl+W t
到底部窗口 Ctrl+W b
排版
向右缩进 >>
向左缩进 <<
右移当前行所在的{....} >i}
内的所有代码(不含"{"和"}")
一个shiftwidth个空格
<i{ 相反 <i} 一样效果
右移当前行所在的{....} >a}
内的所有代码(含"{"和"}")
一个shiftwidth个空格
<a{ 相反 <a} 一样效果
大小写转换
行小写 guu
行大写 gUU
行翻转 g~~
标签页Vim在7以后的版本,开始支持标签页的功能
新建一个标签 :tabnew
转到下一个标签 :tabnext
转到上一个标签 :tabprevious
标签 mark--方便跳来跳去
m 标签指令,mx把当前位置标为x, x 可为 a-z A-Z
'x 跳至标签为 x 所在行的行首非空白处
`x 跳至标签为 x 所在行标签时的位置
编辑多个文件
:n 下一个文件
:N 上一个文件
:first 第一个文件
:last 最后一个文件
:qa 全部退出
映射表
:map Normal, Visual and Operator-pending
:vmap Visual
:nmap Normal
:omap Operator-pending
:map! Insert and Command-line
:imap Insert
:cmap Command-line
<silent> 不在命令行上显示该映射
例子:
映射< 为 <>
:imap < x<Esc>r<a><Esc>ha
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xuzhihong_gdut/archive/2009/01/15/3788220.aspx
无意间想看一下各个门户网站所使用的编码,于是习惯性的用自己写的HTTP调试工具来看。
新浪、网易、搜狐这中国互联网原生的3个大佬,都是gb2312的页面编码。
web服务器方面来看,网易用了nginx,sohu和sina用的是apache,sina是2.0,sohu是1.3
web服务器架构上来看,三个都用了squid来做前端缓冲,至于是否使用负载均衡的软硬件就无法探测得知了。
从此可见,技术领先上,网易第一,新浪次之,sohu最土。而从他们的经营情况来看,也是这个排序。
互联网是一个新技术几乎每时每刻都出现的行业领域,每一次有重大的新技术出现,如果能对现有环境产生巨大改变的,那必然会造就一个时代的英雄出来,网易是,borland是,Google是,就连微软和Oracle都是,占据技术制高点,是成功的法宝!IT企业在技术方面的投入多少,也侧面反映了他们能走到的高度情况。当然这里的前提是非盲目性投资,盲目的投资就像土财主买了个MBA证书一样的可笑。
后话,至于UTF8编码他们都没采用,也能想得通,如果全更换为UTF8,他们的带宽和系统负载需要提高将近一倍,而他们的受众群体都是华人,明显得不偿失。
新浪、网易、搜狐这中国互联网原生的3个大佬,都是gb2312的页面编码。
web服务器方面来看,网易用了nginx,sohu和sina用的是apache,sina是2.0,sohu是1.3
web服务器架构上来看,三个都用了squid来做前端缓冲,至于是否使用负载均衡的软硬件就无法探测得知了。
从此可见,技术领先上,网易第一,新浪次之,sohu最土。而从他们的经营情况来看,也是这个排序。
互联网是一个新技术几乎每时每刻都出现的行业领域,每一次有重大的新技术出现,如果能对现有环境产生巨大改变的,那必然会造就一个时代的英雄出来,网易是,borland是,Google是,就连微软和Oracle都是,占据技术制高点,是成功的法宝!IT企业在技术方面的投入多少,也侧面反映了他们能走到的高度情况。当然这里的前提是非盲目性投资,盲目的投资就像土财主买了个MBA证书一样的可笑。
后话,至于UTF8编码他们都没采用,也能想得通,如果全更换为UTF8,他们的带宽和系统负载需要提高将近一倍,而他们的受众群体都是华人,明显得不偿失。
404不正确页面的优势可能在于不用调用Rewrite模块,Rewrite须要调用此模块。因此404不正确页面可能会更节省资源,使大型站点的速度更快一些。我编写的静态化网页,目前大多数都是运用 404不正确。
运用 404不正确页面,不能被POST和GET。例如305.php?name1=auiou,假如此305.php页面是用404不正确产生,则此$_GET["name1"]的值不会被读取。其它页面的
运用 POST要领将action指向此404不正确产生的305.php,也不能被接收,例如所发送的信息不能被305.php接收。
如果您希望产生的虚拟路径如305.php被POST和GET,运用 Rewrite可处理。
404不正确页面的开头有一些Linux空间必须写入这句,有一些Linux空间则必须写为才可以被搜索引擎收入,否则会被认为是404页面。调试时,可以在网上搜索“404 检测工具”执行 测试。
Rewrite能不能须要写语句,我还没有测试过。
404不正确页面的准则相对不严格,因此有更好的适应范围。Rewrite相对更严格,例如305.html与305-1.html须要写2个重写准则;运用 404不正确页面只要一个准则即可。这也是我运用 404不正确,而不运用 Rewrite的另一个主要原由。
我是这么写的:
RewriteRule /con/user/act/gift [L,R=404]
[L,R=404]// # NOTE! FOR APACHE ON WINDOWS
运用 404不正确页面,不能被POST和GET。例如305.php?name1=auiou,假如此305.php页面是用404不正确产生,则此$_GET["name1"]的值不会被读取。其它页面的
运用 POST要领将action指向此404不正确产生的305.php,也不能被接收,例如所发送的信息不能被305.php接收。
如果您希望产生的虚拟路径如305.php被POST和GET,运用 Rewrite可处理。
404不正确页面的开头有一些Linux空间必须写入这句,有一些Linux空间则必须写为才可以被搜索引擎收入,否则会被认为是404页面。调试时,可以在网上搜索“404 检测工具”执行 测试。
Rewrite能不能须要写语句,我还没有测试过。
404不正确页面的准则相对不严格,因此有更好的适应范围。Rewrite相对更严格,例如305.html与305-1.html须要写2个重写准则;运用 404不正确页面只要一个准则即可。这也是我运用 404不正确,而不运用 Rewrite的另一个主要原由。
#RewriteRule ^(.*)$ [L,r=404]
#RewriteRule ^(.*)$ - [L,r=404]
RewriteRule ^(.*)$ /error404.html [L,r=404]
#RewriteRule ^(.*)$ - [L,r=404]
RewriteRule ^(.*)$ /error404.html [L,r=404]
我是这么写的:
RewriteRule /con/user/act/gift [L,R=404]
为了使Apache更加平滑地从1.3版升级到2.0版,Apache开发团队做了很多工作。目前很多重要的模块已经可以很好地支持2.0版,如PHP、FastCGI、Mod_perl、Mod_python等。在httpd.conf的指令配置语法上,目前的2.0版(2.0.45)与1.3版的兼容性已做得相当好。比如,以前的2.0版如果要使用PHP,一般用过滤器实现;现在的PHP官方文档中已经使用1.3版中的LoadModule语句做为加载PHP的推荐方式。只要略微了解一下Apache 2.0的新特性,从1.3版升级到2.0版将是一件非常容易的事情。使用Apache 2.0是大势所趋,因为Apache的开发团队已经把开发重心转移到2.0版上。1.3版自2002年10月发布了1.3.27后一直没有新版本推出,而2.0版在与1.3.27同时发布2.0.43后,在今年1月发布了2.0.44,并于今年3月末发布了2.0.45,并包含了很多改进和修正。
MPM的引入带来性能改善
Apache 2.0在性能上的改善最吸引人。在支持POSIX线程的Unix系统上,Apache可以通过不同的MPM运行在一种多进程与多线程相混合的模式下,增强部分配置的可扩充性能。相比于Apache 1.3,2.0版本做了大量的优化来提升处理能力和可伸缩性,并且大多数改进在默认状态下即可生效。但是在编译和运行时刻,2.0也有许多可以显著提高性能的选择。本文不想叙述那些以功能换取速度的指令,如HostnameLookups等,而只是说明在2.0中影响性能的最核心特性:MPM(Multi-Processing Modules,多道处理模块)的基本工作原理和配置指令。
毫不夸张地说,MPM的引入是Apache 2.0最重要的变化。大家知道,Apache是基于模块化的设计,而Apache 2.0更扩展了模块化设计到Web服务器的最基本功能。服务器装载了一种多道处理模块,负责绑定本机网络端口、接受请求,并调度子进程来处理请求。扩展模块化设计有两个重要好处:
◆ Apache可以更简洁、有效地支持多种操作系统;
◆ 服务器可以按站点的特殊需要进行自定制。
在用户级,MPM看起来和其它Apache模块非常类似。主要区别是在任意时刻只能有一种MPM被装载到服务器中。
指定MPM的方法
下面以Red Hat Linux 9为平台,说明在Apache 2.0中如何指定MPM (Apache采用2.0.45)。先解压缩源代码包httpd-2.0.45.tar.gz,生成httpd-2.0.45目录(Apache 1.3源代码包的命名规则是apache_1.3.NN.tar.gz,而2.0版则是httpd-2.0.NN.tar.gz,其中NN是次版本号)。
进入httpd-2.0.45目录,运行以下代码:
显示如下:
上述操作用来选择要使用的进程模型,即哪种MPM模块。Beos、mpmt_os2分别是BeOS和OS/2上缺省的MPM,perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要CGI的虚拟主机时特别有用,会比1.3版中的SuExec机制做得更好。leader和threadpool都是基于worker的变体,还处于实验性阶段,某些情况下并不会按照预期设想的那样工作,所以Apache官方也并不推荐使用。因此,我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM ( 有关其它的MPM详细说明,请参见Apache官方文档:http://httpd.apache.org/docs-2.0/mod/)。
prefork的工作原理及配置
如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM。它所采用的预派生子进程方式也是Apache 1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。
若使用prefork,在make编译和make install安装后,使用“httpd -l”来确定当前使用的MPM,应该会看到prefork.c(如果看到worker.c说明使用的是worker MPM,依此类推)。再查看缺省生成的httpd.conf配置文件,里面包含如下配置段:
prefork的工作原理是,控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:
◆ 可防止意外的内存泄漏;
◆ 在服务器负载下降的时侯会自动减少子进程数。
因此,可根据服务器的负载来调整这个值。笔者认为10000左右比较合适。
MaxClients是这些指令中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。如果把这个值设为大于256,那么Apache将无法起动。事实上,256对于负载稍重的站点也是不够的。在Apache 1.3中,这是个硬限制。如果要加大这个值,必须在“configure”前手工修改的源代码树下的src/include/httpd.h中查找256,就会发现“#define HARD_SERVER_LIMIT 256”这行。把256改为要增大的值(如4000),然后重新编译Apache即可。在Apache 2.0中新加入了ServerLimit指令,使得无须重编译Apache就可以加大MaxClients。下面是笔者的prefork配置段:
上述配置中,ServerLimit的最大值是20000,对于大多数站点已经足够。如果一定要再加大这个数值,对位于源代码树下server/mpm/prefork/prefork.c中以下两行做相应修改即可:
worker的工作原理及配置
相对于prefork,worker是2.0 版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,钥梢源硐喽院A康那肭螅低匙试吹目∮诨诮痰姆衿鳌5牵瑆orker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。这种MPM的工作方式将是Apache 2.0的发展趋势。
在configure -with-mpm=worker后,进行make编译、make install安装。在缺省生成的httpd.conf中有以下配置段:
worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用ThreadLimit指令,它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行:
这两行对应着ThreadsPerChild和ThreadLimit的限制数。最好在configure之前就把64改成所希望的值。注意,不要把这两个值设得太高,超过系统的处理能力,从而因Apache不起动使系统很不稳定。
Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。这两个值位于源码树server/mpm/worker/worker.c中的以下两行:
需要注意的是,如果显式声明了ServerLimit,那么它乘以ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则Apache将会自动调节到一个相应值(可能是个非期望值)。下面是笔者的worker配置段:
<IfModule worker.c>
StartServers 3
MaxClients 2000
ServerLimit 25
MinSpareThreads 50
MaxSpareThreads 200
ThreadLimit 200
ThreadsPerChild 100
MaxRequestsPerChild 0
</IfModule>
通过上面的叙述,可以了解到Apache 2.0中prefork和worker这两个重要MPM的工作原理,并可根据实际情况来配置Apache相关的核心参数,以获得最大的性能和稳定性。
我的配置:
MPM的引入带来性能改善
Apache 2.0在性能上的改善最吸引人。在支持POSIX线程的Unix系统上,Apache可以通过不同的MPM运行在一种多进程与多线程相混合的模式下,增强部分配置的可扩充性能。相比于Apache 1.3,2.0版本做了大量的优化来提升处理能力和可伸缩性,并且大多数改进在默认状态下即可生效。但是在编译和运行时刻,2.0也有许多可以显著提高性能的选择。本文不想叙述那些以功能换取速度的指令,如HostnameLookups等,而只是说明在2.0中影响性能的最核心特性:MPM(Multi-Processing Modules,多道处理模块)的基本工作原理和配置指令。
毫不夸张地说,MPM的引入是Apache 2.0最重要的变化。大家知道,Apache是基于模块化的设计,而Apache 2.0更扩展了模块化设计到Web服务器的最基本功能。服务器装载了一种多道处理模块,负责绑定本机网络端口、接受请求,并调度子进程来处理请求。扩展模块化设计有两个重要好处:
◆ Apache可以更简洁、有效地支持多种操作系统;
◆ 服务器可以按站点的特殊需要进行自定制。
在用户级,MPM看起来和其它Apache模块非常类似。主要区别是在任意时刻只能有一种MPM被装载到服务器中。
指定MPM的方法
下面以Red Hat Linux 9为平台,说明在Apache 2.0中如何指定MPM (Apache采用2.0.45)。先解压缩源代码包httpd-2.0.45.tar.gz,生成httpd-2.0.45目录(Apache 1.3源代码包的命名规则是apache_1.3.NN.tar.gz,而2.0版则是httpd-2.0.NN.tar.gz,其中NN是次版本号)。
进入httpd-2.0.45目录,运行以下代码:
$ ./configure --help|grep mpm
显示如下:
--with-mpm=MPM Choose the process model for Apache to use. MPM={beos|worker|prefork|mpmt_os2| perchild|leader|threadpool}
上述操作用来选择要使用的进程模型,即哪种MPM模块。Beos、mpmt_os2分别是BeOS和OS/2上缺省的MPM,perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要CGI的虚拟主机时特别有用,会比1.3版中的SuExec机制做得更好。leader和threadpool都是基于worker的变体,还处于实验性阶段,某些情况下并不会按照预期设想的那样工作,所以Apache官方也并不推荐使用。因此,我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM ( 有关其它的MPM详细说明,请参见Apache官方文档:http://httpd.apache.org/docs-2.0/mod/)。
prefork的工作原理及配置
如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM。它所采用的预派生子进程方式也是Apache 1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。
若使用prefork,在make编译和make install安装后,使用“httpd -l”来确定当前使用的MPM,应该会看到prefork.c(如果看到worker.c说明使用的是worker MPM,依此类推)。再查看缺省生成的httpd.conf配置文件,里面包含如下配置段:
<IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
prefork的工作原理是,控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:
◆ 可防止意外的内存泄漏;
◆ 在服务器负载下降的时侯会自动减少子进程数。
因此,可根据服务器的负载来调整这个值。笔者认为10000左右比较合适。
MaxClients是这些指令中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。如果把这个值设为大于256,那么Apache将无法起动。事实上,256对于负载稍重的站点也是不够的。在Apache 1.3中,这是个硬限制。如果要加大这个值,必须在“configure”前手工修改的源代码树下的src/include/httpd.h中查找256,就会发现“#define HARD_SERVER_LIMIT 256”这行。把256改为要增大的值(如4000),然后重新编译Apache即可。在Apache 2.0中新加入了ServerLimit指令,使得无须重编译Apache就可以加大MaxClients。下面是笔者的prefork配置段:
<IfModule prefork.c> StartServers 10 MinSpareServers 10 MaxSpareServers 15 ServerLimit 2000 MaxClients 1000 MaxRequestsPerChild 10000 </IfModule>
上述配置中,ServerLimit的最大值是20000,对于大多数站点已经足够。如果一定要再加大这个数值,对位于源代码树下server/mpm/prefork/prefork.c中以下两行做相应修改即可:
1.define DEFAULT_SERVER_LIMIT 256
2.define MAX_SERVER_LIMIT 20000
2.define MAX_SERVER_LIMIT 20000
worker的工作原理及配置
相对于prefork,worker是2.0 版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,钥梢源硐喽院A康那肭螅低匙试吹目∮诨诮痰姆衿鳌5牵瑆orker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。这种MPM的工作方式将是Apache 2.0的发展趋势。
在configure -with-mpm=worker后,进行make编译、make install安装。在缺省生成的httpd.conf中有以下配置段:
<IfModule worker.c> StartServers 2 MaxClients 150 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 </IfModule>
worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用ThreadLimit指令,它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行:
1.define DEFAULT_THREAD_LIMIT 64
2.define MAX_THREAD_LIMIT 20000
2.define MAX_THREAD_LIMIT 20000
这两行对应着ThreadsPerChild和ThreadLimit的限制数。最好在configure之前就把64改成所希望的值。注意,不要把这两个值设得太高,超过系统的处理能力,从而因Apache不起动使系统很不稳定。
Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。这两个值位于源码树server/mpm/worker/worker.c中的以下两行:
1.define DEFAULT_SERVER_LIMIT 16
2.define MAX_SERVER_LIMIT 20000
2.define MAX_SERVER_LIMIT 20000
需要注意的是,如果显式声明了ServerLimit,那么它乘以ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则Apache将会自动调节到一个相应值(可能是个非期望值)。下面是笔者的worker配置段:
<IfModule worker.c>
StartServers 3
MaxClients 2000
ServerLimit 25
MinSpareThreads 50
MaxSpareThreads 200
ThreadLimit 200
ThreadsPerChild 100
MaxRequestsPerChild 0
</IfModule>
通过上面的叙述,可以了解到Apache 2.0中prefork和worker这两个重要MPM的工作原理,并可根据实际情况来配置Apache相关的核心参数,以获得最大的性能和稳定性。
我的配置:
<IfModule prefork.c>
StartServers 150
MinSpareServers 100
MaxSpareServers 150
ServerLimit 6193
#ServerLimit 2150
MaxClients 824
#MaxClients 600
MaxRequestsPerChild 0
</IfModule>
StartServers 150
MinSpareServers 100
MaxSpareServers 150
ServerLimit 6193
#ServerLimit 2150
MaxClients 824
#MaxClients 600
MaxRequestsPerChild 0
</IfModule>
------以下引用php手册内容--------------
要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。
下面的例子说明了如何删除刚才设置的 cookie: 例子 2. setcookie() 删除
例子
// 将过期时间设为一小时前
删除一个cookie的方法就是把这个cookie的有效期设置为当前时间以前,这
也是几乎所有php程序员都会这么做。
后来一个初接触php的朋友告诉我,他在程序中本想把一个cookie的值设置为
空,结果导致这个cookie直接被删除。我当时的第一反应是不相信,于是测试
了一下
setcookie("testcookie", '');
print_r($_COOKIE);
结果果然是整个$_COOKIE数组都是空的,而非仅仅$_COOKIE['testcookie']为
空.于是用winsock抓包,观察返回的http头,发现http头竟然是
Set-Cookie: testcookie=deleted; expires=Mon, 18-Jun-2007 02:42:33 GMT
这说明setcookie("testcookie", '');的的确确是将testcookie这个cookie直
接删除.而关于这种情况在php手册中完全没有说明.
最后阅读php源码,终于发现真相(这就是开源的好处了,有什么不清楚的内幕
直接查源码)
以下代码可以在php5.20的linux源码包中ext/standard/head.c第99行附近找到.
if (value && value_len == 0) {
/*
* MSIE doesn't delete a cookie when you set it to a null value
* so in order to force cookies to be deleted, even on MSIE, we
* pick an expiry date 1 year and 1 second in the past
*/
time_t t = time(NULL) - 31536001;
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC);
sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
efree(dt);
} else {
sprintf(cookie, "Set-Cookie: %s=%s", name, value ? encoded_value : "");
if (expires > 0) {
strcat(cookie, "; expires=");
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);
strcat(cookie, dt);
efree(dt);
}
}
源码中清清楚楚的显示,if (value && value_len == 0) ,当value_len为0
时
最后我们可以得出结论,在php中使用
bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )
要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。
下面的例子说明了如何删除刚才设置的 cookie: 例子 2. setcookie() 删除
例子
// 将过期时间设为一小时前
setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);
----------------引用结束--------------------------setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);
删除一个cookie的方法就是把这个cookie的有效期设置为当前时间以前,这
也是几乎所有php程序员都会这么做。
后来一个初接触php的朋友告诉我,他在程序中本想把一个cookie的值设置为
空,结果导致这个cookie直接被删除。我当时的第一反应是不相信,于是测试
了一下
setcookie("testcookie", '');
print_r($_COOKIE);
结果果然是整个$_COOKIE数组都是空的,而非仅仅$_COOKIE['testcookie']为
空.于是用winsock抓包,观察返回的http头,发现http头竟然是
Set-Cookie: testcookie=deleted; expires=Mon, 18-Jun-2007 02:42:33 GMT
这说明setcookie("testcookie", '');的的确确是将testcookie这个cookie直
接删除.而关于这种情况在php手册中完全没有说明.
最后阅读php源码,终于发现真相(这就是开源的好处了,有什么不清楚的内幕
直接查源码)
以下代码可以在php5.20的linux源码包中ext/standard/head.c第99行附近找到.
if (value && value_len == 0) {
/*
* MSIE doesn't delete a cookie when you set it to a null value
* so in order to force cookies to be deleted, even on MSIE, we
* pick an expiry date 1 year and 1 second in the past
*/
time_t t = time(NULL) - 31536001;
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC);
sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
efree(dt);
} else {
sprintf(cookie, "Set-Cookie: %s=%s", name, value ? encoded_value : "");
if (expires > 0) {
strcat(cookie, "; expires=");
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);
strcat(cookie, dt);
efree(dt);
}
}
源码中清清楚楚的显示,if (value && value_len == 0) ,当value_len为0
时
sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
会发送删除cookie的http头给浏览器.最后我们可以得出结论,在php中使用
setcookie($cookiename, '');或者 setcookie($cookiename, NULL);
都会删除cookie,当然这些手册中并没有。