摘要: 分类:计算机技术 字号: 大大  中中  小小 [文章作者:张宴 本文版本:v4.10 最后修改:2008.12.23 转载请注明原文链接:http://blog.s135.com/post/366.htm]   前言:本文是我撰写的关于搭建“Nginx + PHP(FastCGI)”Web服务器的第4篇文章。本系列文章作为国内最早详细...  阅读全文
posted @ 2009-03-06 12:21 小马歌 阅读(331) | 评论 (1)编辑 收藏
 

1,启动和控制

/etc/rc.d/init.d/lighttpd start [stop] [restart]

2,如果没有启动起来,手工命令行敲一下:

/usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf

根据提示处理。

3,如果是提示关于{ 之类符号的,很可能是perl没有起作用。configure的–with-pcre,如果找不到pcre-devel是不报错的。rpm -q pcre-devel 看一下就知道了。

安装PHP:

官方下载PHP,configure 时候加上:’–enable-fastcgi’ ‘–enable-force-cgi-redirect’ ‘–enable-discard-path’,其他按实际需要。

我的例子:’./configure’ ‘–prefix=/usr/local/php’ ‘–with-gd’ ‘–with-mysql’ ‘–with-zlib’ ‘–with-freetype-dir=/usr/local/lib’ ‘–with-jpeg-dir=/usr/lib’ ‘–with-iconv’ ‘–with-curl’ ‘–enable-fastcgi’ ‘–enable-force-cgi-redirect’ ‘–enable-discard-path’

注意: 不能有’–with-apxs=/www/bin/apxs’之类的。

检查一下是否正确:/usr/local/php/bin/php -v

如果有(cgi-fcgi) 则安装正确,如果是(cli)那就没有安装对。

最好安上eaccelarator,教程很多,不累述。
调整lighttpd配置:

server.modules = (
“mod_rewrite”,
“mod_redirect”,
# “mod_alias”,
“mod_access”,
“mod_status”,
# “mod_setenv”,
“mod_fastcgi”,
# “mod_proxy”,
“mod_simple_vhost”,
# “mod_cgi”,
“mod_compress”,
“mod_expire”,
“mod_accesslog” )

fastcgi.server = ( “.php” =>
( “localhost” =>
(
“socket” => “/tmp/php-fastcgi.socket”,
“bin-path” => “/usr/local/php/bin/php”
)
)
)

复制安装目录下的文件:

cp spawn-php.sh /usr/local/lighttpd/bin/

调整设置:

cd /usr/local/lighttpd/bin
vi spawn-php.sh

修改下述变量为正确值:

SPAWNFCGI=”/usr/local/lighttpd/bin/spawn-fcgi”
FCGIPROGRAM=”/usr/local/php/bin/php”
FCGI_WEB_SERVER_ADDRS=”192.168.133.17″
USERID=nobody
GROUPID=nobody

运行一次:

[bin]$ ./spawn-php.sh
spawn-fcgi.c.207: child exited with: 0, Success

成功了,启动lighttpd
[bin]$ /etc/rc.d/init.d/lighttpd start
OK !

posted @ 2009-03-06 12:19 小马歌 阅读(1361) | 评论 (0)编辑 收藏
 
2008-08-27 10:00

这里我们先来区分两种填写表单的方法:
第一种,用鼠标在表单项中切换。这是我们经常用的,他们会先找到需要填写的第一项,用鼠标点上去,然后右手移到键盘上(我们暂且不管你的左手放在什么地方),填写信息,接着右手移到鼠标上,点选第二项,再把右手移到键盘上,填写信息……不断重复,直到表单填写完,最后用鼠标点击“提交表单”按钮。这样做起来非常不方便,尤其是用户体验上。
第二种,用Tab键切换。在填写表单时只在填第一项时用鼠标点选,该项填写完成后用Tab键切换至下一项,最后用回车键送出表单。整个填写过程中,双手只停留在键盘上,不用摸鼠标。
哪种方法的效率高?大家一定都有相同的答案。
有没有办法修正这一点呢?答案就是使用tabindex属性。


tabindex属性设置按下tab键时的响应顺序。它的值是一个数字,越小的数字响应顺序越靠前,最小为1。在未设置tabindex属性时,tab键将从页面的第一个链接或者表单项开始切换(这里要说明一个情况,IE浏览器中第一次按下tab键时,选中的是地址栏)。
利用tabindex的这一特性,我们就可以给表单里的各项添加相应的属性。比如一个登录表单,第一个表单项是“用户名”,我们就可以在这一项上添加tabindex=”1”,并依次为后面的项赋值。这样,在访问这个页面时,按下tab键后光标就停在“用户名”的文本输入框上,从而完全实现了无鼠标参与的表单填写。
此外,在某些网站的注册页面,部分表单项后面会跟着一个链接或者按钮,用来对当前项的需要输入的内容进行解释或验证。在未添加tabindex属性的页面,tab键会经过这些链接或按钮。熟练的tab键用户往往会在这上面犯错误——他们以为光标已经进入下一个文本框了,可实际却停在一个链接上。最糟的情况时,他们就完全找不到光标了,从而需要重新拿起鼠标来点选下一项。使用tabindex属性就可以很好的避免这一点。为每个表单项都添加tabindex,tab键就不会进入非填写区域了。
不过我很遗憾的发现,在我访问过的网站中,没有一家使用tabindex属性。

最后,我提供一段代码供您测试tabindex属性的作用。

<form id=”form” name=”form” method=”post” action=”">
<p><a href=”www.trade.cn”> 贸易视点网</a></p>
<p>第二项:
<label>
<input type=”text” tabindex=”2″ name=”textfield” />
</label>
</p>
<p>第一项:
<label>
<input type=”text” tabindex=”1″ name=”textfield2″ />
</label>
</p>
<p>第三项:
<label>
<input type=”text” tabindex=”3″ name=”textfield3″ />
</label>
</p>
</form>

posted @ 2009-03-04 12:02 小马歌 阅读(422) | 评论 (0)编辑 收藏
 
2008-08-26 11:27

     主要介绍如何在 Linux 系统上安装高性能的 HTTP 服务器 —— Nginx、并在不改变原有网站结构的条件下用 Nginx 来提升网站的访问速度。

Nginx 简介

Nginx("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。 Igor 将源代码以类BSD 许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。

根据最新一期(08 年 6 月份)的 NetCraft 调查报告显示,已经有超过两百万的主机使用了 Nginx,这个数字超过了另外一个轻量级的 HTTP 服务器 lighttpd, 排名第四,并且发展迅速。下面是这份报告的前几名的报表:

以下为引用的内容:
产品          网站数                    
Apache 84,309,103
IIS 60,987,087
Google GFE 10,465,178
Unknown 4,903,174
nginx 2,125,160
Oversee 1,953,848
lighttpd 1,532,952

            
关于这期调查报告的更详细信息请看下面链接:

http://survey.netcraft.com/Reports/200806/           

下图是最近几个月使用 Nginx 和 lighttpd 的网站数比较


                           
图 1. 最近几个月使用 Nginx 和 lighttpd 的网站数比较
                           

使用 Nginx 前必须了解的事项
           
目前官方 Nginx 并不支持 Windows,您只能在包括 Linux、UNIX、BSD 系统下安装和使用;
Nginx 本身只是一个 HTTP 和反向代理服务器,它无法像 Apache 一样通过安装各种模块来支持不同的页面脚本,例如 PHP、CGI 等;
Nginx 支持简单的负载均衡和容错;
支持作为基本 HTTP 服务器的功能,例如日志、压缩、Byte ranges、Chunked responses、SSL、虚拟主机等等,应有尽有。
            在 Linux 下安装 Nginx
            为了确保能在 Nginx 中使用正则表达式进行更灵活的配置,安装之前需要确定系统是否安装有 PCRE(Perl Compatible Regular Expressions)包。您可以到 ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的 PCRE 源码包,使用下面命令下载编译和安装 PCRE 包

# wget ftp://ftp.csx.cam.ac.uk/pub/soft ... cre/pcre-7.7.tar.gz
# tar zxvf pcre-7.7.tar.gz
# cd pcre-7.7
# ./configure
# make
# make install
                        

            接下来安装 Nginx,Nginx 一般有两个版本,分别是稳定版开发版,您可以根据您的目的来选择这两个版本的其中一个,下面是把 Nginx 安装到 /opt/nginx 目录下的详细步骤:
           

# wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz
# tar zxvf nginx-0.6.31.tar.gz


# cd nginx-0.6.31
# ./configure --with-http_stub_status_module –prefix=/opt/nginx
# make
# make install
                        

            其中参数 --with-http_stub_status_module 是为了启用 nginx 的 NginxStatus 功能,用来监控 Nginx 的当前状态。
            安装成功后 /opt/nginx 目录下有四个子目录分别是:conf、html、logs、sbin 。其中 Nginx 的配置文件存放于conf/nginx.conf,Nginx 只有一个程序文件位于 sbin 目录下的 nginx 文件。确保系统的 80端口没被其他程序占用,运行 sbin/nginx 命令来启动 Nginx,打开浏览器访问此机器的 IP,如果浏览器出现 Welcome tonginx! 则表示 Nginx 已经安装并运行成功。
            常用的 Nginx 参数和控制
            程序运行参数
            Nginx 安装后只有一个程序文件,本身并不提供各种管理程序,它是使用参数和系统信号机制对 Nginx 进程本身进行控制的。 Nginx 的参数包括有如下几个:
                            -c <path_to_config>:使用指定的配置文件而不是 conf 目录下的 nginx.conf 。
                            -t:测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。
                            -v:显示 nginx 版本号。

-V:显示 nginx 的版本号以及编译环境信息以及编译时的参数。

例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令

sbin/nginx – t – c conf/nginx2.conf

通过信号对 Nginx 进行控制

Nginx 支持下表中的信号:

信号名                                             作用描述                    

TERM, INT 快速关闭程序,中止当前正在处理的请求

QUIT 处理完当前请求后,关闭程序

HUP 重新加载配置,并开启新的工作进程,关闭就的进程,此操作不会中断请求

USR1 重新打开日志文件,用于切换日志,例如每天生成一个新的日志文件

USR2 平滑升级可执行程序

WINCH 从容关闭工作进程

有两种方式来通过这些信号去控制 Nginx,第一是通过 logs 目录下的 nginx.pid 查看当前运行的 Nginx 的进程 ID,通过 kill – XXX <pid> 来控制 Nginx,其中 XXX 就是上表中列出的信号名。如果您的系统中只有一个 Nginx 进程,那您也可以通过 killall 命令来完成,例如运行 killall – s HUP nginx 来让 Nginx 重新加载配置。

配置 Nginx

先来看一个实际的配置文件:

以下为引用的内容:
            user nobody;# 工作进程的属主
worker_processes 4;# 工作进程数,一般与 CPU 核数等同

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid        logs/nginx.pid;

events {
    use epoll;#Linux 下性能最好的 event 模式
    worker_connections 2048;# 每个工作进程允许最大的同时连接数
}

http {
    include       mime.types;
    default_type application/octet-stream;

    #log_format main '$remote_addr - $remote_user [$time_local] $request '
    #                  '"$status" $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log off;
    access_log logs/access.log;# 日志文件名

    sendfile        on;
    #tcp_nopush     on;
    tcp_nodelay     on;

    keepalive_timeout 65;

    include          gzip.conf;
   
    # 集群中的所有后台服务器的配置信息
    upstream tomcats {
         server 192.168.0.11:8080 weight=10;
         server 192.168.0.11:8081 weight=10;
         server 192.168.0.12:8080 weight=10;
         server 192.168.0.12:8081 weight=10;
         server 192.168.0.13:8080 weight=10;
         server 192.168.0.13:8081 weight=10;
    }

    server {
        listen       80;#HTTP 的端口
        server_name localhost;

        charset utf-8;

        #access_log logs/host.access.log main;

         location ~ ^/NginxStatus/ {
            stub_status on; #Nginx 状态监控配置
            access_log off;
         }

         location ~ ^/(WEB-INF)/ {
            deny all;
         }
       

         location ~ \.(htm|html|asp|php|gif|jpg|jpeg|png|bmp|ico|rar|css|js|
         zip|java|jar|txt|flv|swf|mid|doc|ppt|xls|pdf|txt|mp3|wma)$ {
             root /opt/webapp;
            expires 24h;
        }

        location / {
            proxy_pass http://tomcats;# 反向代理
            include proxy.conf;
        }

        error_page 404 /html/404.html;

        # redirect server error pages to the static page /50x.html
        #
         error_page 502 503 /html/502.html;
        error_page 500 504 /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

Nginx 监控

上面是一个实际网站的配置实例,其中灰色文字为配置说明。上述配置中,首先我们定义了一个 location ~^/NginxStatus/,这样通过 http://localhost/NginxStatus/ 就可以监控到 Nginx的运行信息,显示的内容如下:

以下为引用的内容:
Active connections: 70
server accepts handled requests
14553819 14553819 19239266
Reading: 0 Writing: 3 Waiting: 67

NginxStatus 显示的内容意思如下:
           
active connections – 当前 Nginx 正处理的活动连接数。

erveraccepts handled requests -- 总共处理了 14553819 个连接 , 成功创建 14553819 次握手 (证明中间没有失败的 ), 总共处理了 19239266 个请求 ( 平均每次握手处理了 1.3 个数据请求 )。

reading -- nginx 读取到客户端的 Header 信息数。

writing -- nginx 返回给客户端的 Header 信息数。

waiting -- 开启 keep-alive 的情况下,这个值等于 active - (reading + writing),意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接。

静态文件处理

通过正则表达式,我们可让 Nginx 识别出各种静态文件,例如 images 路径下的所有请求可以写为:

以下为引用的内容:
            location ~ ^/images/ {
    root /opt/webapp/images;
}
                        

            而下面的配置则定义了几种文件类型的请求处理方式。
            location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|ico|css|js|txt)$ {
    root /opt/webapp;
    expires 24h;
}

对于例如图片、静态 HTML 文件、js 脚本文件和 css 样式文件等,我们希望 Nginx 直接处理并返回给浏览器,这样可以大大的加快网页浏览时的速度。因此对于这类文件我们需要通过 root 指令来指定文件的存放路径,同时因为这类文件并不常修改,通过 expires 指令来控制其在浏览器的缓存,以减少不必要的请求。 expires 指令可以控制 HTTP 应答中的“ Expires ”和“ Cache-Control ”的头标(起到控制页面缓存的作用)。您可以使用例如以下的格式来书写 Expires:

以下为引用的内容:
expires 1 January, 1970, 00:00:01 GMT;
expires 60s;
expires 30m;
expires 24h;
expires 1d;
expires max;
expires off;

动态页面请求处理

Nginx本身并不支持现在流行的 JSP、ASP、PHP、PERL 等动态页面,但是它可以通过反向代理将请求发送到后端的服务器,例如Tomcat、Apache、IIS 等来完成动态页面的请求处理。前面的配置示例中,我们首先定义了由 Nginx直接处理的一些静态文件请求后,其他所有的请求通过 proxy_pass 指令传送给后端的服务器(在上述例子中是 Tomcat)。最简单的 proxy_pass 用法如下:

以下为引用的内容:
            location / {
    proxy_pass        http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
}

这里我们没有使用到集群,而是将请求直接送到运行在 8080 端口的 Tomcat 服务上来完成类似 JSP 和 Servlet 的请求处理。

当页面的访问量非常大的时候,往往需要多个应用服务器来共同承担动态页面的执行操作,这时我们就需要使用集群的架构。 Nginx 通过 upstream 指令来定义一个服务器的集群,最前面那个完整的例子中我们定义了一个名为 tomcats 的集群,这个集群中包括了三台服务器共 6 个 Tomcat 服务。而 proxy_pass 指令的写法变成了:

以下为引用的内容:
            location / {
    proxy_pass        http://tomcats;
    proxy_set_header X-Real-IP $remote_addr;
}

在 Nginx 的集群配置中,Nginx 使用最简单的平均分配规则给集群中的每个节点分配请求。一旦某个节点失效时,或者重新起效时,Nginx 都会非常及时的处理状态的变化,以保证不会影响到用户的访问。

总结

尽管整个程序包只有五百多 K,但麻雀虽小、五脏俱全。 Nginx官方提供的各种功能模块应有尽有,结合这些模块可以完整各种各样的配置要求,例如:压缩、防盗链、集群、FastCGI、流媒体服务器、Memcached 支持、URL 重写等等,更关键的是 Nginx 拥有 Apache 和其他 HTTP服务器无法比拟的高性能。您甚至可以在不改变原有网站的架构上,通过在前端引入 Nginx 来提升网站的访问速度。

posted @ 2009-03-04 12:01 小马歌 阅读(216) | 评论 (0)编辑 收藏
 
分支,标签,与合并几乎是所有版本控制系统的基本概念.如果你不熟悉这些功能,我们在这章提供了一个很好
的介绍.如果你非常熟悉了,也能很好的让你看看Subversion是如何实现这些功能的.
分支是版本控制的一项基本的功能.如果你将要使用Subversion来管理你的数据.这是一个特色你将最终依赖
它.这章要求你已经对Subversion的基本概念比较熟悉.

什么是分支?
假设你需要在你的电脑上维护一份被分离的文档,一个手册或是别的什么.某天要求你对同份文档做一个不同
的修改分离,但分离后他们两者只有一小部分不同,因此只有轻微的不同.
你将怎么解决这种处境?显而易见的方法是不是:可以再拷贝这份文档,然后保存两个不同的分离版本.当某个
部分要进行修改时,只要写入对应的文件就可以了.
经常需要对两个拷贝版本进行同样的修改.例如:如果发现一个打印错误在第一个文件里,这也很可能存在第二
个拷贝文件里.这两个文件是相同的的.
这就是分支的基本概念,一条基于另外一条开发线存在的分支.并共享在分离之前的日志.一个分支就象一个拷
贝的存在,并从那里离开,并具有自己的历史.
图:Figur 4.1. Branches of development
Subversion提供了一些功能来保持文件或目录分支的平行性.允许通过拷贝数据来创建分支,并记录与源文件
的关系.也能帮助你将一个分支的修改复制到另外其他的支流上.总的来说,能够映射出不同的工作拷贝.这样
就可以在不同的分支上进行工作.

使用分支
图:Figure 4.2. Starting repository layout
假设Sally与你同时拥有"calc"项目的工作副本,并都有/calc/trunk的工作副本.所有项目相关的文件都
在/calc目录下,因为你们的团队已经商定/calc/trunk用于存放开发主线.
此时你被要求完成一个任务就是新增项目的一个基本新特性.这将需要很长的时间来完成,并可能回影响到项
目中的大部分晚间.问题是你不想与Sally有任何冲突,她正在修改项目中的一些存在的小BUG.并依赖于最新发
布的项目版本,这里(/calc/trunk)主线版本是最有效的.如果你提交修改那么肯定会打乱Sally的修改工作.
一种策略就是进入一个空洞:你和Sally在一到两周内停止共享信息.那就是开始获取整顿在你工作副本的所有
文件,并不做任何提交一直到你完成工作任务.这个方案存在着很多问题,第一,这样一来做不安全.很多人喜欢
频繁的将工作结果上传到版本库,已防止工作副本被突发事件破坏引起的后果.第二,不够容易.如果你在不同
的机器上工作,你就需要手工的将工作副本进行拷贝修改.最后,当你完成你的所有修改后,你将发现很难将你
的工作合并到主线项目的代码中去.
更好的解决方法就是创,建所有你自己的分支.能频繁的提交工作在不与其他人的冲突下.也能有选择性的共享
信息.

创建一个分支
创建一个分支非常简单-只需要用svn copy命令拷贝项目就可以.Subversion不单支持单文件,也支持整个文件
目录的分支创建.在此例中,我们要拷贝/calc/trunk文件夹.那么应该把拷贝放在那里呢?任何地方你想要放置
的地方.这里需要提到项目的策略在库中有/calc/branches目录空间,并你想要拷贝的目录名重命名为my-
calc-branch.
有两种不同的方法来进行拷贝.首先介绍有些麻烦的方法.只是为了让概念清晰一点.首先,检出版本库./calc.
使用svn copy命令拷贝要进行分支的文件目录.
$ cd bigwc
$ svn copy trunk branches/my-calc-branch
$ svn status
A  +   branches/my-calc-branch
在这个例自立,拷贝命令递归拷贝trunk下的文件到新的工作目录.branches/my-calc-branch.你可以从svn
status 命令,心得目录被添加版本库中.同时注意"+"符号前面的字母A.他表明添加的列表是一些数据的拷贝,
并不是新添加的版本库的数据.当年提交修改后,版本库就会创建/calc/branches/my-calc-branch在版本库中
通过拷贝/calc/trunk,而不是通过工作副本将数据传送到版本库.
$ svn commit -m "Creating a private branch of /calc/trunk."
Adding         branches/my-calc-branch
Committed revision 341.
现在介绍一种简单的创建分支的方法,那就是可以通过给svn copy 命令传入两个URL路径来实现.
$ svn copy http://svn.example.com/repos/calc/trunk \
           http://svn.example.com/repos/calc/branches/my-calc-branch \
      -m "Creating a private branch of /calc/trunk."
Committed revision 341.
从版本库的角度来看,实际上这两种方法并无任何区别.注意区别只在与本地客户端,后者可以立即执行分支任
务,简单,并不需要你检出庞大的工作副本.这种方法是最常用的.
图 4.3. Repository with new copy

廉价的拷贝
Subversion的库经过特别的设计.当你拷贝一个文件目录是,你不需要担心会占用大量的版本库容量-实际上版
本库并不会真正的拷贝数据.取而代之的是建立一个新的目录路口来指向已存在的目录树.如果你是UNIX的用
户,这与磁盘连接的概念是相同的.后面对文件或是目录的修改也是影响被拷贝文件目录.任何能够使用该概念
的地方Subversion都会利用该理念.
这也是为什么听到廉价拷贝这个词.我们不需要担心文件目录有多大-拷贝的花费都是非常微小的.这种特性也
是每次提交所做的事,每个版本都是一次廉价拷贝.除了很少的一点修改数据进行保存.
当然,这些机制或数据共享对于用户都是隐藏不可见的.我们能简单的看到拷贝目录.主要点就是拷贝是非常廉
价的,无论是时间还是空间.如果你用这种方法拷贝是非常快的.当然可以随心所欲的进行分支.

使用分支进行工作
现在我们建立了项目的一个份支,我们就可以检出该分支并开始工作使用它.
$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch
A  my-calc-branch/Makefile
A  my-calc-branch/integer.c
A  my-calc-branch/button.c
Checked out revision 341.
这个工作副本并无任何特别之处;只是简单镜像了一个库中项目.当你提交修改后,Sally并不期望当她更新工
作副本的时候看到这些修改.因为她的工作副本是/calc/trunk.
让我们假设看看一个星期里所发生的事
      You make a change to /calc/branches/my-calc-branch/button.c, which creates revision 342.
      You make a change to /calc/branches/my-calc-branch/integer.c, which creates revision 343.
      Sally makes a change to /calc/trunk/integer.c, which creates revision 344.
现在这里有两条独立的开发线
图Figure 4.4. The branching of one file's history

分支背后的关键概念
这里有两点重要的内容需要在这里记住.第一,Subversion并没有冲突分支的概念-它只知道怎么去进行拷贝.
当你拷贝一个目录是,结果就是目录是一个独立的分支.你可能回想像一个不同的目录被建立或被处理.但对于
Subversion只是平常的目录控制区别只是再扩展一个历史日志信息.第二,因为这种拷贝机制,Subversion的分
支只是平常的存储在版本库中,而不像其他的版本控制系统,分支是真正存储了目录文件.
注意,Subversion并不支持不同版本库之间拷贝也使用映射机制,所以他只能在同版本库下工作.
posted @ 2009-03-04 11:38 小马歌 阅读(794) | 评论 (0)编辑 收藏
 
1. 请问交换机和路由器分别的实现原理是什么?分别在哪个层次上面实现的?

将网络互相连接起来要使用一些中间设备(或中间系统),ISO的术语称之为中继(re
lay)系统。根据中继系统所在的层次,可以有以下五种中继系统:
1)       物理层(即常说的第一层、层L1)中继系统,即转发器(repeater)。
2)       数据链路层(即第二层,层L2),即网桥或桥接器(bridge)。
3)       网络层(第三层,层L3)中继系统,即路由器(router)。
4)       网桥和路由器的混合物桥路器(brouter)兼有网桥和路由器的功能。
5)       在网络层以上的中继系统,即网关(gateway).
当中继系统是转发器时,一般不称之为网络互联,因为这仅仅是把一个网络扩大了,而这
仍然是一个网络。高层网关由于比较复杂,目前使用得较少。因此一般讨论网络互连时都
是指用交换机和路由器进行互联的网络。本文主要阐述交换机和路由器及其区别。  
2.  第二层交换机和路由器的区别:
传统交换机从网桥发展而来,属于OSI第二层即数据链路层设备。它根据MAC地址寻
址,通过站表选择路由,站表的建立和维护由交换机自动进行。路由器属于OSI第三层
即网络层设备,它根据IP地址进行寻址,通过路由表路由协议产生。因特网的路由选择
协议:内部网关协议IGP和外部网关协议EGP
3. 第三层交换机和路由器的区别:
在第三层交换技术出现之前,几乎没有必要将路由功能器件和路由器区别开来,他们完全
是相同的:提供路由功能正在路由器的工作,然而,现在第三层交换机完全能够执行传统
路由器的大多数功能。
综上所述,交换机一般用于LAN-WAN的连接,交换机归于网桥,是数据链路层的设
备,有些交换机也可实现第三层的交换。路由器用于WAN-WAN之间的连接,可以解
决异性网络之间转发分组,作用于网络层。他们只是从一条线路上接受输入分组,然后向
另一条线路转发。这两条线路可能分属于不同的网络,并采用不同协议。相比较而言,路
由器的功能较交换机要强大,但速度相对也慢,价格昂贵,第三层交换机既有交换机线速
转发报文能力,又有路由器良好的控制功能,因此得以广播应用。

----------------------------------------------------------------------

2.1    OSI和TCP/IP
1.  七层网络结构功能及特点--OSI
1)   物理层:为数据链路层提供物理连接,在其上串行传送比特流,即所传送数据的单位
是比特。此外,该层中还具有确定连接设备的电气特性和物理特性等功能。
2)   数据链路层:负责在网络节点间的线路上通过检测、流量控制和重发等手段,无差错
地传送以帧为单位的数据。为做到这一点,在每一帧中必须同时带有同步、地址、差错控
制及流量控制等控制信息。
3)   网络层:为了将数据分组从源(源端系统)送到目的地(目标端系统),网络层的任
务就是选择合适的路由和交换节点,使源的传输层传下来的分组信息能够正确无误地按照
地址找到目的地,并交付给相应的传输层,即完成网络的寻址功能。
4)   传输层:传输层是高低层之间衔接的接口层。数据传输的单位是报文,当报文较长时
将它分割成若干分组,然后交给网络层进行传输。传输层是计算机网络协议分层中的最关键
一层,该层以上各层将不再管理信息传输问题。
5)   会话层:该层对传输的报文提供同步管理服务。在两个不同系统的互相通信的应用进
程之间建立、组织和协调交互。例如,确定是双工还是半双工工作。
6)   表示层:该层的主要任务是把所传送的数据的抽象语法变换为传送语法,即把不同计
算机内部的不同表示形式转换成网络通信中的标准表示形式。此外,对传送的数据加密(
或解密)、正文压缩(或还原)也是表示层的任务。
7)   应用层:该层直接面向用户,是OSI中的最高层。它的主要任务是为用户提供应用的
接口,即提供不同计算机间的文件传送、访问与管理,电子邮件的内容处理,不同计算机
通过网络交互访问的虚拟终端功能等。
2. TCP/IP功能及特点
1)   网络接口层:这是TCP/IP协议的最低一层,包括有多种逻辑链路控制和媒体访问协议
。网络接口层的功能是接收IP数据报并通过特定的网络进行传输,或从网络上接收物理帧
,抽取出IP数据报并转交给网际层。
2)   网际网层(IP层):该层包括以下协议:IP(网际协议)、ICMP(Internet Contro
l Message Protocol,因特网控制报文协议)、ARP(Address Resolution Protocol,地址
解析协议)、RARP(Reverse Address Resolution Protocol,反向地址解析协议)。该层
负责相同或不同网络中计算机之间的通信,主要处理数据报和路由。在IP层中,ARP协议用
于将IP地址转换成物理地址,RARP协议用于将物理地址转换成IP地址,ICMP协议用于报告差
错和传送控制信息。IP协议在TCP/IP协议组中处于核心地位。
3)   传输层:该层提供TCP(传输控制协议)和UDP(User Datagram Protocol,用户数据
报协议)两个协议,它们都建立在IP协议的基础上,其中TCP提供可靠的面向连接服务,U
DP提供简单的无连接服务。传输层提供端到端,即应用程序之间的通信,主要功能是数据
格式化、数据确认和丢失重传等。
4)   应用层:TCP/IP协议的应用层相当于OSI模型的会话层、表示层和应用层,它向用户
提供一组常用的应用层协议,其中包括:Telnet、SMTP、DNS等。此外,在应用层中还包含
有用户应用程序,它们均是建立在TCP/IP协议组之上的专用程序。
3. OSI参考模型和TCP/IP参考模型的区别:
1)   OSI模型有7层,TCP/IP只有4层;
2)   OSI先于协议出现,因此不会偏向于任何一组特定的协议,通用性更强,但有些功能
不知该放哪一层上,因此不得不加入一些子层;TCP/IP后于协议出现,仅是将已有协议的
一个描述,因此两者配合的非常好;但他不适合其他的协议栈,不容易描述其他非TCP/IP
的网络;
3)   OSI中网络层同时支持无连接和面向连接的通信,但在传输层上只支持面向连接的通
信;TCP/IP中网络层只支持无连接通信,传输层同时支持两种通信;
4)   在技术发生变化时,OSI模型比TCP/IP模型中的协议更容易被替换。
4.         请你详细的解释一下IP协议的定义,在哪个层上面,主要有什么作用? TCP与
UDP呢? 
解:与IP协议配套使用的还有三个协议:
ARP-地址解析协议
RARP-逆地址解析协议
ICMP-因特网控制报文协议ICMP
IP协议-网际协议
IP地址、IP包头

posted @ 2009-03-02 18:05 小马歌 阅读(678) | 评论 (0)编辑 收藏
 
本文以RedHat9.0和i386平台为例,剖析了从用户打开电源直到屏幕出现命令行提示符的整个Linux启动过程。并且介绍了启动中涉及到的各种文件。

  阅读Linux源代码,无疑是深入学习Linux的最好方法。在本文对Linux启动过程的介绍中,我们也尝试从源代码的视角来更深入的剖析Linux的启动过程,所以其中也简单涉及到部分相关的Linux源代码,Linux启动这部分的源码主要使用的是C语言,也涉及到了少量的汇编。而启动过程中也执行了大量的shell(主要是bash shell)所写脚本。为了方便读者阅读,笔者将整个Linux启动过程分成以下几个部分逐一介绍,大家可以参考下图:

  当用户打开PC的电源,BIOS开机自检,按BIOS中设置的启动设备(通常是硬盘)启动,接着启动设备上安装的引导程序lilo或grub开始引导Linux,Linux首先进行内核的引导,接下来执行init程序,init程序调用了rc.sysinit和rc等程序,rc.sysinit和rc当完成系统初始化和运行服务的任务后,返回init;init启动了mingetty后,打开了终端供用户登录系统,用户登录成功后进入了Shell,这样就完成了从开机到登录的整个启动过程。

 

 

    下面就将逐一介绍其中几个关键的部分:


  第一部分:内核的引导(核内引导)

  Red Hat9.0可以使用lilo或grub等引导程序开始引导Linux系统,当引导程序成功完成引导任务后,Linux从它们手中接管了CPU的控制权,然后CPU就开始执行Linux的核心映象代码,开始了Linux启动过程。这里使用了几个汇编程序来引导Linux,这一步泛及到Linux源代码树中的“arch/i386/boot”下的这几个文件:bootsect.S、setup.S、video.S等。

  其中bootsect.S是生成引导扇区的汇编源码,它完成加载动作后直接跳转到setup.S的程序入口。setup.S的主要功能就是将系统参数(包括内存、磁盘等,由BIOS返回)拷贝到特别内存中,以便以后这些参数被保护模式下的代码来读取。此外,setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。最后,setup.S将系统转换到保护模式,并跳转到 0x100000。

  那么0x100000这个内存地址中存放的是什么代码?而这些代码又是从何而来的呢?

  0x100000这个内存地址存放的是解压后的内核,因为Red Hat提供的内核包含了众多驱动和功能而显得比较大,所以在内核编译中使用了“makebzImage”方式,从而生成压缩过的内核,在RedHat中内核常常被命名为vmlinuz,在Linux的最初引导过程中,是通过"arch/i386/boot/compressed/"中的head.S利用misc.c中定义的decompress_kernel()函数,将内核vmlinuz解压到0x100000的。

  当CPU跳到0x100000时,将执行"arch/i386/kernel/head.S"中的startup_32,它也是vmlinux的入口,然后就跳转到start_kernel()中去了。start_kernel()是"init/main.c"中的定义的函数,start_kernel()中调用了一系列初始化函数,以完成kernel本身的设置。start_kernel()函数中,做了大量的工作来建立基本的Linux核心环境。如果顺利执行完start_kernel(),则基本的Linux核心环境已经建立起来了。

  在start_kernel()的最后,通过调用init()函数,系统创建第一个核心线程,启动了init过程。而核心线程init()主要是来进行一些外设初始化的工作的,包括调用do_basic_setup()完成外设及其驱动程序的加载和初始化。并完成文件系统初始化和root文件系统的安装。

  当do_basic_setup()函数返回init(),init()又打开了/dev/console设备,重定向三个标准的输入输出文件stdin、stdout和stderr到控制台,最后,搜索文件系统中的init程序(或者由init=命令行参数指定的程序),并使用 execve()系统调用加载执行init程序。到此init()函数结束,内核的引导部分也到此结束了,

    第二部分:运行init


  init的进程号是1,从这一点就能看出,init进程是系统所有进程的起点,Linux在完成核内引导以后,就开始运行init程序,。init程序需要读取配置文件/etc/inittab。inittab是一个不可执行的文本文件,它有若干行指令所组成。在Redhat系统中,inittab的内容如下所示(以“###"开始的中注释为笔者增加的):

  #
  # inittab       This file describes how the INIT process should set up
  #               the system in a certain run-level.
  #
  # Author:       Miquel van Smoorenburg,

  #               Modified for RHS Linux by Marc Ewing and Donnie Barnes
  #

  # Default runlevel. The runlevels used by RHS are:
  #   0 - halt (Do NOT set initdefault to this)
  #   1 - Single user mode
  #   2 - Multiuser, without NFS (The same as 3, if you do not havenetworking)
  #   3 - Full multiuser mode
  #   4 - unused
  #   5 - X11
  #   6 - reboot (Do NOT set initdefault to this)
  #
  ###表示当前缺省运行级别为5(initdefault);
  id:5:initdefault:

  ###启动时自动执行/etc/rc.d/rc.sysinit脚本(sysinit)
  # System initialization.
  si::sysinit:/etc/rc.d/rc.sysinit

  l0:0:wait:/etc/rc.d/rc 0
  l1:1:wait:/etc/rc.d/rc 1
  l2:2:wait:/etc/rc.d/rc 2
  l3:3:wait:/etc/rc.d/rc 3
  l4:4:wait:/etc/rc.d/rc 4
  ###当运行级别为5时,以5为参数运行/etc/rc.d/rc脚本,init将等待其返回(wait)
  l5:5:wait:/etc/rc.d/rc 5
  l6:6:wait:/etc/rc.d/rc 6

  ###在启动过程中允许按CTRL-ALT-DELETE重启系统
  # Trap CTRL-ALT-DELETE
  ca::ctrlaltdel:/sbin/shutdown -t3 -r now

  # When our UPS tells us power has failed, assume we have a few minutes
  # of power left.  Schedule a shutdown for 2 minutes from now.
  # This does, of course, assume you have powerd installed and your
  # UPS connected and working correctly.
  pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"

  # If power was restored before the shutdown kicked in, cancel it.
  pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

  ###在2、3、4、5级别上以ttyX为参数执行/sbin/mingetty程序,打开ttyX终端用于用户登录,
  ###如果进程退出则再次运行mingetty程序(respawn)
  # Run gettys in standard runlevels
  1:2345:respawn:/sbin/mingetty tty1
  2:2345:respawn:/sbin/mingetty tty2
  3:2345:respawn:/sbin/mingetty tty3
  4:2345:respawn:/sbin/mingetty tty4
  5:2345:respawn:/sbin/mingetty tty5
  6:2345:respawn:/sbin/mingetty tty6

  ###在5级别上运行xdm程序,提供xdm图形方式登录界面,并在退出时重新执行(respawn)
  # Run xdm in runlevel 5
  x:5:respawn:/etc/X11/prefdm -nodaemon

以上面的inittab文件为例,来说明一下inittab的格式。其中以#开始的行是注释行,除了注释行之外,每一行都有以下格式:
  id:runlevel:action:process

  对上面各项的详细解释如下:

  1. id

  id是指入口标识符,它是一个字符串,对于getty或mingetty等其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。

  2. runlevel

  runlevel是init所处于的运行级别的标识,一般使用0-6以及S或s。0、1、6运行级别被系统保留:其中0作为shutdown动作,1作为重启至单用户模式,6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。在一般的系统实现中,都使用了2、3、4、5几个级别,在Redhat系统中,2表示无NFS支持的多用户模式,3表示完全多用户模式(也是最常用的级别),4保留给用户自定义,5表示XDM图形登录方式。7-9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。

  3. action

  action是描述其后的process的运行方式的。action可取的值包括:initdefault、sysinit、boot、bootwait等:

  initdefault是一个特殊的action值,用于标识缺省的启动级别;当init由核心激活以后,它将读取inittab中的initdefault项,取得其中的runlevel,并作为当前的运行级别。如果没有inittab文件,或者其中没有initdefault项,init将在控制台上请求输入runlevel。

  sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel。

  其余的action(不含initdefault)都与某个runlevel相关。各个action的定义在inittab的man手册中有详细的描述。

  4. process

  process为具体的执行程序。程序后面可以带参数。

  第三部分:系统初始化

  在init的配置文件中有这么一行:

  si::sysinit:/etc/rc.d/rc.sysinit

  它调用执行了/etc/rc.d/rc.sysinit,而rc.sysinit是一个bash shell的脚本,它主要是完成一些系统初始化的工作,rc.sysinit是每一个运行级别都要首先运行的重要脚本。它主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。

  rc.sysinit约有850多行,但是每个单一的功能还是比较简单,而且带有注释,建议有兴趣的用户可以自行阅读自己机器上的该文件,以了解系统初始化所详细情况。由于此文件较长,所以不在本文中列出来,也不做具体的介绍。

  当rc.sysinit程序执行完毕后,将返回init继续下一步。


第四部分:启动对应运行级别的守护进程


  在rc.sysinit执行后,将返回init继续其它的动作,通常接下来会执行到/etc/rc.d/rc程序。以运行级别3为例,init将执行配置文件inittab中的以下这行:

  l5:5:wait:/etc/rc.d/rc 5

  这一行表示以5为参数运行/etc/rc.d/rc,/etc/rc.d/rc是一个Shell脚本,它接受5作为参数,去执行/etc/rc.d/rc5.d/目录下的所有的rc启动脚本,/etc/rc.d/rc5.d/目录中的这些启动脚本实际上都是一些链接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。

  /etc/rc.d/rc5.d/中的rc启动脚本通常是K或S开头的链接文件,对于以以S开头的启动脚本,将以start参数来运行。而如果发现存在相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。

  至于在每个运行级中将运行哪些守护进程,用户可以通过chkconfig或setup中的"System Services"来自行设定。常见的守护进程有:

  amd:自动安装NFS守护进程
  apmd:高级电源管理守护进程
  arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和IP地址对数据库
  autofs:自动安装管理进程automount,与NFS相关,依赖于NIS
  crond:Linux下的计划任务的守护进程
  named:DNS服务器
  netfs:安装NFS、Samba和NetWare网络文件系统
  network:激活已配置网络接口的脚本程序
  nfs:打开NFS服务
  portmap:RPC portmap管理器,它管理基于RPC服务的连接
  sendmail:邮件服务器sendmail
  smb:Samba文件共享/打印服务
  syslog:一个让系统引导时起动syslog和klogd系统日志守候进程的脚本
  xfs:X Window字型服务器,为本地和远程X服务器提供字型集
  Xinetd:支持多种网络服务的核心守护进程,可以管理wuftp、sshd、telnet等服务

  这些守护进程也启动完成了,rc程序也就执行完了,然后又将返回init继续下一步。

    第五部分:建立终端


  rc执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开6个终端,以便用户登录系统。通过按Alt+Fn(n对应1-6)可以在这6个终端中切换。在inittab中的以下6行就是定义了6个终端:

  1:2345:respawn:/sbin/mingetty tty1
  2:2345:respawn:/sbin/mingetty tty2
  3:2345:respawn:/sbin/mingetty tty3
  4:2345:respawn:/sbin/mingetty tty4
  5:2345:respawn:/sbin/mingetty tty5
  6:2345:respawn:/sbin/mingetty tty6

  从上面可以看出在2、3、4、5的运行级别中都将以respawn方式运行mingetty程序,mingetty程序能打开终端、设置模式。同时它会显示一个文本登录界面,这个界面就是我们经常看到的登录界面,在这个登录界面中会提示用户输入用户名,而用户输入的用户将作为参数传给login程序来验证用户的身份。

  第六部分:登录系统,启动完成

  对于运行级别为5的图形方式用户来说,他们的登录是通过一个图形化的登录界面。登录成功后可以直接进入KDE、Gnome等窗口管理器。而本文主要讲的还是文本方式登录的情况:

  当我们看到mingetty的登录界面时,我们就可以输入用户名和密码来登录系统了。

  Linux的账号验证程序是login,login会接收mingetty传来的用户名作为用户名参数。然后login会对用户名进行分析:如果用户名不是root,且存在/etc/nologin文件,login将输出nologin文件的内容,然后退出。这通常用来系统维护时防止非root用户登录。只有/etc/securetty中登记了的终端才允许root用户登录,如果不存在这个文件,则root可以在任何终端上登录。/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

  在分析完用户名后,login将搜索/etc/passwd以及/etc/shadow来验证密码以及设置账户的其它信息,比如:主目录是什么、使用何种shell。如果没有指定主目录,将默认为根目录;如果没有指定shell,将默认为/bin/bash。

  login程序成功后,会向对应的终端在输出最近一次登录的信息(在/var/log/lastlog中有记录),并检查用户是否有新邮件(在/usr/spool/mail/的对应用户名目录下)。然后开始设置各种环境变量:对于bash来说,系统首先寻找/etc/profile脚本文件,并执行它;然后如果用户的主目录中存在.bash_profile文件,就执行它,在这些文件中又可能调用了其它配置文件,所有的配置文件执行后后,各种环境变量也设好了,这时会出现大家熟悉的命令行提示符,到此整个启动过程就结束了。

  希望通过上面对Linux启动过程的剖析能帮助那些想深入学习Linux用户建立一个相关Linux启动过程的清晰概念,进而可以进一步研究Linux接下来是如何工作的。

posted @ 2009-03-02 18:03 小马歌 阅读(126) | 评论 (0)编辑 收藏
 
[文章作者:张宴 本文版本:v1.0 最后修改:2007.11.16 转载请注明出处:http://blog.s135.com]

  最近遇到一个问题,Linux下的PHP命令行程序作为守护进程,需要从队列文件中读一行数据,通过TCP协议发送给外地的接收服务器,再读下一行数据,再发送。当本地与外地的网络状况不好时,有时候发送一条数据所耗费的时间就较长,累积起来容易造成队列堵塞和延迟。

  于是,我准备用该PHP命令行程序生成多个子进程,将串行处理变成并行处理。最简单的方法就是在PHP中用exec()或popen()函数将一个shell命令行推到后台去执行,例如:
<?php
exec("/bin/sh /opt/zhangyan.sh &");
?>
  最后的&表示将shell脚本推到后台去执行。

  但是这样会有一个问题,如果推到后台的进程太多,可能会导致服务器系统资源耗尽而崩溃,所以必须控制进程数量。



  我写了一个PHP程序(/opt/zhangyan.php)、一个shell程序(/opt/zhangyan.sh)作为测试用例。

  程序的逻辑:
  1、设置/opt/zhangyan.php最多允许生成500个子进程;
  2、当/opt/zhangyan.php读取到一条数据后,将允许生成的子进程数减1(空闲进程数$p_number=500-1=499),然后将数据交给/opt/zhangyan.sh去后台处理,不等待/opt/zhangyan.sh处理结束,继续读取下一条数据;
  3、当允许生成的子进程数减至0时(空闲进程数$p_number=0),/opt/zhangyan.php会等待1秒钟,然后检查后台还有多少个/opt/zhangyan.sh子进程尚未处理结束;
  4、如果1秒钟之后/opt/zhangyan.php发现后台的/opt/zhangyan.sh子进程数还是500(空闲进程数$p_number=0),会继续等待1秒钟,如此反复;
  5、如果/opt/zhangyan.php发现后台尚未处理结束的/opt/zhangyan.sh子进程数减少到300个了(空闲进程数$p_number=500-300=200),那么/opt/zhangyan.php会再往后台推送200个/opt/zhangyan.sh子进程;



/opt/zhangyan.php代码如下:
  1. <?php   
  2. function run($input)   
  3. {   
  4.     global $p_number;   
  5.     if ($p_number <= 0)   
  6.     {   
  7.         $p_number = worker_processes($p_number);   
  8.     }   
  9.     $p_number = $p_number - 1;   
  10.     $out = popen("/bin/sh /opt/zhangyan.sh \"{$input}\" &""r");   
  11.     pclose($out);   
  12. }   
  13.   
  14. function worker_processes($p_number)   
  15. {   
  16.     $limit = 500;//允许推到后台的最大进程数   
  17.     while ($p_number <= 0)   
  18.     {   
  19.         $cmd = popen("ps -ef | grep \"/opt/zhangyan.sh\" | grep -v grep | wc -l""r");   
  20.         $line = fread($cmd, 512);   
  21.         pclose($cmd);   
  22.         $p_number = $limit - $line;   
  23.         if ($p_number <= 0)   
  24.         {   
  25.             sleep(1);//暂停1秒钟   
  26.         }   
  27.     }   
  28.     return $p_number;   
  29. }   
  30.   
  31. $input = "http://blog.s135.com"; //模拟从队列文件中读取到的数据   
  32. for ($i = 1; $i <= 1000; $i++)   
  33. {   
  34.     run($input);   
  35.     echo "Idle process number: " . $p_number . "\n";   
  36. }   
  37. ?>  
  (/opt/zhangyan.php程序用来模拟从队列文件中读取1000行数据,交给子进程/opt/zhangyan.sh去处理。)



/opt/zhangyan.sh代码如下:
  1. #!/bin/sh   
  2. echo $(date -d "today" +"%Y-%m-%d %H:%M:%S"$1 >> /opt/zhangyan.log   
  3. sleep_time=$(expr $RANDOM % 4 + 1)   
  4. sleep $sleep_time  
  (/opt/zhangyan.sh脚本用来模拟向外地接收服务器发送数据。其中的$(expr $RANDOM % 4 + 1)用来生成1~5之间的随机数,用来使程序暂停1~5秒钟。暂停1秒表示网络状况好,发送数据顺畅;暂停2~6秒表示网络状况不好,发送过程需要1~5秒。)



 执行程序:
/usr/local/php/bin/php /opt/zhangyan.php

 (/usr/local/php/bin/php因PHP解析器所在的路径)

 查看/opt/zhangyan.sh打下的日志文件的第一行和最后一行:
head -n 1 /opt/zhangyan.log
 2007-11-16 07:54:13 http://blog.s135.com
tail -n 1 /opt/zhangyan.log
 2007-11-16 07:54:18 http://blog.s135.com

  可以看出,500进程并发处理这1000条数据只耗费5秒钟。而按照原来的串行模式,处理每条数据即使只耗费最短的1秒钟,也需要1000秒,约合16分钟才能完成。



 PS:将PHP程序作为Linux守护进程的方法:
nohup /usr/local/php/bin/php /opt/zhangyan.php 2>&1 > /dev/null &

 (nohup命令可以在用户退出终端后仍然执行程序,“2>&1 > /dev/null”表示不显示标准输出和错误输出,最后的&表示推到后台执行。)
posted @ 2009-03-02 18:03 小马歌 阅读(210) | 评论 (0)编辑 收藏
 

1.删除0字节文件
find -type f -size 0 -exec rm -rf {} \;

2.查看进程
按内存从大到小排列
ps -e   -o "%C   : %p : %z : %a"|sort -k5 -nr

3.按cpu利用率从大到小排列
ps -e   -o "%C   : %p : %z : %a"|sort   -nr

4.打印说cache里的URL
grep -r -a   jpg /data/cache/* | strings | grep "http:" | awk -F'http:' '{print "http:"$2;}'

5.查看http的并发请求数及其TCP连接状态
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'


6. sed -i '/Root/s/no/yes/' /etc/ssh/sshd_config   sed在这个文里Root的一行,匹配Root一行,将no替换成yes.

7.1.如何杀掉mysql进程:
ps aux|grep mysql|grep -v grep|awk '{print $2}'|xargs kill -9 (从中了解到awk的用途)

killall -TERM mysqld

kill -9 `cat /usr/local/apache2/logs/httpd.pid`   试试查杀进程PID



8.显示运行3级别开启的服务:
ls /etc/rc3.d/S* |cut -c 15-   (从中了解到cut的用途,截取数据)

9.如何在编写SHELL显示多个信息,用EOF
cat << EOF
+--------------------------------------------------------------+
|       === Welcome to Tunoff services ===                |
+--------------------------------------------------------------+
EOF

10. for 的巧用(如给mysql建软链接)
cd /usr/local/mysql/bin
for i in *
do ln /usr/local/mysql/bin/$i /usr/bin/$i
done

11. 取IP地址:
ifconfig eth0 |grep "inet addr:" |awk '{print $2}'|cut -c 6-   或者

ifconfig   | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'

12.内存的大小:
free -m |grep "Mem" | awk '{print $2}'


13.
netstat -an -t | grep ":80" | grep ESTABLISHED | awk '{printf "%s %s\n",$5,$6}' | sort

14.查看Apache的并发请求数及其TCP连接状态:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

15.因为同事要统计一下服务器下面所有的jpg的文件的大小,写了个shell给他来统计.原来用xargs实现,但他一次处理一部分,搞的有多个总和....,下面的命令就能解决啦.
find / -name *.jpg -exec wc -c {} \;|awk '{print $1}'|awk '{a+=$1}END{print a}'


CPU的数量(多核算多个CPU,cat /proc/cpuinfo |grep -c processor)越多,系统负载越低,每秒能处理的请求数也越多。

--------------------------------------------------------------------------------------------------------------------
16   CPU负载   # cat /proc/loadavg
检查前三个输出值是否超过了系统逻辑CPU的4倍。  

18   CPU负载   #mpstat 1 1
检查%idle是否过低(比如小于5%)

19   内存空间   # free
检查free值是否过低   也可以用 # cat /proc/meminfo

20   swap空间   # free
检查swap used值是否过高   如果swap used值过高,进一步检查swap动作是否频繁:
# vmstat 1 5
观察si和so值是否较大

21   磁盘空间   # df -h
检查是否有分区使用率(Use%)过高(比如超过90%)   如发现某个分区空间接近用尽,可以进入该分区的挂载点,用以下命令找出占用空间最多的文件或目录:
# du -cks * | sort -rn | head -n 10

22   磁盘I/O负载   # iostat -x 1 2
检查I/O使用率(%util)是否超过100%

23   网络负载   # sar -n DEV
检查网络流量(rxbyt/s, txbyt/s)是否过高

24   网络错误   # netstat -i
检查是否有网络错误(drop fifo colls carrier)   也可以用命令:# cat /proc/net/dev

25 网络连接数目   # netstat -an | grep -E “^(tcp)” | cut -c 68- | sort | uniq -c | sort -n

26   进程总数   # ps aux | wc -l
检查进程个数是否正常 (比如超过250)

27   可运行进程数目   # vmwtat 1 5
列给出的是可运行进程的数目,检查其是否超过系统逻辑CPU的4倍


28   进程   # top -id 1
观察是否有异常进程出现

29   网络状态   检查DNS, 网关等是否可以正常连通

30   用户   # who | wc -l
检查登录用户是否过多 (比如超过50个)   也可以用命令:# uptime

31   系统日志   # cat /var/log/rflogview/*errors
检查是否有异常错误记录   也可以搜寻一些异常关键字,例如:
# grep -i error /var/log/messages
# grep -i fail /var/log/messages

32   核心日志   # dmesg
检查是否有异常错误记录

33   系统时间   # date
检查系统时间是否正确

34   打开文件数目   # lsof | wc -l
检查打开文件总数是否过多

35   日志   # logwatch –print   配置/etc/log.d/logwatch.conf,将 Mailto 设置为自己的email 地址,启动mail服务 (sendmail或者postfix),这样就可以每天收到日志报告了。
缺省logwatch只报告昨天的日志,可以用# logwatch –print –range all 获得所有的日志分析结果。
可以用# logwatch –print –detail high 获得更具体的日志分析结果(而不仅仅是出错日志)。

36.杀掉80端口相关的进程
lsof -i :80|grep -v "PID"|awk '{print "kill -9",$2}'|sh

37.清除僵死进程。
ps -eal | awk '{ if ($2 == "Z") {print $4}}' | kill -9

38.tcpdump 抓包 ,用来防止80端口被人攻击时可以分析数据
# tcpdump -c 10000 -i eth0 -n dst port 80 > /root/pkts

39.然后检查IP的重复数 并从小到大排序 注意 "-t\ +0"   中间是两个空格
# less pkts | awk {'printf $3"\n"'} | cut -d. -f 1-4 | sort | uniq -c | awk {'printf $1" "$2"\n"'} | sort -n -t\ +0

40.查看有多少个活动的php-cgi进程
netstat -anp | grep php-cgi | grep ^tcp | wc -l

chkconfig --list | awk '{if ($5=="3:on") print $1}'
41.kudzu查看网卡型号
kudzu --probe --class=network
posted @ 2009-03-02 18:02 小马歌 阅读(294) | 评论 (0)编辑 收藏
 

curl是一个利用URL语法在命令行方式下工作的文件传输工具。本文介绍了它的简单用法。 ************************************************************************************

curl是一个利用URL语法在命令行方式下工作的文件传输工具。 它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。 curl同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务器, cookies, 用户名/密码认证, 下载文件断点续传, 上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器, 通过http代理服务器上传文件到FTP服务器等等,功能十分强大。 Windows操作系统下的网络蚂蚁,网际快车(FlashGet)的功能它都可以做到。准确的说,curl支持文件的上传和下载,所以是一个综合传输工具,但是按照传统,用户习惯称curl为下载工具。 curl是瑞典curl组织开发的,您可以访问: http://curl.haxx.se/ 获取它的源代码和相关说明。 鉴于curl在Linux上的广泛使用,IBM在AIX Linux Toolbox的光盘中包含了这个软件,并且您可以访问IBM网站: http://www- 1.ibm.com/servers/aix/products/aixos/linux/altlic.html     下载它。 curl的最新版本是 7.18.0,IBM网站上提供的版本为7.9.3。 在AIX下的安装很简单,IBM网站上下载的rpm格式的包。 在 http://curl.haxx.se/docs/ ,您可以下载到UNIX格式的man帮助,里面有详细的curl工具的使用说明。 curl的用法为:curl [options] [URL...] 其中options是下载需要的参数,大约有80多个,curl的各个功能完全是依靠这些参数完成的。具体参数的使用,用户可以参考curl的man帮助。下面,本文就将结合具体的例子来说明怎样利用curl进行下载。

1、获得一张页面
使用命令:curl http://curl.haxx.se 这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将不显示文件头部,即HTML文档的header。要全部显示,请加参数 -i,要只显示头部,用参数 -I。任何时候,可以使用 -v 命令看curl是怎样工作的,它向服务器发送的所有命令都会显示出来。为了断点续传,可以使用-r参数来指定传输范围。
2、表单(Form)的获取
在WEB页面设计中,form是很重要的元素。Form通常用来收集并向网站提交信息。提交信息的方法有两种,GET方法和POST方法。先讨论GET方法,例如在页面中有这样一段: <form method="GET" action="junk.cgi"> <input type=text name="birthyear"> <input type=submit name=press value="OK"> </form> 那么浏览器上会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单就用GET方法向服务器提交文本框的数据。例如原始页面是在 www.hotmail.com/when/birth.html看到的,然后您在文本框中输入1905,然后按OK按钮,那么浏览器的URL现在应该是:“www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK” 对于这种网页,curl可以直接处理,例如想获取上面的网页,只要输入: curl "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK" 就可以了。 表单用来提交信息的第二种方法叫做POST方法,POST方法和GET方法的区别在于GET方法使用的时候,浏览器中会产生目标URL,而POST不会。类似GET,这里有一个网页: <form method="POST" action="junk.cgi"> <input type=text name="birthyear"> <input type=submit name=press value="OK"> </form> 浏览器上也会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单用POST方法向服务器提交数据。 这时的URL是看不到的,因此需要使用特殊的方法来抓取这个页面: curl -d "birthyear=1905&press=OK" www.hotmail.com/when/junk.cgi 这个命令就可以做到。 1995年年末,RFC 1867定义了一种新的POST方法,用来上传文件。主要用于把本地文件上传到服务器。此时页面是这样写的: <form method="POST" enctype='multipart/form-data' action="upload.cgi"> <input type=file name=upload> <input type=submit name=press value="OK"> </form> 对于这种页面,curl的用法不同: curl -F upload=@localfilename -F press=OK URL 这个命令的实质是将本地的文件用POST上传到服务器。有关POST还有不少用法,用户可以自己摸索。
3、使用PUT方法。
HTTP协议文件上传的标准方法是使用PUT,此时curl命令使用-T参数: curl -T uploadfile www.uploadhttp.com/receive.cgi
4、有关认证。
curl可以处理各种情况的认证页面,例如下载用户名/密码认证方式的页面(在IE中通常是出现一个输入用户名和密码的输入框): curl -u name:password www.secrets.com 如果网络是通过http代理服务器出去的,而代理服务器需要用户名和密码,那么输入: curl -U proxyuser:proxypassword http://curl.haxx.se 任何需要输入用户名和密码的时候,只在参数中指定用户名而空着密码,curl可以交互式的让用户输入密码。
5、引用。
有些网络资源访问的时候必须经过另外一个网络地址跳转过去,这用术语来说是:referer,引用。对于这种地址的资源,curl也可以下载: curl -e http://curl.haxx.se daniel.haxx.se
6、指定用户客户端。
有些网络资源首先需要判断用户使用的是什么浏览器,符合标准了才能够下载或者浏览。此时curl可以把自己“伪装”成任何其他浏览器: curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" URL 这个指令表示curl伪装成了IE5.0,用户平台是Windows 2000。(对方服务器是根据这个字串来判断客户端的类型的,所以即使使用AIX也无所谓)。使用: curl -A "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" URL 此时curl变成了Netscape,运行在PIII平台的Linux上了。
7、COOKIES
Cookie是服务器经常使用的一种记忆客户信息的方法。如果cookie被记录在了文件中,那么使用命令: curl -b stored_cookies_in_file www.cookiesite.com curl可以根据旧的cookie写出新cookie并发送到网站: curl -b cookies.txt -c newcookies.txt www.cookiesite.com
8、加密的HTTP——HTTPS。
如果是通过OpenSSL加密的https协议传输的网页,curl可以直接访问: curl https://that.secure.server.com
9、http认证。
如果是采用证书认证的http地址,证书在本地,那么curl这样使用: curl -E mycert.pem https://that.secure.server.com
参考读物和注意事项:
curl非常博大,用户要想使用好这个工具,除了详细学习参数之外,还需要深刻理解http的各种协议与URL的各个语法。这里推荐几个读物: RFC 2616 HTTP协议语法的定义。 RFC 2396 URL语法的定义。 RFC 2109 Cookie是怎样工作的。 RFC 1867 HTTP如何POST,以及POST的格式。

这东西现在已经是苹果机上内置的命令行工具之一了,可见其魅力之一斑!

1)二话不说,先从这里开始吧!

curl http://www.yahoo.com

回车之后,www.yahoo.com 的html就稀里哗啦地显示在屏幕上了~~~~~

2)嗯,要想把读过来页面存下来,是不是要这样呢?
curl http://www.yahoo.com > page.html

当然可以,但不用这么麻烦的!
用curl的内置option就好,存下http的结果,用这个option: -o
curl -o page.html http://www.yahoo.com

这样,你就可以看到屏幕上出现一个下载页面进度指示。等进展到100%,自然就OK咯

3)什么什么?!访问不到?肯定是你的proxy没有设定了。
使用curl的时候,用这个option可以指定http访问所使用的proxy服务器及其端口: -x
curl -x 123.45.67.89:1080 -o page.html http://www.yahoo.com

4)访问有些网站的时候比较讨厌,他使用cookie来记录session信息。
像IE/NN这样的浏览器,当然可以轻易处理cookie信息,但我们的curl呢?..
我们来学习这个option: -D <– 这个是把http的response里面的cookie信息存到一个特别的文件中去
curl -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com

这样,当页面被存到page.html的同时,cookie信息也被存到了cookie0001.txt里面了

5)那么,下一次访问的时候,如何继续使用上次留下的cookie信息呢?要知道,很多网站都是靠监视你的cookie信息,来判断你是不是不按规矩访问他们的网站的。
这次我们使用这个option来把上次的cookie信息追加到http request里面去: -b
curl -x 123.45.67.89:1080 -o page1.html -D cookie0002.txt -b cookie0001.txt http://www.yahoo.com

这样,我们就可以几乎模拟所有的IE操作,去访问网页了!

6)稍微等等~~~~~我好像忘记什么了~~~~~
对了!是浏览器信息~~~~

有些讨厌的网站总要我们使用某些特定的浏览器去访问他们,有时候更过分的是,还要使用某些特定的版本~~~~
NND,哪里有时间为了它去找这些怪异的浏览器呢!?

好在curl给我们提供了一个有用的option,可以让我们随意指定自己这次访问所宣称的自己的浏览器信息: -A
curl -A “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)” -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com

这样,服务器端接到访问的要求,会认为你是一个运行在Windows 2000上的IE6.0,嘿嘿嘿,其实也许你用的是苹果机呢!

而”Mozilla/4.73 [en] (X11; U; Linux 2.2; 15 i686″则可以告诉对方你是一台PC上跑着的Linux,用的是Netscape 4.73,呵呵呵

7)另外一个服务器端常用的限制方法,就是检查http访问的referer。比如你先访问首页,再访问里面所指定的下载页,这第二次访问的referer地址就是第一次访问成功后的页面地址。这样,服务器端只要发现对下载页面某次访问的referer地址不 是首页的地址,就可以断定那是个盗连了~~~~~

讨厌讨厌~~~我就是要盗连~~~~~!!
幸好curl给我们提供了设定referer的option: -e
curl -A “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)” -x 123.45.67.89:1080 -e “mail.yahoo.com” -o page.html -D cookie0001.txt http://www.yahoo.com

这样,就可以骗对方的服务器,你是从mail.yahoo.com点击某个链接过来的了,呵呵呵

8)写着写着发现漏掉什么重要的东西了!—– 利用curl 下载文件

刚才讲过了,下载页面到一个文件里,可以使用 -o ,下载文件也是一样。
比如, curl -o 1.jpg
这里教大家一个新的option: -O
大写的O,这么用: curl -O
这样,就可以按照服务器上的文件名,自动存在本地了!

再来一个更好用的。
如果screen1.JPG以外还有screen2.JPG、screen3.JPG、.、screen10.JPG需要下载,难不成还要让我们写一个script来完成这些操作?
不干!
在curl里面,这么写就可以了:
curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen[1-10].JPG

呵呵呵,厉害吧?!~~~

9)再来,我们继续讲解下载!
curl -O http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG

这样产生的下载,就是
~zzh/001.JPG
~zzh/002.JPG

~zzh/201.JPG
~nick/001.JPG
~nick/002.JPG

~nick/201.JPG

够方便的了吧?哈哈哈

咦?高兴得太早了。
由于zzh/nick下的文件名都是001,002,201,下载下来的文件重名,后面的把前面的文件都给覆盖掉了~~~

没关系,我们还有更狠的!
curl -o #2_#1.jpg http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG

–这是..自定义文件名的下载?
–对头,呵呵!

#1是变量,指的是{zzh,nick}这部分,第一次取值zzh,第二次取值nick
#2代表的变量,则是第二段可变部分—[001-201],取值从001逐一加到201
这样,自定义出来下载下来的文件名,就变成了这样:
原来: ~zzh/001.JPG —> 下载后: 001-zzh.JPG
原来: ~nick/001.JPG —> 下载后: 001-nick.JPG

这样一来,就不怕文件重名啦,呵呵

继续讲下载
我们平时在windows平台上,flashget这样的工具可以帮我们分块并行下载,还可以断线续传。
curl在这些方面也不输给谁,嘿嘿

比如我们下载screen1.JPG中,突然掉线了,我们就可以这样开始续传
curl -c -O

当然,你不要拿个flashget下载了一半的文件来糊弄我~~~~别的下载软件的半截文件可不一定能用哦~~~

分块下载,我们使用这个option就可以了: -r

举例说明
比如我们有一个 http://cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 要下载(赵老师的电话朗诵)

我们就可以用这样的命令:
curl -r 0-10240 -o “zhao.part1″ http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &
curl -r 10241-20480 -o “zhao.part1″ http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &
curl -r 20481-40960 -o “zhao.part1″ http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &
curl -r 40961- -o “zhao.part1″ http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3

这样就可以分块下载啦。
不过你需要自己把这些破碎的文件合并起来
如果你用UNIX或苹果,用 cat zhao.part* > zhao.mp3就可以
如果用的是Windows,用copy /b 来解决吧,呵呵

上面讲的都是http协议的下载,其实ftp也一样可以用。
用法嘛,
curl -u name:passwd ftp://ip:port/path/file
或者大家熟悉的
curl ftp://name:passwd@ip/path/file

10)说完了下载,接下来自然该讲上传咯
上传的option是 -T

比如我们向ftp传一个文件: curl -T localfile -u name:passwd ftp://upload_site/path/

当然,向http服务器上传文件也可以
比如 curl -T localfile http://cgi2.tky.3web.ne.jp/~zzh/abc.cgi
注意,这时候,使用的协议是HTTP的PUT method

刚才说到PUT,嘿嘿,自然让老服想起来了其他几种methos还没讲呢!
GET和POST都不能忘哦。

http提交一个表单,比较常用的是POST模式和GET模式

GET模式什么option都不用,只需要把变量写在url里面就可以了
比如:
curl http://www.yahoo.com/login.cgi?user&password=12345

而POST模式的option则是 -d

比如,curl -d “user=nickwolfe&password=12345″ http://www.yahoo.com/login.cgi
就相当于向这个站点发出一次登陆申请~~~~~

到底该用GET模式还是POST模式,要看对面服务器的程序设定。

一点需要注意的是,POST模式下的文件上的文件上传,比如

<input type=”file” name=”upload”><input type=”submit” name=”nick” value=”go”>

这样一个HTTP表单,我们要用curl进行模拟,就该是这样的语法:
curl -F upload=@localfile -F nick=go http://cgi2.tky.3web.ne.jp/~zzh/up_file.cgi

罗罗嗦嗦讲了这么多,其实curl还有很多很多技巧和用法
比如 https的时候使用本地证书,就可以这样
curl -E localcert.pem https://remote_server

再比如,你还可以用curl通过dict协议去查字典~~~~~
curl dict://dict.org/d:computer

posted @ 2009-03-02 18:01 小马歌 阅读(322) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 70 71 72 73 74 75 76 77 78 下一页 Last