背景:防止盗链,大多数能搞定,但防止抓取有些困难。curl 模拟浏览器头和refer及Curl模仿http浏览器常见命令:http://www.jackxiang.com/post/6641/

.htaccess
DirectoryIndex search.php
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^$ [NC]
RewriteCond %{HTTP_REFERER} !^http://你的网站IP  [NC,OR]
RewriteRule ^search_result.php search.php


如果HTTP_REFERER为空或者与指定的网站IP不匹配。访问search_result.php时跳到search.php.
[NC] ,[OR]这个我也不太懂。望高手指点下。

摘自:http://yulei568.blog.163.com/blog/static/135886720084231390136/
更多相关:http://www.jb51.net/os/RedHat/1060.html
通过查看Nginx的并发连接,我们可以更清除的知道网站的负载情况。Nginx并发查看有两种方法(之所以这么说,是因为笔者只知道两种),一种是通过 web界面,一种是通过命令,web查看要比命令查看显示的结果精确一些。下面介绍这两种查看方法

No1、通过浏览器查看
    通过web界面查看时Nginx需要开启status模块,也就是安装Nginx时加上        --with-http_stub_status_module   然后配置Nginx.conf,在server点里面加入如下内容


  配置完后重新启动Nginx后我们可以通过浏览器访问http://localhost/status 查看。
点击在新窗口中浏览此图片
解析:
Active connections    //当前 Nginx 正处理的活动连接数。
server accepts handled requests //总共处理了8 个连接 , 成功创建 8 次握手,总共处理了500个请求。
Reading //nginx 读取到客户端的 Header 信息数。
Writing //nginx 返回给客户端的 Header 信息数。
Waiting //开启 keep-alive 的情况下,这个值等于 active - (reading + writing),意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接
No2、通过命令查看
#netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 17
ESTABLISHED 3254
LAST_ACK 236
FIN_WAIT_1 648
FIN_WAIT_2 581
CLOSING 7
CLOSE_WAIT 4916

解析:
CLOSED  //无连接是活动的或正在进行
LISTEN  //服务器在等待进入呼叫
SYN_RECV  //一个连接请求已经到达,等待确认
SYN_SENT  //应用已经开始,打开一个连接
ESTABLISHED  //正常数据传输状态/当前并发连接数
FIN_WAIT1  //应用说它已经完成
FIN_WAIT2  //另一边已同意释放
ITMED_WAIT  //等待所有分组死掉
CLOSING  //两边同时尝试关闭
TIME_WAIT  //另一边已初始化一个释放
LAST_ACK  //等待所有分组死掉


============================================================
来自:http://blog.s135.com/nginx_php_v5/

实践:
[root@localhost 20131212]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 109
ESTABLISHED 63
SYN_RECV 103
LAST_ACK 2
原理讲解和图示:Nginx基于TCP的四层负载均衡介绍
Nginx Plus的商业授权版开始具有TCP负载均衡的功能。从Nginx 1.7.7版本开始加入的,现在变成了一个商业收费版本,想要试用,需要在官网申请。也就是说,Nginx除了以前常用的HTTP负载均衡外,Nginx增加基于TCP协议实现的负载均衡方法。

HTTP负载均衡,也就是我们通常所有“七层负载均衡”,工作在第七层“应用层”。而TCP负载均衡,就是我们通常所说的“四层负载均衡”,工作在“网络层”和“传输层”。例如,LVS(Linux Virtual Server,Linux虚拟服务)和F5(一种硬件负载均衡设备),也是属于“四层负载均衡”。
......OSI模型里tcp/ip 是4层,而到应用层则是七层了......相关学习:http://jackxiang.com/post/6280/


阅读全文

阅读全文
七夜兄弟的fastcgi blog增强版:
http://bbs.phpchina.com/forum.php?mod=viewthread&tid=200687
了解:
1)升级使用sqlite3的fts3扩展,进行全文检索
2)使用rmmseg进行中文分词
3)  drupal文件上传

这个哥们的邮箱:sunjianfei@xiaomi.com
http://bbs.phpchina.com/forum.php?mod=viewthread&tid=249829
http://bbs.phpchina.com/forum.php?mod=viewthread&tid=249829
————————————————————————————————
找这个哥们他从邮箱里回了一个做好的,我没看明白当时为嘛选这些,问了下七夜:Add Time:2014-08-20
1)升级使用sqlite3的fts3扩展,进行全文检索
2)使用rmmseg进行中文分词
3)  drupal文件上传
这玩意都是啥,像1) mysql都能直接直持吧?
像二mysql好像也有插件是吧?
像上传为嘛要用drupal来增强呢?
+————————+
有啥考量没?
七夜
14/8/20 星期三 上午 11:07:01
用nginx的上传就行   //是一个Nginx专用的上传模块,https://jackxiang.com/post/6221/ 有介绍。
回忆未来-向东-Jàck 14/8/20 星期三 上午 11:09:01
七夜兄弟说的是那个nginx一个上传插件吧?nginx_upload_module

七夜
14/8/20 星期三 上午 11:09:00
恩是的。nginx模块
上午 11:09:23
回忆未来-向东-Jàck 14/8/20 星期三 上午 11:09:23
我都想用c写一个专门的上传了,啊哈哈。
七夜
14/8/20 星期三 上午 11:09:43
不用。都有现成的

回忆未来-向东-Jàck 14/8/20 星期三 上午 11:10:17
写了一半写不下去了,c功力不够,对那个上传大文件是先放内存还是直接写文件这块涉及到缓存处理上好像有点纠结。
七夜
写磁盘。内存缓存部分
七夜
14/8/20 星期三 上午 11:13:11
写磁盘。内存缓存部分
————————
那是从内存一下写入磁盘,还是要有一个进程来看哪个文件内存放得多就先写呢?

啥也不会
14/8/20 星期三 上午 11:15:07
mmap啊 别的交给系统好了



SQLite的FTS3扩展

FTS3允许用户创建一个全文索引的特殊表,

CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT);     /* FTS3 table */
CREATE TABLE enrondata2(content TEXT);                        /* Ordinary table */
使用FTS3效率特别快

SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux';  /* 0.03 seconds */
SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */
http://www.cnblogs.com/abob/archive/2010/12/01/1893425.html

2)使用rmmseg进行中文分词:
C语言开源高性能中文分词组件,C语言mmseg中文分词器 《狮子的魂》:https://code.google.com/p/friso/

3) drupal文件上传:http://blog.sina.com.cn/s/blog_a94fd80d01017tkx.html

FastCGI Blog 2.0版本正在开发中,新的版本,将是代码级别的优化,还有一些功能的增强
1. 使用了内存池,提高申请小内存的效率.一个请求一个内存池.这样杜绝了内存泄漏。
2. 自己编写了hashmap、list等实现,减少对第三方lib的依赖
3. 使用配置文件,修改相关配置更加方便
4. 使用功能更为强大的html编辑器,增加后台文件上传功能
5. 代码高亮显示
6. 文章的全文搜索功能.(有时间的话,实现该功能)
http://bbs.chinaunix.net/thread-1790317-3-1.html
C FastCGI Blog 零痛苦一键安装包
自从上次发布了我用写C写的 FastCGI Blog,很多人都说安装不太方便,所以我做了个一键安装包,大家可以零痛苦体验
解开压缩包,执行
./install.sh "/root/local"
/root/local
是安装目录


Nginx转发 spawn-fcgi看护
欢迎测试,欢迎加入

七夜开发
的博客基础上进行升级:
1)升级为g++编译,方便整合c++库
2)升级使用sqlite3的fts3扩展,进行全文检索
3)使用rmmseg进行中文分词
目前正在更新:
1)  整理
代码
结构,提供方便的二次开发接口和说明文档
2)添加
文件
上传,实现drupal文件上传的
用户
体验
3)后台
模板
管理
代码还在完善中,请静侯
————————————————————————————————

所有的软件包下载List:
http://code.google.com/p/php-tokyocabinet/downloads/list

C实现的FastCGI Blog:
http://www.fengblog.org/archives/200/

http://blog.sina.com.cn/s/blog_7041f8eb0100nkxe.html
下载完整版的地址:
http://www.pudn.com/downloads426/sourcecode/windows/network/detail1804143.html

七夜博客系统 FastCGI Blog 2.0,自从C-blog1.0发布以来,很多人给了很中肯的意见。这段有时间了,赶紧的把一些大家都需要的功能给开发出来。现在推出c-blog2.0版本.在这个版本里,还没实现全文搜索.在2.1版里会实现全文搜索功能。
这次升级的功能列表:
1. 引入了 配置文件
2. 增加cookie 解析,和文件上传功能
3. html编辑器,换了 更为强大的KindEditor编辑器
4. 支持代码高亮
5. 使用了内存池.统一分配 统一释放,程序更安全
6. 更清晰的 程序目录分类.
(1) db 为 数据库目录
(2) log 为 日志目录
(3) src 为 c-blog源文件目录
(4) htdocs 为 www访问目录.nginx 指到这个目录就行
7. 使用 configure make make install 方式 安装.更为简单

一直想有个自己的blog,就是犯懒不肯code,最近对自己下了狠劲。利用一两个月业余时间完成了这个blog,我还是很有成就感的。哈哈哈。这个blog程序,这几天刚完成。有bug在所难免,欢迎大家提出来,我会不断的维护的。下面我罗列一下这个blog的功能

这个blog采用html template技术, 模板修改起来就跟php的模板一样简单

后台功能
1. 分类管理、添加、删除、编辑(只支持一级分类)
2. 文章管理、添加、删除、编辑
3. 生成静态首页、清除全部静态页缓存
4. 友情链接管理、添加、删除、编辑
5. 评论列表、删除
6. 简单的用户登录和退出
========================================================================================
这个blog 依赖这些 lib
1. FastCGI  http://www.fastcgi.com/dist/
2. tokyocabinet  http://fallabs.com/tokyocabinet/
DownLoad:http://fallabs.com/kyotocabinet/pkg/
http://fallabs.com/tokyocabinet/pastpkg/tokyocabinet-1.3.27.tar.gz

3. SQLite3 http://www.sqlite.org/download.html
4. jemalloc http://www.canonware.com/download/jemalloc/

下载上述软件,并编译安装.
blog的编译命令是(相关lib路径,根据自己的改,)
gcc -o blog blog.c util.c tpllib.c rbtree.c assign.c ./module/bl



(gdb) set env module=user
(gdb) run
Starting program: /usr/local/htdocs/cblog
[Thread debugging using libthread_db enabled]
[New Thread 0xb7ff0b70 (LWP 5952)]
Location:/
输出:
./src/blog.c:                   puts("Location:/\r\n\r\n")


/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -f /usr/local/htdocs/cblog -s /tmp/fcgi-blog.sock


http://blogtest.com/article-read-opensource-15-c-fastcgi-blog-2.0.html
这个是用cgi生成的网页么?怎么访问这个cgi啊?

七夜  下午 02:47:19
article-read-opensource-15-c-fastcgi-blog-2.0.html
article 是访问article 模块
read  是访问article 模块 中的函数
opensource  是分类名
15 是 id
后面 的 都是 seo
url seo
回忆未来-向东-Jàck  下午 02:48:19
你这个有没有url的seo,这个得自己编写?
这个url的seo是不是写在nginx里的?当时。


等会
/panel-user-login.html

后台登录链接的Url及帐号名密码如下:
http://blogtest.com/panel-user-login.html
http://blogtest2.com/panel-user-login.html
用户名:七夜
密码:vilinux


tail -f   /data1/logs/access.log
tail -f /data1/logs/nginx_error.log
回忆未来-向东-Jàck  下午 03:09:22
192.168.137.1 - - [03/Jul/2013:15:09:11 +0800] "GET /panel-user-login.html HTTP/1.1" 502 383 "-" "Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0"

七夜  下午 03:09:40
看看error
errlor.log
回忆未来-向东-Jàck  下午 03:10:24
2013/07/03 15:10:14 [crit] 2799#0: *3 connect() to unix:/tmp/fcgi-blog.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.137.1, server: blogtest.com, request: "GET /panel-user-login.html HTTP/1.1", upstream: "fastcgi://unix:/tmp/fcgi-blog.sock:", host: "blogtest.com"


回忆未来-向东-Jàck  下午 03:10:24
2013/07/03 15:10:14 [crit] 2799#0: *3 connect() to unix:/tmp/fcgi-blog.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.137.1, server: blogtest.com, request: "GET /panel-user-login.html HTTP/1.1", upstream: "fastcgi://unix:/tmp/fcgi-blog.sock:", host: "blogtest.com"
七夜  下午 03:11:10
chmod 777
没权限
回忆未来-向东-Jàck  下午 03:11:40
chmod -R 777 /tmp/fcgi-blog.sock  
是吧?

可以了,修改了下nginx的配置,如下可以,访问,不知密码是多少:
http://blogtest.com/panel-user-login.html


Ok的Nginx配置如下:


说明通过tail看nginx的日志多么重要:
tail -f /data1/logs/nginx_error.log /data1/logs/access.log

The page you are looking for is temporarily unavailable.
Please try again later.
查看Nginx错误日志:
tail -f /data1/logs/nginx_error.log /data1/logs/access.log
==> /data1/logs/nginx_error.log <==
2013/07/03 18:17:50 [crit] 3728#0: *98 connect() to unix:/tmp/fcgi-blog.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.137.1, server: blogtest.com, request: "GET /panel-user-login.html HTTP/1.1", upstream: "fastcgi://unix:/tmp/fcgi-blog.sock:", host: "blogtest.com"

==> /data1/logs/access.log <==
192.168.137.1 - - [03/Jul/2013:18:17:50 +0800] "GET /panel-user-login.html HTTP/1.1" 502 383 "-" "Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0"



ulimit -c unlimited
./cblog //产生core文件,core.5273
gdb cblog core.5273
----------------------------------
Core was generated by `./cblog'.
Program terminated with signal 11, Segmentation fault.
#0  0x00cab5e7 in tcmapput () from /usr/local/lib/libtokyocabinet.so.7
--------------------------------------------------------------------------------------------------
七夜  下午 05:21:33
不行,你不能这么gdb的
你 log 输出一下
就能知道了

====================================================================================
一)启动fastcgi:
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -f /usr/local/htdocs/cblog -s /tmp/fcgi-blog.sock
spawn-fcgi: child spawned successfully: PID: 2251
chmod -R 777 /tmp/fcgi-blog.sock

二)进去后出现:
./templets/panel/category_update.html Error loading template file!

三)调试方法:
root@192.168.137.128:/usr/local/conf# strace -p 2251
Process 2251 attached - interrupt to quit
accept(0, {sa_family=AF_FILE, NULL}, [2]) = 5
select(6, [5], NULL, NULL, {2, 0})      = 1 (in [5], left {1, 999996})
read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\4\1\7\0\f\0QUERY_"..., 8192) = 1072
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77a0000
open("./templets/panel/category_insert.html", O_RDONLY) = -1 ENOENT (No such file or directory)
munmap(0xb77a0000, 4096)  


=====================================================================================
没法读到模板的问题如下解决办法:
-------------------------------------------------------
七夜兄弟:
open("./templets/blog/article_list.html", O_RDONLY) = -1 ENOENT (No such file or directory)

./module/panel/article.c:       if (tpl_load(tpl,"./templets/blog/article_list.html") != TPL_OK)

打开文件编译后,这个模板文件是相对于fastcgi这个程序是从哪儿开始算机的啊?
编译文件打开的模板文件你写的是相对路径,这个相对路径是相对的根目录是?

七夜  上午 11:13:12
/usr/local/htdocs/
你得在这个目录,你试试我的方法.
cd  /usr/local/htdocs/
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -f ./cblog -s /tmp/fcgi-blog.sock
spawn-fcgi: child spawned successfully: PID: 3639



这个sqllite备份怎么备份,
这玩意一个文件容易一出问题,整个文件里数据就挂了吧?
稳定性怎么样、如果真用sqlite的话。有没有办法提高其数据的安全这方面的经验。
七夜  上午 11:27:12
stop fastcgi. after copy sqlite3 db file to other path
安全,已经不在发布目录
所以不用担心会被浏览器下载什么的
七夜  上午 11:29:24
可能会有些小bug。大问题没有。我运行了一年
回忆未来-向东-Jàck  上午 11:30:13
像nginx下的php一样起多个。可以么?
七夜  上午 11:30:23
目前还不可以
回忆未来-向东-Jàck  上午 11:31:07
我看好像有个fastcgi命令可以起一个端口起来,有个参数是多少个进程的啊。
==========================================================
关于多个进程现在只有一个,可以再学习下。
下面关于后台的功能特别是那个缓存:
回忆未来-向东-Jàck  上午 11:32:26
这添加文章太快了,这种快感不错,比我在外面的博客快了进10倍,
这用户体验好啊。
清楚全部缓存
这个是什么意思,缓存在哪儿的?
七夜  上午 11:33:00
我会生成静态页的
列表页 首页 文章页
都会生成的静态页的
回忆未来-向东-Jàck  上午 11:33:20
生成首页
不就是么?
是自动生成的么,其他的静态页面。
首页要自己生成是吧?
七夜  上午 11:33:46
列表页 文章页 是自动生成的
访问生成的
回忆未来-向东-Jàck  上午 11:34:53
哈哈,好的,我有空再看下代码,学习一下,灰常感谢。


回忆未来-向东-Jàck  上午 11:36:34
tokyocabinet  jemalloc 用在这儿是干嘛的?
好像是内存分配的是吧?这个jemalloc。它有什么好处?
这个tokyocabinet  是个什么玩意?是缓存吗。
七夜  上午 11:38:43
jemalloc 优化的 内存管理器
tokyocabinet 有现成的 map list封装
回忆未来-向东-Jàck  上午 11:39:30
这样就不容易内存泄漏和数据结构上也带来了处理方便是吧?我也学学。
七夜  上午 11:41:45
不是,jemalloc 主要是代替 libc的malloc 和free
内存泄漏  还是自己去管理

回忆未来-向东-Jàck  上午 11:42:09
仅仅是设想下像这种单个的fastcg进程i能支持并发多少 有没有过测试或估计哩?
七夜  上午 11:42:16
你可以压测一下

问下scottjiang兄弟这块的实践经验:
fastcgi只起一个进程,大概能支持并发多少啊?scottjiang兄弟。
location ~ \.html$ {                        
    root           /usr/local/htdocs;        
    fastcgi_pass   unix:/tmp/fcgi-blog.sock;
    fastcgi_index  cblog;                    
    include        fastcgi_params;          
}
有没有经验值啊?我想了解下这块。再就是怎么把这一个进程变多个啊。
江庆海  上午 11:50:24
可以在apache中配置最大进程数。根据你的业务请求量,一般配几十吧。
你google一下配置说明,应该有可以启动进程数,每个进程数处理最大并发个数、超时等配置。
nginx 不太熟啊,应该也是有的。

================================================
多个进程的参考方法如下:
1. nginx安装(略过)
2. FastCGI安装
因为nginx不能直接执行外部的cgi程序,我们可使用lighttpd中的spawn-fastcgi来让nginx可支持外部cgi运行。也有另外一种方法安装nginx-fcgi来让nginx支持cgi,我们这里讲解一种使用spawn-fastcgi的方法。
#include <iostream>
#include <fcgi_stdio.h>
#include <stdlib.h>
int main()
{
int count = 0;
while(FCGI_Accept() >= 0){
printf("Content-type: text/html\r\n"
"\r\n"
""
"FastCGI Hello!"
"Request number %d running on host%s "
"Process ID: %d\n", ++count, getenv("SERVER_NAME"), getpid());
}
return 0;
}
编译程序:g++ testcgi.c -o lzgFastCGI  -lfcgi
测试程序是否能正常运行:./myFastCGI,如果能正常运行则说明程序没有问题,如果出现缺少库libfcgi.so.0,则自己需要手动把/usr/local/lib/libfcgi.so.0库建立一个链接到/usr/lib/目录下:ln -s /usr/local/libfcgi.so.0 /usr/lib/
3. nginx配置、测试
1) 拷贝lzgFastCGI程序到nginx下的cgibin目录(自己可以创建,根据需要更改)
2) 启动spawn-fastcgi管理进程
/usr/local/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25 -f /usr/local/nginx/cgibin/lzgFastCGI
查看一下9002端口是否已成功:netstat -na | grep 9002
3) 更改nginx.conf配置文件

添加配置
location ~ \.cgi$ {
  fastcgi_pass 127.0.0.1:9002;
  fastcgi_index index.cgi;
  fastcgi_param SCRIPT_FILENAME fcgi$fastcgi_script_name;
  include fastcgi_params;
}

根据上面的文章进行实践是OK的:
/usr/local/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25 -f /usr/local/nginx/cgibin/lzgFastCGI

cd /usr/local/htdocs/
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25  -f ./cblog

实践OK的,Ok步骤如下:
root@192.168.137.128:/usr/local/htdocs# /usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25  -f ./cblog
spawn-fcgi: child spawned successfully: PID: 4367
root@192.168.137.128:/usr/local/htdocs# netstat -atlunp|grep 9002
tcp        0      0 127.0.0.1:9002              0.0.0.0:*                   LISTEN      4367/./cblog

Nginx配置:
location ~ \.cgi$ {     //这儿略有区别,是html都指向这个cgi了。

适当参考即可,和实际的情况均有出入:http://blog.csdn.net/qzier_go/article/details/7340868
http://terry831010.blog.163.com/blog/static/6916117120126185428827/

http://www.ha97.com/173.html
使用spawn-fcgi来控制php-cgi的FastCGI进程:
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -u apache -g apache -f /usr/bin/php-cgi
参数含义如下:
-f <fcgiapp> 指定调用FastCGI的进程的执行程序位置,根据系统上所装的PHP的情况具体设置。
-a <addr> 绑定到地址addr。
-p <port> 绑定到端口port。
-s <path> 绑定到unix socket的路径path。
-C <childs> 指定产生的FastCGI的进程数,默认为5。(仅用于PHP)
-P <path> 指定产生的进程的PID文件路径。
-u和-g FastCGI使用什么身份(-u 用户 -g 用户组)运行,CentOS下可以使用apache用户,其他的根据情况配置,如nobody、www-data等。

实践来源:http://www.phpabc.cn/apachejie-he-spawn-fcgishi-yong-fastcgi.html
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -a 127.0.0.1 -p 9000 -C 5 -u apache -g www -f /usr/local/webserver/php/bin/php-cgi          
spawn-fcgi: child spawned successfully: PID: 7551

ps aux|grep php
apache    7551 16.7  1.6  43396  6016 ?        Ssl  15:14   0:01 /usr/local/webserver/php/bin/php-cgi
====================================================================================

Sqlite表查询相关实践:
root@192.168.137.128:/usr/local/db# sqlite3 blog.db
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
1)查看表名
sqlite> .table
article     category    comment     friendlink

2)查表内容:
sqlite> select * from category;
1|php|php|1
2|mysql|mysql|2
3|nosql|nosql|3
4|linux|linux|4
5|javascript|javascript|5
6||life|6
7||opensource|7
8|web2.0|web2.0|8

3)表结构:
sqlite> .schema category  
CREATE TABLE [category] (
[sid] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,
[sortname] VARCHAR(30)  NOT NULL,
[sortdir] VARCHAR(30)  NOT NULL,
[pos] INTEGER DEFAULT '0' NOT NULL
);
CREATE INDEX [IDX_CATEGORY_POS] ON [category](
[pos]  ASC
);

4)退出sqliite
sqlite> .exit







————————————————Add:2013-12-10启动了1000个fastcgi进程————————————————
http://www.cnblogs.com/xiaouisme/archive/2012/08/01/2618398.html
步骤如下:
(1)代码情况:heloFastCGI.c

(2)make情况:makefile.sh

(3)建立目录步骤:step.txt
mkdir -p /usr/local/webserver/nginx/myFastCGI                              
cp helloFastCGI /usr/local/webserver/nginx/myFastCGI                      
/usr/local/webserver/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 9100 -C 25 -f  
/usr/local/webserver/nginx/myFastCGI/helloFastCGI -F 1000    
              
启动:
/usr/local/webserver/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 9100 -C 25 -f /usr/local/webserver/nginx/myFastCGI/helloFastCGI -F 1000

启动后:
root@192.168.137.128:/data0/htdocs/myfastcgi# ps aux|grep helloFastCGI |wc
   1001   11012  115083
root@192.168.137.128:/data0/htdocs/myfastcgi# netstat -atlunp|grep 9100
tcp        0      0 127.0.0.1:9100              0.0.0.0:*                   LISTEN      5524/helloFastCGI  

注意这是一行命令哦。注意可能要sudo.
-p是指定fastcgi控制器绑定的TCP端口listen的.
如果你想调试单个fastcgi程序,可以把-f换成-n.
-F指定spawn-fcgi将fork多少个child进程。之后nginx对于此cgi的请求就可以并发了。显然这里的直接并发量是1000.
其他参数可以help看看:(看起来-C对不要php的我来说没啥用.本文是初次使用记录性教程,这里就不纠结这些参数了)
关闭spawn-fcgi打开的fastcgi程序:
$ netstat -anp | grep 9000 #查看占用9000端口的程序ID
$ kill -9 PID #或killall 进程名
后面这些进程启动后,怎么和nginx对接上呢,需要进行配置文件研究修改即可,文章里有说明。

                                              ...........关于配置的说明:..............
1. .ginx收到cgi请求后,会看有多少个该cgi程序的进程(spawn-fcgi -F指定的参数),然后根据并发量来调用(调度)cgi程序。
2. 原版spawn-fcgi(可参考下面七参考资料里daemon版spawn-fcgi)在fork了cgi程序后,自己就退出了。这时fork了的cgi程序的父进程ID都是1了,即init系统进程。这样,如果想并发就需要你的fastcgi去支持并发,可google:fastcgi并发
3. 关于php,nginx是用fastcgi来解析php的。这个负责解析的fastcgi程序并不多,好像就1个,因此这cgi不能大并发,但是没关系nginx支持cgi缓存~所以php网页的并发请求跟fastcgi关系不大。其实可以把fastcgi对于php的作用当作一个编译器,编译完后,php都有了缓存,再请求就不需要再次跑fastcgi来解析php脚本了,php就是个该死的脚本啊~~
我自己也不知道讲清楚没。其实我自己也不知道自己清楚没。:-)

________________对cblog进行设置在原来基础上加上: -F 1000 ________________

root@192.168.137.128:/usr/local/htdocs# ps aux|grep cblog|wc
    491    5402   35846

==============================================================

对其扩展为多个FastCGI的进程后分别以Unix socket和9002进行较为深入的研究并证明其调度及和程序里cookie在多进程里出现登录失败的问题研究
=======================================================================================
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -f ./cblog -s /tmp/fcgi-blog.sock -F 3
/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25  -f ./cblog
以下结论:其写的blog不支持多个进程的登录,上面起了进程均后只有3个进程,而其中走的是unix socket不是端口有两个:2392、2394。
其它一个是端口:9002,它个没有疑义。对于2392、2394两个进程是可能被fastcgi轮流来接请求的,于是出现cookie登录失败,实践知而只起一个这样的进程ID号,不会存在这样的情况,估计其cookie没有写得兼容多个fastcgi罢。
同时发现只起动/usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi  -f ./cblog -s /tmp/fcgi-blog.sock -F 3,出现其进程有时只有2个,说明程序相当不稳定,所以只能说是起研究之用:
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh  
spawn-fcgi: child signaled: 11
spawn-fcgi: child spawned successfully: PID: 2638
spawn-fcgi: child spawned successfully: PID: 2639
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh
spawn-fcgi: child signaled: 11
spawn-fcgi: child spawned successfully: PID: 2655
spawn-fcgi: child spawned successfully: PID: 2656
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh
spawn-fcgi: child spawned successfully: PID: 2671
spawn-fcgi: child spawned successfully: PID: 2673
spawn-fcgi: child spawned successfully: PID: 2674
只启动上面这一个本地unix socket后出现,如果连接:http://blogtest2.com/panel-user-login.html 也就是9002出现:
The page you are looking for is temporarily unavailable.
Please try again later.
说明这两者:Unix socket和9002是独立的。
(第二:再次证明之反证。)反之,如只起用9002多个pid后,是什么情况?实践一下:
起3个依旧不稳定: /usr/local/webserver/fastcgi/spawn-fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25  -f ./cblog -F 3
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh    
spawn-fcgi: child signaled: 8
spawn-fcgi: child spawned successfully: PID: 2736
spawn-fcgi: child spawned successfully: PID: 2737
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh
spawn-fcgi: child signaled: 11
spawn-fcgi: child spawned successfully: PID: 2752
spawn-fcgi: child spawned successfully: PID: 2753
root@192.168.137.128:/usr/local/webserver/nginx# sh /root/runfastcgi.sh
spawn-fcgi: child spawned successfully: PID: 2763
spawn-fcgi: child spawned successfully: PID: 2765
spawn-fcgi: child spawned successfully: PID: 2766
此时访问 Unix socket出现得到确实是独立的再次证晨:
http://blogtest.com/panel-user-login.html  The page you are looking for is temporarily unavailable.Please try again later.
root@192.168.137.128:/usr/local/webserver/nginx# strace -p 2763 -p 2765
http://blogtest2.com/panel-user-login.html
Process 2763 attached - interrupt to quit
Process 2765 attached - interrupt to quit
[pid  2765] accept(0,  <unfinished ...>
[pid  2763] accept(0, {sa_family=AF_INET, sin_port=htons(56906), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid  2763] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  2763] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\277\1\0\17\32SCRIPT"..., 8192) = 1000
[pid  2763] time(NULL)                  = 1386912681
[pid  2763] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb778e000
[pid  2763] munmap(0xb778e000, 4096)    = 0
[pid  2763] write(5, "\1\6\0\1\0005\3\0X-Accel-Redirect: /templ"..., 88) = 88
[pid  2763] shutdown(5, 1 /* send */)   = 0
[pid  2763] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999995})
[pid  2763] read(5, "", 1024)           = 0
[pid  2763] close(5)                    = 0
[pid  2763] accept(0,
登录action:
[pid  2765] <... accept resumed> {sa_family=AF_INET, sin_port=htons(56908), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid  2765] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  2765] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\4f\2\0\17\32SCRIPT"..., 8192) = 1240
[pid  2765] time(NULL)                  = 1386912715
[pid  2765] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7758000
[pid  2765] gettimeofday({1386912715, 783922}, NULL) = 0
[pid  2765] open("/dev/urandom", O_RDONLY|O_LARGEFILE) = 6
[pid  2765] fcntl64(6, F_GETFD)         = 0
[pid  2765] fcntl64(6, F_SETFD, FD_CLOEXEC) = 0
[pid  2765] getuid32()                  = 0
[pid  2765] getppid()                   = 1
[pid  2765] gettimeofday({1386912715, 801719}, NULL) = 0
[pid  2765] gettimeofday({1386912715, 802502}, NULL) = 0
[pid  2765] read(6, "\304\264\345M\0?\352V\4\320\323\257u$\16\325", 16) = 16
[pid  2765] gettid()                    = 2765
[pid  2765] time(NULL)                  = 1386912715
[pid  2765] open("/etc/localtime", O_RDONLY) = 7
[pid  2765] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2765] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2765] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7757000
[pid  2765] read(7, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 405
[pid  2765] _llseek(7, -7, [398], SEEK_CUR) = 0
[pid  2765] read(7, "\nCST-8\n", 4096)  = 7
[pid  2765] close(7)                    = 0
[pid  2765] munmap(0xb7757000, 4096)    = 0
[pid  2765] munmap(0xb7758000, 4096)    = 0
[pid  2765] write(5, "\1\6\0\1\0\274\4\0Set-Cookie: session=05ef"..., 224) = 224
[pid  2765] shutdown(5, 1 /* send */)   = 0
[pid  2765] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999994})
[pid  2765] read(5, "", 1024)           = 0
[pid  2765] close(5)                    = 0
[pid  2765] accept(0,
跳转到管理页面又变回2763:
[pid  2763] <... accept resumed> {sa_family=AF_INET, sin_port=htons(56909), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid  2763] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  2763] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\374\4\0\17\36SCRIPT"..., 8192) = 1064
[pid  2763] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb778e000
[pid  2763] munmap(0xb778e000, 4096)    = 0
[pid  2763] write(5, "\1\6\0\1\0m\3\0Content-type: text/html\r"..., 144) = 144
[pid  2763] shutdown(5, 1 /* send */)   = 0
[pid  2763] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999150})
[pid  2763] read(5, "", 1024)           = 0
[pid  2763] close(5)                    = 0
[pid  2763] accept(0,
说明这个第一个Unix的socket也好,9002端口也好,都存在我们常说的一个问题就是都会通过fastcgi协议分派到不同的进程中去处理,是有统一调度的!!!
第二:两者是独立的,一个是访问句柄,一个是访问端口进行通讯,独立而不干扰。但是这块七夜写的Cookie的登录判断这块可能写得不够严谨,有时间得看下这块的代码实现才行,同时借鉴PHP的cookie实现机制才能实现真正的cookie在多进程下不会出现失效的问题。EOF
——————第一:混合的情况:Unix Socket和9002同时————
作登录请求
root@192.168.137.128:~# sh /root/runfastcgi.sh
spawn-fcgi: child spawned successfully: PID: 2386
spawn-fcgi: child spawned successfully: PID: 2392
spawn-fcgi: child spawned successfully: PID: 2394
spawn-fcgi: child spawned successfully: PID: 2395
root@192.168.137.128:~# ps aux|grep cblog      
root      2386  0.0  0.2  13868  1112 ?        Ssl  13:15   0:00 ./cblog
root      2392  0.0  0.2  13868  1112 ?        Ssl  13:15   0:00 ./cblog
root      2394  0.0  0.2  13868  1112 ?        Ssl  13:15   0:00 ./cblog
root@192.168.137.128:~# strace -p 2386 -p 2392 -p 2394
从:http://blogtest2.com/panel-user-login.html
到登录:登陆成功!的action都是:2386进程在干(见:)。
root@192.168.137.128:~# strace -p 2386 -p 2392 -p 2394
Process 2386 attached - interrupt to quit
Process 2392 attached - interrupt to quit
Process 2394 attached - interrupt to quit
[pid  2394] accept(0,  <unfinished ...>
[pid  2392] accept(0,  <unfinished ...>
[pid  2386] accept(0, {sa_family=AF_INET, sin_port=htons(56887), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid  2386] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  2386] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\221\7\0\17\32SCRIPT"..., 8192) = 960
[pid  2386] time(NULL)                  = 1386911788
[pid  2386] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d3000
[pid  2386] munmap(0xb77d3000, 4096)    = 0
[pid  2386] write(5, "\1\6\0\1\0005\3\0X-Accel-Redirect: /templ"..., 88) = 88
[pid  2386] shutdown(5, 1 /* send */)   = 0
[pid  2386] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999727})
[pid  2386] read(5, "", 1024)           = 0
[pid  2386] close(5)                    = 0
[pid  2386] accept(0, {sa_family=AF_INET, sin_port=htons(56889), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid  2386] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  2386] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\0048\0\0\17\32SCRIPT"..., 8192) = 1192
[pid  2386] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d3000
[pid  2386] gettimeofday({1386911862, 145842}, NULL) = 0
[pid  2386] open("/dev/urandom", O_RDONLY|O_LARGEFILE) = 6
[pid  2386] fcntl64(6, F_GETFD)         = 0
[pid  2386] fcntl64(6, F_SETFD, FD_CLOEXEC) = 0
[pid  2386] getuid32()                  = 0
[pid  2386] getppid()                   = 1
[pid  2386] gettimeofday({1386911862, 155096}, NULL) = 0
[pid  2386] gettimeofday({1386911862, 155738}, NULL) = 0
[pid  2386] read(6, "\3218\03774\374\342\3\f\330\377M{\214y\24", 16) = 16
[pid  2386] gettid()                    = 2386
[pid  2386] time(NULL)                  = 1386911862
[pid  2386] open("/etc/localtime", O_RDONLY) = 7
[pid  2386] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2386] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2386] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d2000
[pid  2386] read(7, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 405
[pid  2386] _llseek(7, -7, [398], SEEK_CUR) = 0
[pid  2386] read(7, "\nCST-8\n", 4096)  = 7
[pid  2386] close(7)                    = 0
[pid  2386] munmap(0xb77d2000, 4096)    = 0
[pid  2386] munmap(0xb77d3000, 4096)    = 0
[pid  2386] write(5, "\1\6\0\1\0\274\4\0Set-Cookie: session=44ad"..., 224) = 224
[pid  2386] shutdown(5, 1 /* send */)   = 0
[pid  2386] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 982622})
[pid  2386] read(5, "", 1024)           = 0
[pid  2386] close(5)                    = 0
[pid  2386] accept(0,
登录后进入管理:还是2386



方式:fastcgi_pass 127.0.0.1:9002;
http://blogtest.com/panel-user-login.html
[pid  2392] <... accept resumed> {sa_family=AF_FILE, NULL}, [2]) = 5
[pid  2392] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999999})
[pid  2392] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\211\7\0\f\0QUERY_"..., 8192) = 952
[pid  2392] time(NULL)                  = 1386912018
[pid  2392] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7796000
[pid  2392] munmap(0xb7796000, 4096)    = 0
[pid  2392] write(5, "\1\6\0\1\0005\3\0X-Accel-Redirect: /templ"..., 88) = 88
[pid  2392] shutdown(5, 1 /* send */)   = 0
[pid  2392] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999999})
[pid  2392] read(5, "", 1024)           = 0
[pid  2392] close(5)                    = 0
[pid  2392] accept(0,
提交action:
[pid  2394] <... accept resumed> {sa_family=AF_FILE, NULL}, [2]) = 5
[pid  2394] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999991})
[pid  2394] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\4/\1\0\f\0QUERY_"..., 8192) = 1184
[pid  2394] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77dc000
[pid  2394] gettimeofday({1386912056, 976899}, NULL) = 0
[pid  2394] open("/dev/urandom", O_RDONLY|O_LARGEFILE) = 6
[pid  2394] fcntl64(6, F_GETFD)         = 0
[pid  2394] fcntl64(6, F_SETFD, FD_CLOEXEC) = 0
[pid  2394] getuid32()                  = 0
[pid  2394] getppid()                   = 1
[pid  2394] gettimeofday({1386912056, 978495}, NULL) = 0
[pid  2394] gettimeofday({1386912056, 978630}, NULL) = 0
[pid  2394] read(6, "\366\377\210C\247\350\367\231\221a7\271sE}\251", 16) = 16
[pid  2394] gettid()                    = 2394
[pid  2394] time(NULL)                  = 1386912056
[pid  2394] open("/etc/localtime", O_RDONLY) = 7
[pid  2394] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2394] fstat64(7, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
[pid  2394] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77db000
[pid  2394] read(7, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 405
[pid  2394] _llseek(7, -7, [398], SEEK_CUR) = 0
[pid  2394] read(7, "\nCST-8\n", 4096)  = 7
[pid  2394] close(7)                    = 0
[pid  2394] munmap(0xb77db000, 4096)    = 0
[pid  2394] munmap(0xb77dc000, 4096)    = 0
[pid  2394] write(5, "\1\6\0\1\0\274\4\0Set-Cookie: session=c605"..., 224) = 224
[pid  2394] shutdown(5, 1 /* send */)   = 0
[pid  2394] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999992})
[pid  2394] read(5, "", 1024)           = 0
[pid  2394] close(5)                    = 0
[pid  2394] accept(0,
http://blogtest.com/cpanel.htm  [未登录]
[pid  2392] <... accept resumed> {sa_family=AF_FILE, NULL}, [2]) = 5
[pid  2392] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999989})
[pid  2392] read(5, "\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\357\1\0\f\0QUERY_"..., 8192) = 1048
[pid  2392] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7796000
[pid  2392] munmap(0xb7796000, 4096)    = 0
[pid  2392] write(5, "\1\6\0\1\0m\3\0Content-type: text/html\r"..., 144) = 144
[pid  2392] shutdown(5, 1 /* send */)   = 0
[pid  2392] select(6, [5], NULL, NULL, {2, 0}) = 1 (in [5], left {1, 999993})
[pid  2392] read(5, "", 1024)           = 0
[pid  2392] close(5)                    = 0
[pid  2392] accept(0,  
方式:fastcgi_pass   unix:/tmp/fcgi-blog.sock;
Download:
http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
configure and make :

实践Ok如下:
能到到Get的配置: upload_pass     /up.php?$args;     ,并重新启动Nginx即可。
阅读全文
背景:近来对Nginx的上传模块这一块,Flash上传时进度条都过了,但是那个文件还没有出现,一会儿后才出现那个文件,并慢慢增大,我用的是Nginx的上传插件,这种问题怎么去查?我刚用了strace,我在想它是把上传的东东放在哪儿去了呢?
http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
Rango  上午 11:56:57
用apache来做吧,apache是交给php来处理的,
回忆未来-向东-Jàck  下午 12:01:57
嗯,我再看看,兄弟觉得Apache下的PHP比起Nginx的PHP在上传一块有更高的效率是么?
Rango  下午 12:02:23
都差不多吧
apache比较成熟

=================================================================================
Rango  下午 01:45:42
你看下 man pwrite
回忆未来-向东-Jàck  下午 01:55:19
好看到了,这个PHP上传大文件和Nginx上传大文件,是先接进来放到内存后,在写到文件里吧?
Rango  下午 01:55:30
嗯,是的,都是这样做了
pwrite就是相当于 fseek + fwrite
回忆未来-向东-Jàck  下午 01:56:55
至于内存里放在什么时候开始写,那应该是由nginx程序里的配置来实现的吧?
如果我猜测没错的话
=================================================================================
upload_buffer_size 上传缓冲区大小
upload_max_file_size 指定上传文件最大大小,软限制。client_max_body_size硬限制。
upload_limit_rate 上传限速,如果设置为0则表示不限制。
upload_pass_args 是否转发参数。
=============================================================================


=============================================================================
ack 1460:
第一个报文的TCP头里通过MSS这个可选项告知对方本端能够接收的最大报文(当然,这个大小是TCP净荷的大小),以太网上这个值一般设置成1460,因为1460Byte净荷+20Byte TCP头+20Byte IP头 = 1500字节,正好符合链路层最大报文的要求。
http://wenku.baidu.com/view/d77645d533d4b14e84246800.html


strace -p 7269  -o s.log
Nginx太多了进程:
[root@test tmp]# cat strace.sh


都是读4096个字符一次写,pwrite64和这个相当应该:
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);


原型  char *  fgets(char * s, int n,FILE *stream);
    参数:
         s: 字符型指针,指向存储读入数据的缓冲区的地址。
         n: 从流中读入n-1个字符
         stream : 指向读取的流。


函数原型
ssize_t pwrite(intfd, const void *buf, size_tcount, off_toffset);
编辑本段
用法
返回值:成功,返回写入到文件中的字节数;失败,返回-1;
参数:
(1) fd:要写入数据的文件描述符
(2) buf:数据缓存区指针,存放要写入文件中的数据
(3) count:写入文件中的数据的字节数
(4) offset:写入起始地址的偏移量,写入地址=文件开始+offset。注意,执行后,文件偏移指针不变

什么是字节,字节数相关学习备案:
字节(Byte 发音:/‘bait/):字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位。在ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。符号:英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节的大小 。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值:0 最大值:255 。如一个ASCII码就是一个字节,此类单位的换算为:  1KB(Kilobyte 千字节)=1024B,1MB(Megabyte 兆字节 简称“兆”)=1024KB,1GB(Gigabyte 吉字节 又称“千兆”)=1024MB,
数据包是信息在通行通道上传递的形式~~
字节是信息的单位~~一字节等于8个比特位!
wc - c 统计字节数:
[root@test ~]# cat a.txt |wc -c
2  [里面写:a的字节数]
[root@test ~]# vi a.txt        
[root@test ~]# cat a.txt |wc -c
8  [里面写:a向东 的字节数]
比特(bit)即一个二进制位  例如100011就是6比特
字节(byte)这是计算机中数据类型最基本的单位了,8bit 组成1byte
字(word)两个byte称为一个word,所以字大小应该是16位bit,共两字节。(Shell里的)
双字(double word 简写为DWORD)见名知意,两个字,四个字节,32bit。
C语言:char 字符型  占1byte 即8位,一个char型数据(例如:a、#、!之类的)用了1个字节来存储:

root@192.168.137.128:~# ./a.out
size of char a=1
size of char =1



中间断开测试,浏览器突然断开:
accept4(5, {sa_family=AF_INET, sin_port=htons(58438), sin_addr=inet_addr("192.168.137.1")}, [16], SOCK_NONBLOCK) = 3
epoll_ctl(13, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLET, {u32=3039736117, u64=722997274181808437}}) = 0                    
epoll_wait(13, {{EPOLLIN, {u32=3039736117, u64=722997274181808437}}}, 512, 60000) = 1                              
gettimeofday({1368072732, 443326}, NULL) = 0                                                                        
recv(3, "POST /upload HTTP/1.1\r\nHost: tes"..., 32768, 0) = 32768                                                  
recv(3, "\0\1\0\0*0\0\0\0\2\0\0\0\0\0\0\0\1\0\0*0\0\0\0\2\0\0\0\0\0\0"..., 8192, 0) = 8192                          
epoll_wait(13, {{EPOLLIN, {u32=3039736117, u64=722997274181808437}}}, 512, 7) = 1                                  
gettimeofday({1368072732, 446037}, NULL) = 0                                                                        
epoll_wait(13, {}, 512, 4)              = 0                                                                        
gettimeofday({1368072732, 451445}, NULL) = 0                                                                        
open("/data/app/test.local/upload_tmp/0000000005", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4                    
pwrite64(4, "\0\0\0\24ftypisom\0\0\0\1isom\0\rx\373moov\0\0\0l"..., 4096, 0) = 4096                                
pwrite64(4, "\0\2\0\0\0\0\0\0\0\3\0\0\16\20\0\0\0\1\0\0*0\0\0\0\2\0\0\0\0\0\0"..., 4096, 4096) = 4096              
pwrite64(4, "\0\1\0\0*0\0\0\0\2\0\0\0\0\0\0\0\1\0\0*0\0\0\0\2\0\0\0\0\0\0"..., 4096, 8192) = 4096                  

.........................................


pwrite64(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 7622656) = 4096          
pwrite64(4, "e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\240\5\343\t\240\335d\t@\327d\t\240.\341\t"..., 4096, 7626752) = 4096
recv(3, 0xa0a9048, 8192, 0)             = -1 EAGAIN (Resource temporarily unavailable)                            
epoll_wait(13, {{EPOLLIN|EPOLLERR|EPOLLHUP, {u32=3039736117, u64=722997274181808437}}}, 512, 60000) = 1          
gettimeofday({1368072745, 256485}, NULL) = 0                                                                      
recv(3, 0xa0a9048, 8192, 0)             = -1 ECONNRESET (Connection reset by peer)                                
pwrite64(4, "s\0i\0t\0o\0r\0y\0\0\0\0\0\36\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 2800, 7630848) = 2800              
close(4)                                = 0                                                                      
unlink("/data/app/test.local/upload_tmp/0000000005") = 0                                                          
write(9, "2013/05/09 12:12:25 [alert] 7269"..., 240) = 240                                                        
close(3)                                = 0                                                                      
epoll_wait(13,  <unfinished ...>  



阅读全文
对于nginx+php的一些网站,上传文件大小会受到多个方面的限制,一个是nginx本身的限制,限制了客户端上传文件的大小,一个是php.ini文件中默认了多个地方的设置。所以为了解决上传文件大小限定的问题必须要做出多处修改。以下整理了几个地方。

1、修改/usr/local/nginx/conf/nginx.conf 文件,查找 client_max_body_size 将后面的值设置为你想设置的值。比如:

附录:Nginx有一个Upload组件:
上传速率,上传Body大小,也就是上传文件时可能较大?
client_max_body_size 1024M
upload_limit_rate 158k
如下:


2、修改php.ini

在php.ini里面查看如下行:

默认允许HTTP文件上传,此选项不能设置为OFF。
upload_tmp_dir =/tmp/www


在上传大文件时,你会有上传速度慢的感觉,当超过一定的时间,会报脚本执行超过30秒的错误,这是因为在php.ini配置文件中max_execution_time配置选项在作怪,其表示每个脚本最大允许执行时间(秒),0 表示没有限制。你可以适当调整max_execution_time的值,不推荐设定为0。

参考文章:
PHP.INI配置:文件上传功能配置教程:http://www.leapsoul.cn/?p=488
背景:把Nginx用来代理apache的svn,在传一个psd时出现:Server sent unexpected return value (413 Request Entity Too Large) in respon。

Nginx上传文件出现一个错误:413 Request Entity Too Large,百度了一下,原来是文件太大了。
原因上传文件超过最大值,修改nginx.conf的值就可以解决了。
client_max_body_size 2M
改为
client_max_body_size 50M;
背景:
   对于Nginx的上传模块,在内存上可能会有不少的缩减和PHP的相比,在性能上也就是上传的速度可能要快2,3倍,但这个模块对认证的配置没有,也就是如有某cookie才能上传等,它仅仅就是一个模块,也就是说这一块还有待hack或作者本人去实现,我看网上也有其它兄弟想用并去试着实现这一块。因为是http里的rfc协议的支持,它也就支持断点续传了,这有一篇文章讲述到这一块,于是做出转载之举动,文章如下:
阅读全文
背景:Lua在游戏行业比较火,不少公司在用它。
最近公司在考虑做openapi的proxy服务器,公司主营网游,旗下多款游戏的用户登陆,充值等等有很多接口,想聚合分散的接口统一走一个通道,所以都要走这上面,压力不小。
在语言和平台上主要在nodejs和ngx_lua中选择,当然最后还是选择了ngx_lua放弃了nodejs的方案,主要原因:
1、主要考虑公司会nodejs的人貌似就我一个,会累死我的
2、对于ngx的运维和配置相对比nodejs来说更加熟悉和有经验
3、从各种性能测试来说ngx_lua似乎在CPU和内存上更胜一筹

我在研究一阵子ngx_lua之后发现lua语法和js真的很像,同时ngx_lua模型也是单线程的异步的事件驱动的,工作原理和nodejs相同,代码甚至比nodejs的异步回调更好写一些。

性能测试,100并发
php:17400
nodejs:31197
ngx_lua:32628

单纯做http代理服务器加上一些简单的逻辑,似乎ngx_lua的方案更加合适,同时ngx_lua还支持redis、mysql等数据库的支持。

最后附上PHP vs Node.js vs Nginx-Lua性能测试,转载的
http://bluehua.org/demo/php.node.lua.html
洋葱路由(Onion Routing)是在一个计算机网络上的匿名通信技术,由David Goldschlag, Michael Reed, 和 PaulSyverson发展。洋葱路由(OR)的目标是保护一条信息发送者和接受者的隐私,同时当它在网络中转换时也提供对信息内容的保护。洋葱路由根据Chaum的混合瀑布原理完成这个:信息从源地出发经过一个代理序列(洋葱路由器)到达目的地,当重路由信息在一个不可预知的路径时。为了保护敌手偷听信息内容,信息被在路由器之间加密。洋葱路由的优点(一般是混合串联)是不必要去相信每个合作路由器;如果一个或多个路由器是不安全的、匿名通信仍然可以被完成。

Linux下windows都有:黑客x档案2011年1月刊。
有时间可以看一下:
Nginx开发从入门到精通:
http://tengine.taobao.org/book/
nginx模块开发篇:
http://tengine.taobao.org/book/module_development.html
材料有四样,准备如下模块和代码,用python脚本也是可以很快测试一下断点上传的,链接在:https://jackxiang.com/post/8331/
1.php的支持,自带的,就是建立一个fast-cgi跑php,提供一个test.php显示最终结果
2.nginx_upload_module 上传插件
http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
3.nginx_upload_progress_module,上传进度条插件
akostrikov-nginx-upload-progress-module-v0.8.2-1-g3d8e105.zip
http://wiki.nginx.org/HttpUploadProgressModule
下载
https://nodeload.github.com/akostrikov/nginx-upload-progress-module/zipball/master
4.https://github.com/drogus/jquery-upload-progress ,显示进度条的jquery插件
__________________________________________________________________
编译:


疑难问题,nginx: [emerg] zero size shared memory zone "proxied",在nginx.conf里加一行upload_progress proxied 1m;:




解决nginx上传模块nginx_upload_module传递GET参数的方法总结:
http://www.cnblogs.com/lidabo/p/4169752.html

Download:
http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
configure and make :

Nginx配置文件:




较靠谱的文章:http://blog.sina.com.cn/s/blog_704836f401014bpj.html


因为nginx upload module已经做完了最费时的mime解析工作,后端的PHP代码只需要简单的移动文件到合适的位置就可以了。因为upload module是使用C语言写的,比起PHP作解析工作的效率高多了,因此极大地提高了文件上传的效率。

二、upload module的配置参数简要说明

下边是一些配置参数的说明:

upload_pass 指明了需要后续处理的php地址
upload_cleanup 如果php出现400 404 499 500-505之类的错误,则删除上传的文件
upload_store 上传文件存放地址
upload_store_access 上传文件的访问权限,user:r是指用户可读
upload_limit_rate 上传限速,如果设置为0则表示不限制
upload_pass_form_field 从表单原样转到后端的参数,可以正则表达式表示
官方的例子是upload_pass_form_field "^submit$|^description$";
意思是把submit,description这两个字段也原样通过upload_pass传递到后端php处理。如果希望把所有的表单字段都传给后端可以用upload_pass_form_field "^.*$";


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

背景:追求极致,由服务器脚本(比如PHP)来负责接收上传的数据。这种方式存在性能和效率的问题。所以,决定采用Nginx的上传模块来完成接收数据的功能,接收完数据后,再去转给后端脚本语言进行后续处理(比如:移动文件、插入文件的信息到数据库中)。

RFC 1867:
module for nginx web server for handling file uploads using multipart/form-data encoding (RFC 1867) and resumable uploads according to this protocol.
Description

The module parses request body storing all files being uploaded to a directory specified by upload_store directive. The files are then being stripped from body and altered request is then passed to a location specified by upload_pass directive, thus allowing arbitrary handling of uploaded files. Each of file fields are being replaced by a set of fields specified by upload_set_form_field directive. The content of each uploaded file then could be read from a file specified by $upload_tmp_path variable or the file could be simply moved to ultimate destination. Removal of output files is controlled by directive upload_cleanup. If a request has a method other than POST, the module returns error 405 (Method not allowed). Requests with such methods could be processed in alternative location via error_page directive.

Nginx.conf
======================================================================

1.上面的#include fastcgi_params; 被我注释掉了,否则出现:405 Method not allowed ,查了下:
Nginx 静态文件中的 POST 请求返还 405 Method not allowed 错误,于是用了9000的PHP端口。
index.php 内容:


上传后返回:
Array
(
    [file1_name] => 6597350142123536341.jpg
    [file1_content_type] => image/jpeg
    [file1_path] => /data/app/test.local/upload_tmp/0000000001
    [file1_md5] => 5a84d879e497bf64acebdc84c4701a76
    [file1_size] => 110001
    [file2] =>
    [file3] =>
    [file4] =>
    [file5] =>
    [file6] =>
    [submit] => Upload
    [test] => value
)
先看一下这个上传目录的结构是这样的,这些编号的都是上传的素材,没有后缀:
/data/app/test.local/upload_tmp# ls
0000000001  0006630963  0006630964

查看目录下有没有这个文件:
ls /data/app/test.local/upload_tmp/0000000001
/data/app/test.local/upload_tmp/0000000001
sz 下来,更名为.jpg的:
sz  /data/app/test.local/upload_tmp/0000000001 ==》0000000001.jpg ,打开一看果然是我上传的文件,得证!

把这个文件放到自己定义的目录下:

多个文件的一个情况,也就是多个文件的POST数组规律,去进行移动文件即可:
<input type="file" name="file2">
<input type="file" name="file2">
  
[file1_name] => 1332460275090024.jpg
[file1_content_type] => image/jpeg
[file1_path] => /data/app/test.local/upload_tmp/0000000034
[file1_md5] => 4e84aac3bc2cc25b7c69c7b506e4967f
[file1_size] => 73702
[file2_name] => desktop.ini
[file2_content_type] => application/octet-stream
[file2_path] => /data/app/test.local/upload_tmp/0000000035
[file2_md5] => dc723b859dec1526568ad581aec334d5

因为nginx upload module已经做完了最费时的mime解析工作,后端的PHP代码只需要简单的移动文件到合适的位置就可以了。因为upload module是使用C语言写的,比起PHP作解析工作的效率高多了,因此极大地提高了文件上传的效率。

upload_cleanup 如果php出现400 404 499 500-505之类的错误,则删除上传的文件,这块可以利用PHP进行逻辑判断后输出header头来进行操作是否删除文件。
======================================================================
补安装编译方法:
1.下载
wget http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
2.编译(在NGINX编译目录执行以下命令, 其中 --add-module=你下载解压的上传插件目录)
./configure --user=www --group=www --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module   --add-module=/root/software/nginx_http_push_module-0.692   --add-module=/root/software/ngx_cache_purge-1.3 --add-module=/root/software/nginx_upload_module-2.2.0

3.上传界面:


参考来源:
1)nginx上传模块—nginx upload module安装:http://waynerqiu.com/7/136.html
2)写得很简洁的安装方法:http://foooy.me/nginx/158.html  【该文里提到的接受PHP,这块没有做详细的配置,参考上面这篇文章即可。】
3)http://anerg.com/read.php?55  
//这一篇文章描述到:upload_pass     /index.php?c=uploader&a=upload_server; 也就是有框架时怎么用框架的action来进行处理。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------
最后,后记备查用相关模块的使用:
听说有一个哥们解决了get的问题,通过相关nginx的指令实现的,没实践:http://waynerqiu.com/7/139.html
还有实现断点续传,进度显示等的:
最近做一个产品,需要实现从网页上传文件给服务器。一般情况下都是采用Ajax异步方式,创建一个iframe,在iframe里面把数据以form方式提交给后端的服务器脚本,由服务器脚本(比如PHP)来负责接收上传的数据。这种方式存在性能和效率的问题。所以,决定采用Nginx的上传模块来完成接收数据的功能,接收完数据后,再去转给后端脚本语言进行后续处理(比如:移动文件、插入文件的信息到数据库中)。同时,由于需要在前端展现上传的进度,因此可以利用Nginx一个uploadprogress模块来获取。
     整个处理框图如下:
     点击在新窗口中浏览此图片

实现步骤:
     1、查看Nginx是否安装了这两个模块(nginx_upload_module和nginx_uploadprogress_module),命令nginx -V (注意是大写),可以查看Nginx当时编译时候的参数,如果发现有上述两个模块,说明Nginx已经安装了这两个模块。如果没有的话,就需要安装这两个Nginx模块。由于这两个模块不在Nginx源代码中,需要重新编译Nginx,在编译选项中加上
    --add-module=/模块源代码路径/nginx_upload_module-2.2.0 --add-module=/模块源代码路径/nginx_uploadprogress_module-0.8.2 。
      2、由于产品的前端使用的是jQuery框架,所以,找了一个现成的jQuery下的上传文件插件(ajaxfileupload)。该代码基本原理就是动态创建一个iframe,在iframe中再增加一个form,最后数据放到这个form中提交给服务器,代码量比较小也就200来行代码。前端的代码如下:


其中,success的回调函数参数是服务器返给浏览器的结果。
3、配置Nginx,实现上传模块来接收页面上传的文件。把下面配置添加到Nginx的配置文件中,注意是加在server的上下文中。
        location = /upload {
                upload_pass     /service.php?path=uploadfile&a=upload_server;//表示Nginx接收完上传的文件后,然后交给后端处理的地址
                upload_cleanup 400 404 499 500-505; //表示当发生这些http status代码的情况下,会把上传的文件删除
                upload_store    /tmp/upload_tmp 1;//上传模块接收到的文件临时存放的路径, 1 表示方式,该方式是需要在/tmp/upload_tmp下创建以0到9为目录名称的目录,上传时候会进行一个散列处理。
                upload_store_access user:r; //指定访问模式
                upload_limit_rate 128k; //设定上传速度上限
                upload_set_form_field "${upload_field_name}_name" $upload_file_name; //设定后续脚本语言访问的变量,其中${upload_field_name}对照本例子就是addfile。比如后台PHP就可以通过$_POST['addfile_name']来获取上传文件的名称。
                upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;//同上
                upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;//由于在upload_store设置了临时文件存放根路径,该路径就是经过散裂后上传文件存在真实路径,比如后续处理可以根据这值把上传文件拷贝或者移动到指定的目录下。
                upload_pass_form_field "^.*$";//
                upload_pass_args on;// 打开开关,意思就是把前端脚本请求的参数会传给后端的脚本语言,比如:http://192.168.1.203:7100/upload/?k=23.PHP脚本可以通过$_POST['k']来访问。
               track_uploads proxied 30s; #30s表示每次链接处理完毕后,链接会保持30s。
        }
4、上述配置完了,就可以实现上传的功能了。但是,要获取上传的进度,那还是需要配置另外一个模块nginx_uploadprogress_module。其实,获取当前进度原理比较简单,就是通过javascript以异步方式定时给特定地址发送请求,这个模块会以json格式返回上传的进度。配置比较简单。
          1)、首先打开这个模块功能,在Nginx配置文件中http上下文里面,增加upload_progress proxied 5m;其中,proxied表示名称(zone_name官方文档),5m表示每次链接存放跟踪信息的大小。另外,再设置返回格式为json,upload_progress_json_output;
          2)、在上述的location = /upload中增加一个配置项track_uploads proxied 30s; 其中,proxied就是刚才在第一步设置的名字,30s表示每次链接处理完毕后,链接会保持30s。
          3)、设置一个location来处理javascript发送请求。
          location ^~ /progress {

  report_uploads proxied;    #GET此地址得到上传进度
}
           4)、还有一个参数考虑设置upload_progress_header ,这个值缺省是X-Progress-ID。有点类似SessionID,主要用在前台需要在上传文件的时候需要设置这个参数值,比如设置为uuid值。这样javascript每次发送请求要获取上传进度时候,都需要带上这个参数,这样上传进度跟踪模块才知道是返回那个链接的进度。
           经过这三步骤,就把上传进度跟踪模块配置好了。现在就需要对前台脚本就行修改
5、修改第2步的前台脚本



上述黑体就是增加的代码,其中,有些函数是调用产品封装好的函数,所以,不要全部照搬。主要是抓住以下几个要点就可以了:
    1、在上传文件时候需要增加一个uuid,对应的参数就是upload_progress_header设置的,缺省是X-Progress-ID。
    2、在请求获取进度的时候,都要带上这个uuid。
    3、设定一个定时期,定时发送异步的GET方式请求,获取进度数据。
    4、返回的json格式是{"state":"uploading", "size":3232,"received":34},其中上传完毕state值为done,如果发生错误会,state就是error,并且会返回status,错误编码。
    
    步骤就介绍在这里了。另外,javascript方式上传文件,在用户上传文件时候,最好能获取上传文件大小,这样可以提前告诉用户是否超出允许上传的大小值。但是,目前javascript方式获取文件大小要兼容所有浏览器还是存在问题。我打算还是写个flash,通过flash方式来获取,比较保险。

来自:http://blog.csdn.net/waden/article/details/7040123

更多参考:http://blog.sina.com.cn/s/blog_704836f401014bpj.html
分页: 3/5 第一页 上页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]