msgbartop
学习,工作记录
msgbarbottom

23 十一 09 django打包成客户端软件

用django做了一个网站,希望断网的时候,也能够在本地使用。google的gears功能很弱,需要一大堆js来操作sqlite数据库,感觉很麻烦。因此还是需要自己弄一个客户端软件。

py2exe可以提供打包功能,将python打包成一个可执行的exe文件。google了一下“django py2exe” ,已经有了很多详细的文档。这个老外的博客比较详细,按照这个流程下来就基本搞定了。

首先确定要打的包:

  1. django
  2. cherrypy,是多线程的http服务器,替换django的http测试服务器
  3. 自己的app
  4. python的email

编写一个用于启动的python文件,从原作者处拷贝过来,稍微做了一些修改,命名为startdesktop.py

import os
import sys

os.environ[ 'DJANGO_SETTINGS_MODULE' ] = "settings"

import settings
from cherrypy import wsgiserver
import cherrypy
import webbrowser
from django.core.handlers.wsgi import WSGIHandler
from django.core.servers.basehttp import AdminMediaHandler

if __name__ == "__main__":
  print ‘To exit DemoSite close this window.’

  # Set up site-wide config first so we get a log if errors occur.
  cherrypy.config.update({
    ‘environment’: ‘production’,
    ‘log.error_file’: ’site.log’,
    ‘log.screen’: True,
  })

  # run CherryPy and open browser
  try:
    full_media_path = os.path.dirname( os.path.abspath( sys.argv[ 0 ])) + settings.ADMIN_MEDIA_PREFIX

    cherrypy.tree.graft(
      AdminMediaHandler(
        WSGIHandler(),
        media_dir=full_media_path
      ),
      ‘/’
    )
    cherrypy.server.socket_port = settings.WEB_SERVER_PORT
    cherrypy.server.start()
    cherrypy.engine.start_with_callback( webbrowser.open, ( settings.START_URL,), )   
    cherrypy.engine.block()
  except KeyboardInterrupt:
    cherrypy.server.stop()

再然后就是py2exe的setup.py文件的编写了,基本上照抄下来,原作者使用的django版本很老,有一些模块已经没有了,同时又增加了很多新模块。同时目前的网站代码还是比较多,要手工一个个写是在太麻烦,就写一个函数搜一下,自动把当前的app文件添加进去。同时用正则表达式查找导入的django模块,发现一个就自动添加一个。修改后的setup.py文件如下:

# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe
import os

def add_path_tree( base_path, path, skip_dirs=[ '.svn', '.git' ]):
  path = os.path.join( base_path, path )
  partial_data_files = []
  for root, dirs, files in os.walk( os.path.join( path )):
    sample_list = []
    for skip_dir in skip_dirs:
      if skip_dir in dirs:
        dirs.remove( skip_dir )
    if files:
      for filename in files:
        sample_list.append( os.path.join( root, filename ))
    if sample_list:
      partial_data_files.append((
        root.replace(
          base_path + os.sep if base_path else ”,
          ”,
          1
        ),
        sample_list
      ))
  return partial_data_files

def add_python_file(includes,curpath,prefix=”):
    files = os.listdir(curpath)
    for f in files:
        fpath = os.path.join(curpath, f)
        if os.path.isdir(fpath):
            if f == ‘.svn’:
                continue
            add_python_file(includes,fpath,prefix+’%s.’ % f)
        else:
            name,ext = os.path.splitext(f)
            if ext == ‘.py’:
                includes.append(’%s%s’ % (prefix,name))
                add_django_import(includes,fpath)

import re
pat = r’from +django\.(.*?) +import +(.*?)( +as +|\n)’
def add_django_import(includes,filepath):
    #print filepath
    f = open(filepath,’r')
    data = f.read()
    f.close()
    models = re.findall(pat,data)
    for m in models:
        prefix = ‘django.%s.’ % m[0]
        pys = m[1].split(’,')
        for p in pys:
            p = p.lower().strip()
            dmodel = ‘%s%s’ % (prefix,p)
            add_django_file(includes,dmodel)
        prefix = ‘django.%s’ % m[0]
        add_django_file(includes,prefix)

def add_django_file(includes,dmodel):
    if dmodel in includes:
        return
    item = dmodel.replace(’.',’/')
    mpath = os.path.join(django_path,item)
    if os.path.exists(mpath):
        print ‘1′,dmodel
        includes.append(dmodel)
        #如果是django的目录,则继续寻找
        mpath = os.path.join(mpath,’__init__.py’)
        #print mpath
        if os.path.exists(mpath):
            add_django_import(includes,mpath)
    else:
        mpath = os.path.join(django_path,’%s.py’ % item)
        if os.path.exists(mpath):
            #如果是django的文件,则继续寻找
            print ‘2′,dmodel
            #print mpath
            includes.append(dmodel)
            add_django_import(includes,mpath)

py2exe_options = {
  ‘py2exe’: {
    ‘compressed’: 1,
    ‘optimize’: 2,
    ‘ascii’: 1,
    ‘bundle_files’: 1,
    ‘dist_dir’: ‘../setup-client’,
    ‘packages’: [ 'encodings' ],
    ‘excludes’ : [
      'pywin',
      'pywin.debugger',
      'pywin.debugger.dbgcon',
      'pywin.dialogs',
      'pywin.dialogs.list',
      'Tkconstants',
      'Tkinter',
      'tcl',
    ],
    ‘dll_excludes’: [ 'w9xpopen.exe', 'MSVCR71.dll' ],
    ‘includes’: [
    'django.template.loaders.filesystem',
    'django.template.loaders.app_directories',
      'django.middleware.common',
        'django.contrib.auth.backends',
        'django.contrib.sessions.middleware',     
        'django.middleware.doc',     
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sessions.backends.db',
        'django.contrib.sites',
        'django.contrib.admin',
        'django.core.cache.backends',
        'django.db.backends.sqlite3.base',
        'django.db.backends.sqlite3.introspection',
        'django.db.backends.sqlite3.creation',
        'django.db.backends.sqlite3.client',
        'django.template.defaulttags',
        'django.template.defaultfilters',
        'django.template.loader_tags',
        'django.conf.urls.defaults',
        'django.contrib.admin.views.main',
        'django.core.context_processors',
        'django.contrib.auth.management',
        'django.contrib.auth.management.commands',
        'django.contrib.auth.handlers',     
        'django.contrib.auth',
        'django.contrib.auth.middleware',
        'django.views.static',
        'django.contrib.admin.templatetags.adminmedia',
        'django.contrib.admin.templatetags.admin_list',
        'django.contrib.admin.templatetags.admin_modify',
        'django.contrib.admin.templatetags.log',
        'django.conf.urls.shortcut',
        'django.views.defaults',
        'django.core.cache.backends.locmem',
        'django.templatetags.i18n',
        'django.views.i18n',
      # also used by django?
      'email.mime.audio',
      'email.mime.base',
      'email.mime.image',
      'email.mime.message',
      'email.mime.multipart',
      'email.mime.nonmultipart',
      'email.mime.text',
      'email.charset',
      'email.encoders',
      'email.errors',
      'email.feedparser',
      'email.generator',
      'email.header',
      'email.iterators',
      'email.message',
      'email.parser',
      'email.utils',
      'email.base64mime',
      'email.quoprimime',
      'traceback',
    ],
  }
}

# Take the first value from the environment variable PYTHON_PATH
python_path = os.environ[ 'PYTHONPATH' ].split( ‘;’ )[ 0 ]

django_path = os.path.normpath( python_path + ‘/lib/site-packages/’)

django_admin_path = os.path.normpath( python_path + ‘/lib/site-packages/django/contrib/admin’ )
py2exe_data_files = []

lc_path = os.path.normpath( python_path + ‘/lib/site-packages/django/conf/locale’)

# django admin files
py2exe_data_files += add_path_tree( django_admin_path, ‘templates’ )
py2exe_data_files += add_path_tree( django_admin_path, ‘media’ )
# project files
py2exe_data_files += add_path_tree( ”, ‘newmedia’ )
py2exe_data_files += add_path_tree( ”, ‘db’ )

exedict = py2exe_options['py2exe']
includes = exedict['includes']
curpath = os.path.dirname(__file__)
add_python_file(includes,curpath)

django_auth_path = os.path.normpath( python_path + ‘/lib/site-packages/django/contrib/auth’ )
add_python_file(includes,django_auth_path,prefix=’django.contrib.auth.’)
add_python_file(includes,django_admin_path,prefix=’django.contrib.admin.’)

print includes

setup(
  options=py2exe_options,
  data_files=py2exe_data_files,
  zipfile = None,
  console=[ 'startdesktop.py' ],
)

最后再执行setup.py py2exe就开始打包了,最后得到的exe为6M多,有点大。

在这个过程中,还会碰到其他问题:

  1. template文件太多,不能暴露出去,这个时候可以预先装载template文件到一个py文件中,再编写一个load_template_source函数,放到settings中的TEMPLATE_LOADERS,用于模板查找就可以了。
  2. admin界面不能使用,因为django使用imp来查找app的admin.py文件,而imp不能搜索.zip文件。可以使用woobiz的方法解决,这个暂时还没有试验。

02 十一 09 网站的页面优化

网站上线之后,添加到了Google的网站管理员工具。发现google从网站内部提取出了一些奇怪的关键字,比如padding,style,class,这些都是html的标签属性,不应该可见的,难道页面有问题,导致google分析页面出现问题?正好要调整一下页面,所以就一起来弄了。

首先整个网站的结构需要进行调整,原先的html页面内写了太多的style了,有太多的padding了,现在把风格统统调整到一个单独的css文件中。原先在张沈鹏的http://kanrs.com/网站上见过相关介绍,这两天网站好像无法访问了。从http://blog.html.it/layoutgala/获得比较简单的结构,采用css就可以调整各个版块的布局,很方便。

<div id="container">
  <div id="header">Header</div>
  <div id="wrapper">
    <div id="content">Content</div>
  </div>
  <div id="navigation">Navigation</div>
  <div id="extra">Extra stuff</div>
  <div id="footer">Footer</div>
</div>

采用这个模板的一个好处是可以把页面正文放在前面,让搜索引擎能够尽快找到真正的内容。原先的结构是把navigation菜单内容放到了前面,结果baidu认为navigation菜单内容比较重要,显示出来了,google比较智能,能够识别真正的内容。

另外一个定宽的css模板推荐使用Variable Grid System,可以自动生成所需要的css模板。我们的网站不需要定宽,就不采用这个960 Grid了。

结构调整之后,就开始移除padding,style等标签属性了。这个问题不大,慢慢来弄就好了。另外发现在html页面中直接展示了“>”字符,这是一个闭合符号,应该用“&gt;”替代的,不知道这是否是导致google解析有误的地方?这些地方也要修改。

firefox的插件web developer真的不错,可以检查很多内容。在网页信息中,让它显示了一下排版信息,结果看到了很多粉红色的方块,拿douban的网页来看,基本上没有粉红色方块。我猜应该是dom的层次太多,导致了粉红色。开始对div进行调整,没有必要的就去掉,能够合并的就合并,div层次减少之后,再来看看,没有粉红色了。

web developer还可以检验html页面是否符合xhtml规范,html规范等,选择工具,validator HTML,则会跳到Markup Validation Service,可以进行完整的检验,利用这个工具,发现了一个未闭合的标签。还发现一些属性没有加上引号。修改之后,错误减少了很多,剩下的错误主要是图片标签没有加alt属性了。

另外也看了一些seo的书籍,查看了网站管理员/站长 帮助,调整了页面的title,keyword,description等等。感觉这次调整差不多了,先更新到网站上看看效果。

14 十 09 屏蔽ip地址

在nginx中可以直接屏蔽某些IP地址,加上如下语句即可:

deny 221.194.132.0/24;

这样这些ip访问网站的时候,会得到403错误,但有一个问题,访问记录会保存到error.log中,有些垃圾爬虫得到了403错误,还是不断访问,导致log很大,好在可以使用iptables屏蔽:

sudo iptables -A INPUT -i eth0 -j DROP -p tcp --dport 80 -s 221.194.132.0/24

这样nginx也可以轻松一些了。

13 十 09 django 发送错误报告

网站发布之后,需要设置debug=false。这时候如果发生500错误,就不能直接看到出错信息了,django会通过email发送相关的错误信息。需要在settings中进行相关设置即可。老外有一篇文章写得很详细,主要设置如下字段:

EMAIL_HOST=’smtp.xxx.com’
EMAIL_PORT=25
EMAIL_HOST_USER=’my_mailbox_name’
EMAIL_HOST_PASSWORD=’my_mailbox_password’
SERVER_EMAIL=’webmaster@yyy.com’
ADMINS=( (’PK Shiu’, ’support@yyy.com’),)
DEBUG=False

gmail功能强大,可以使用gmail来发送,可以新注册一个gmail信箱专门用于发送错误报告。在settings中需要再加一个设置:

EMAIL_USE_TLS = True

01 五 09 mysql错误

ubuntu8.04下使用apt-get安装mysql的缺省版本是5.0.5,安装完成时候,出现一些问题,无法启动mysqld,提示如下:

* Checking for corrupt, not cleanly closed and upgrade needing tables.

查了一下,好像没有什么好的解答,似乎这个提示和无法启动mysqld没有什么关系,查看mysql的log,也没有什么记录下来。所以干脆用源代码来进行安装,下了最新的5.1.34。在安装mysql之前,还需要安装ncurses这个库,安装完成之后,sudo ldconfig即可。

mysql安装完成之后,启动mysql,报如下错误:

Manager of pid-file quit without updating file.

Google之后,找到一个老外的提示,在新安装mysql的时候,需要执行mysql_install_db进行mysql插件的初始化。

 

总结:mysql一般的安装顺序是:

  1. ./configure –prefix=/usr/local/mysql
  2. make
  3. make install
  4. scripts/mysql_install_db
  5. 设定权限
  6. chown -R root  /usr/local/mysql
    chown -R mysql /usr/local/mysql/var
    chgrp -R mysql /usr/local/mysql

23 四 09 linux操作命令记录

删除大小为0的文件

find . -name "*" -type f -size 0c | xargs -n 1 rm -f

但是如果文件名有空格,则不能删除,但是可以将带空格的文件名改成没有空格,则就可以删除了。

命令如下:

for file in *;do mv "$file" "$(echo $file|tr -d ‘ ‘)";done

 

修改linux系统本地时间为东八区

cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

 

设定后台进程:

crontab -e
00 00 * * * /bin/bash  /var/xxx.sh

设定nginx自动切割日志:

#!/bin/bash
# This script run at 00:00

# The Nginx logs path
logs_path="/var/log/nginx/"

mkdir -p ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/
mv ${logs_path}localhost.access.log ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/localhost.access_$(date -d "yesterday" +"%Y%m%d").log
#kill -USR1 `cat /var/run/nginx.pid`
killall –s USR1 nginx

查看nginx状态,参考http://wiki.nginx.org//NginxChsStubStatusModule?highlight=(status)

location /nginx_status {
 # copied from http://blog.kovyrin.net/2006/04/29/monitoring-nginx-with-rrdtool/
 stub_status on;
 access_log   off;
 allow SOME.IP.ADD.RESS;
 deny all;
}

15 四 09 django admin界面处理

django的admin很强大,可以很方便管理后台数据。近期的一个网站需要处理一堆关联的数据,如果简单使用admin来管理,会碰到一些问题。

情形如下:有A和B两个model

class A(models.Model):
    …

class B(models.Model):
    a = models.ForeignKey(A)
    …

在admin界面中A比较好编辑,在数据量不多的时候,添加B也方便。但是如果A有了几千条数据,添加B的时候要从这么一堆A数据中选择一条,从可用性和系统性能方面来说都是是根本不可能的。于是django admin提供了raw_id_fields字段,ForeignKey字段使用了input编辑框,用户需要手工输入A对象的id即可,或者在弹出的对话框中对A对象集合进行筛选。

这样处理感觉不够方便,数据维护人员需要记住A的id,这很容易填错id。不希望让维护人员了解这些ID,所以就希望能够在A对象的列表界面加一个“添加B对象”字段,当点击这个字段的时候,即可调出B对象的添加界面,django admin支持这种自定义字段,在A对象中如下设置即可:

    def new-B(self):
        return u’<a href="/admin/xxapp/B/add/?a=%d">新建 B</a>’  %  self.id
    new-B.allow_tags = True

通过这种自定义的方式可以添加很多操作,链接会带到任何想执行的功能。

B对象的添加界面出来之后,不希望还要了解A对象的id,因为这是从一个A对象发起的添加操作。所以需要把A对象ID传到B的添加界面中。参数的传递只能通过GET进行了,考察了django.contrib.admin.options,他是支持GET参数的,于是就这样把A对象的ID细节给隐藏掉了。如果怕用户不小心修改了A对象的ID,则可以使用javascript将这个input编辑框给disable掉。

django admin支持添加css和javascript:如下例:

    class ArticleAdmin(admin.ModelAdmin):
        class Media:
            css = {
                "all": ("my_styles.css",)
            }
            js = ("my_code.js",)

B添加完成之后,还希望继续添加另外一个B,也是基于同样的A对象,点击“保存并增加另一个”,这时候GET信息丢失了,A对象ID没有了。第一反映是希望用javascript把“保存并增加另一个”的链接加上GET信息,查看了页面的源代码,是一个submit的操作,没有链接可以修改的。

input type="submit" value="保存并增加另一个" name="_addanother" /

还是到服务端来考察,在django.contrib.admin.options中查找_addanother,在response_add函数中针对_addanother进行了处理,于是事情就简单了,在B的ModelAdmin对象中重写response_add函数:

def response_add(self, request, obj, post_url_continue=’../%s/’):       
        if request.POST.has_key("_addanother"):
            from django.utils.translation import ugettext as _
            from django.utils.encoding import force_unicode
            from django.http import HttpResponseRedirect
            opts = obj._meta
            pk_value = obj._get_pk_val()           
            msg = _(’The %(name)s "%(obj)s" was added successfully.’) % {’name’: force_unicode(opts.verbose_name), ‘obj’: force_unicode(obj)}           
            self.message_user(request, msg + ‘ ‘ + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))

            #新增加代码,记录下GET的信息
            getinfos = request.GET.items()
            gets = ‘?’
            for info in getinfos:
                gets += ‘%s=%s&’ % (info[0],info[1])
            path = request.path + gets

            return HttpResponseRedirect(path)
        return super(admin.ModelAdmin, self).response_add(request,obj,post_url_continue)

这样GET信息就可以保存下来了。

查看了django的最新版本,GET信息还是没有保存,这个不应该,提了一个ticket上去。

08 四 09 python 图片处理

有一堆gif图片,需要处理,python有一个PIL库,处理起来很方便,但是转换的效果很有问题。如: 这一张透明的gif图片,使用简单的保存语句:

from PIL import Image

im = Image.open(’9.gif’)
transparency = im.info['transparency']
im.save(’output.gif’ ,transparency=transparency )

得出的output.gif为 ,多了一些乱七八糟的点。怀疑是我的windows系统环境有问题,然后拿到了ubuntu系统上测试,也是如此,不甘心,在ubuntu上下载了一个python 2.5.4,再下载了PIL的源码进行编译,现象依旧。然后再跑到国外的主机上进行测试,也是一样,不过转换出来的大小都不太一样,有几十个字节的差异。

在open之后,我立即打印了im的数据

print list(im.getdata())

按照正常的话,黑白gif应该只有0和1的点,但是发现下面有很多大于1的点:

[0, 0, 0, 0, 192, 48, 30, 30, 241, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 100, 0, 0, 90, 0, 0, 100, 1, 0, 100, 2, 0, 107, 1, 0, 90, 1, 0, 100, 1, 0, 100, 2, 0
, 107, 2, 0, 90, 2, 0, 100, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 0, 104, 0, 0, 4, 100, 0, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, 2, 100, 6, 0, 60, 0, 0, 0, 0, 1, 0, 0, 0, 1, 4,
100, 9, 0, 2, 100, 10, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 60, 4, 100, 13, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 100, 15, 0, 60, 90, 4, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 100,
17, 0, 101, 3, 0, 105, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 131, 0, 0, 89, 90, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7, 0, 101, 2, 0, 105, 8, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 13
1, 3, 0, 1, 101, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 131, 2, 0, 1, 101, 2, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 131, 2, 0, 1, 101, 2, 0, 105, 10, 0, 100, 20, 0, 100, 22,
0, 131, 2, 0, 1, 101, 2, 0, 105, 10, 0, 100, 20, 0, 100, 23, 0, 131, 2, 0, 1, 100, 2, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

尝试将大于1的点清0,再putdata回去,结果是干净了一点,但还有一些污点,可能本来是一些0的点被染成了1。

该gif图片的格式为GIF89a,转存之后为GIF87a。

我又尝试了一些非透明的gif,这样的转存没有问题。难道是PIL对透明gif处理有问题?google了很多文章,都没有发现什么解决方案或者类似的问题,老外写的文章PIL Tips: Converting Between PNG and GIF,倒是有很多例子,不过好像没有碰到我的这个问题。

————————————————————————

没辙了,看看有没有其他的图形库。发现了imagemagick。有python接口,提供了命令行工具。于是在ubuntu上用sudo apt-get install python-pythonmagick安装,下了一堆包,安装完成,在site-packages目录没有发现任何新东西,不知道给装到哪里去了。当然就无法import PythonMagick了。罢了,还是手工编译安装吧。

imagemagick很顺利的编译安装,听说python接口手工安装非常麻烦,也不用python接口了,直接使用命令行进行处理。看了大量的例子帮助,明白了一些基本用法,直接在命令行输入下列指令:

convert 9.gif output.gif

这回成功了,output.gif和9.gif图片一样的。但是在将png转换为gif的时候报错:

convert    gtk1.png  gtk1.gif
convert: no decode delegate for this image format

google了一下,应该是少了一些部件。需要到(http://www.imagemagick.org/download/delegates/)下载所缺少的库进行安装,之后imagemagick需要再重新configue ,make install.

06 四 09 上传文件的跨域处理

为了减轻主服务器的负担,希望把图片的处理单独拿出来,由图片服务器来处理图片上传,浏览等操作。图片上传使用了ajax方式,采用了ajaxfileupload控件,它动态生成了一个iframe,由iframe来接受上传结果。以前的操作都在www.***.com上处理,这个控件用得不错,分开之后,由img.***.com来负责上传,结果问题就来了,iframe的contentWindow以及contentDocument下面的document拒绝访问。google之后,发现应该是跨域问题,按照道理来说,两个子域的跨域应该很好解决。无非是设置document.domain,主页面中如下设置:

<script language="text/javascript">
    document.domain = "***.com";
</script>

在iframe中的onload事件函数中,也设置了document.domain = "***.com";测试了一下,行不通,还是会报“拒绝访问”,虽然Firebug已经看到了返回值。对javascript不是很熟悉,不知道iframe中这样设置document.domain是否合法。

然后再google了一堆资料,针对跨域的处理有很多方式:jquery的jsonp技术,动态地添加一个<script>标签,因为script标签的src属性是没有跨域的限制,但是好像只能get,不支持post。还有通过服务器中转,数据先到达www.***.com,由www服务器发送到img服务器进行处理,这样也没有问题,但是数据绕了一圈,费时费力。

这个时候想起了nginx的代理设置,是否能够将www服务器的目录映射成img服务器呢?我想应该可以的,那就尝试一下。

首先给ubuntu装上dns服务器,可以模拟这些域名进行测试。然后配置nginx如下:

upstream hosts_www_com {
    server 192.168.1.2:80;
}
server {
    listen       80;
    server_name  www.***.com;

    access_log  /var/log/nginx/***.host.access.log;   

    location ~ ^/imgupload/ {
        proxy_pass        http://192.168.1.129;  #图片服务器的ip
        proxy_set_header  X-Real-IP  $remote_addr;

        proxy_redirect off;

    }

    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_pass http://hosts_www_com;
        proxy_set_header  x-real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}

然后再测试一下,OK了。

27 三 09 nginx 配置

如果需要配置反向代理,则nginx编译的时候需要有–with-http_realip_module参数,于是重新配置编译了一下,这次把大部分参数都加上了

./configure –conf-path=/etc/nginx/nginx.conf –error-log-path=/var/log/nginx/error.log –pid-path=/var/run/nginx.pid –lock-path=/var/lock/nginx.lock –http-log-path=/var/log/nginx/access.log –http-client-body-temp-path=/var/lib/nginx/body –http-proxy-temp-path=/var/lib/nginx/proxy –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –prefix=/usr –with-http_stub_status_module –with-http_realip_module –with-http_dav_module –with-http_flv_module –with-http_sub_module –with-http_addition_module

反向代理配置参数如下:

upstream hosts_xxx_com {
server www.destsite.com:80;
}
server {
listen       80;
server_name  www.xxx.com;

access_log  /var/log/nginx/xxx.host.access.log;

location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://hosts_xxx_com; #这个可以取任意名字,和upstream的名字相同即可
proxy_set_header  x-real-IP  $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

有时候需要需要保护一些目录,限制某些ip访问,可以如下设置:

location ^~ / {
allow   127.0.0.1;
allow   192.168.1.2;#服务器ip
deny    all;
}

如果需要禁止整个域名的访问,可以设置在server中:

allow   192.168.1.2;#自已电脑的ip
deny    all;

可以把限制ip单独弄出一个文件deny.conf,在nginx.conf中include deny.conf;。如果需要动态添加一些限制ip,则可以修改这个deny.conf文件,修改完成之后,通过信号告诉nginx,限制就生效了。

防盗链设置:使用别名配置

location /res/ {
alias   /opt/Src/;
valid_referers none blocked server_names *.xxx.com ;
if ($invalid_referer) {
return 403;
}
}

nginx的信号如下:转摘自常用的 Nginx 参数和控制

通过信号对 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 重新加载配置。