FEEDS
RSS
Atom

使用telnet或SSH远程登录linux时,如果连接非正常中断,重新连接时,系统将开一个新的session,无法恢复原来的session。screen命令可以解决这个问题。

Screen工具是一个终端多路转接器,在本质上,这意味着你能够使用一个单一的终端窗口运行多终端的应用。

基本命令:

开一个会话,并命名为temp:

screen -S temp

临时退出这个会话:

ctrl-a d

再次进入名为temp的会话:

screen -r temp

检查正在运行的会话:

screen -ls

近一个月,本本一起处于半死状态,今天我直接让它死了一回算了,重装了系统,还好重要信息都备份了,以前开个机,要么十几分钟,要么几十次也开不了,运气好的时候还能打开一次。

安装了新的Lion 之后,也不知道是不是自己的配置跟不上了,有钱了再升级硬件吧,今天装完Lion之后,PS 无法运行,今天才知道,Adobe的软件还需要 Java Runtime,也是今天才知道, Lion 默认是不安装 Java Runtime 的,记录一下:

http://support.apple.com/kb/dl1421

上面链接是关于这个Lion 默认不安装 Java Runtime 问题的。

2012年啊

2011年,从我走出大学为止,工作时间最长的一份工作,就是在长沙管仓库,没有想到我从一个理科出生的人大学里面跳到英语专业,也不有想到最后自学整一以计算机行业,更没有想到,以前所学的所有东西,自己会一转眼就全部丢掉转而来长沙看仓库……2010年至2011年,两年的时间,我换了两个大行业,准确的说是,完全不相干的两个行业。

而现在在服装这一块也差不多稳定了,女儿也快满百日了,家有了,该立业了,只是这条路还不太清楚该怎么走啊……

只接上函数了:

#!/usr/bin/env python
# encoding: utf-8
"""
File: utility.py
Created by Pan Tao on 2011-11-20.
Copyright (c) 2011 CosTony.Com. All rights reserved.
"""
import sys
import os
def load_module(name, path = None):
    '''Load Python modules dynamic via module name. Using this function, you can
    load module like this:
        mod = load_module('modulename')
    for this usage, you will get a module which named 'modulename' and rename it
    as mod. This function is very useful for configuration of INSTALLED_MODULES.
    You can create an INSTALLED_MODULES dictionary, and load installed modules 
    dynamic.
    :param name: the module name string
    :param path: where the module stored, set to None when the module path is in
        sys.path.
    :return:
        python module: if there is a module can be found in sys.path
        None: Nothing found    
    '''
    if sys.modules.has_key(name): #if there is a module named 'name value'
        del sys.modules[name] # delete the exist module
    if path: #if there is a customized path
        if os.path.isabs(path): #If this path is an absolute path
            sys.path.insert(0, path)
        else: #or is not an absolute path
            sys.path.insert(0, os.path.abspath(path)) #find this path's absolute path
    return __import__(name)

在Flask中上传文件

上传文件的最简单的一个解决方案其实确实很简单,就下面这几个步骤:

  1. 一个被标记为 enctype="multipart/form-data" 且包含一个 <input type="file| /> 标签的表单( <form> )。
  2. 程序可以从 request.files 中直接访问已上传的文件。
  3. 通过 save() 函数将已上传的文件从临时文件存放位置移动到我们希望它存放的位置。

简单的开始

让我们从一个最简单的上传文件的应用来始,在这个应用中,用户上传的文件会被存放在一个特别的文件目录中,显示会显示该文件给用户,先让我们看看整个应用的引导程序:

import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['txt','pdf','png','jpg','jpeg','gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

最开始我们需要导入一些应用中用到的模块或函数,上面导入的大多数模块和函数我们以前也都见过了,只是这个 werkzeug.secure_filename() 函数我将在稍后再详细的说明一下,在上面的代码段中, UPLOAD_FOLDER 指定了我们文件上传之后在服务器上的存放位置, ALLOWED_EXTENSIONS 则指定了允许上传的文件类型,但是你可以看到我并没有什么 一个URL规则来指定如何访问文件,因为在通常情况,使用服务器软件来服务这些软件比我们用程序发送效率更高,我们只需要在程序里面指定文件的URL路径即可。

至于为什么我们会限定上传的文件类型,这个原因很简单吧,你总不会想让你的用户可以存放任何文件到你的服务器上吧?如果你允许用户上传任何类型文件,那么这之间的风险将很大,比如他们可以上传一个可执行的脚本到你的服务器上,而如果这个脚本还正好处于一个可执行的目录中的话,那么肯定是很不安全的了。

接下面我们将来检查上传至服务器的文件的格式,如果文件允许被上传,那么我们会指定将用户页面转向至刚刚上传的文件上。

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS
@app.route('/', methods = ['GET','POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('uploaded_file', filename = filename))
    return '''
    <!DOCTYPE html>
    <title>Upload New File</title>
    <h1>Upload File</h1>
    <form action="/" method="POST" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" value="Upload" />
    </form>
    '''

一些给专家们的建议

在上面的代码中, secure_filename() 到底做了什么呢?我们先从一个最觉提起的问题上来说:“永远不要相信用户的输入”,你就想象一下,如果某一个用户上传了有下面这样文件名的文件至你的服务器:

filename = "../../../../home/username/.bashrc"

然后再想象一下,如果 ../ 的个数正好,那么,将这个文件名的文件与你的上传路径合并之后,他将有可能修改你的服务器的文件,当然,这种情况很少能出现,而且一般的用户也很少会恶意的去这么做,但是相信我,专门这样做的黑客如果想要黑你,那么他一定会想尽办法这么去做,所以,还是那句话:“永远不要相信任何用户的输入”。

我们从Python命令行中来看一下下这个函数是如何工作的:

>>> secure_filename('../../../../home/username/.hashrc')
'home_username_.bashrc'

现在只剩下最后一件事情了,将用户上传的文件发送给用户查看,在 Flask 0.5 版本中,我们可以使用下面这样函数来做这件事情:

from flask import send_from_directory
@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

另外,你还可以将 uploaded_file 注册成为 build_only ,同时使用共享数据中间介(SharedDataMiddleware),在老版本的Flask也同样适用:

from werkzeug import ShareDataMiddleware
app.add_url_rule('/uploads/<filename>', 'uploaded_file', build_only = True)
app.wsgi_app = ShareDataMiddleware(app.wsgi_app, {'uploads': app.config['UPLOAD_FOLDER'] })

现在你运行你的程序,应该是可以实现文件上传,检测文件类型以及文件名,输出文件给用户查看的所有功能了。

更加高级的文件上传

那么Flask到底是怎么样处理文件上传的呢?是这样的,当用户上传文件至服务器时,如果文件小的话(这个在不同系统上面是不一样的量),Flask会将其保存在内存中,或者如果文件很大的话,会被保存到一个临时文件中(可以使用 tempfile.gettempdir()获取到),默认情况下,只要服务器内存允许,Flask不会管用户上传的文件有多大,但是我们很多时候并不希望这样,这时,我们可以使用通过设置 appMAX_CONTENT_LENGTH 参数来限定用户上传的文件最大大小:

from flask import Flask, Request
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

上面的设置将限定用户最大只允许上传不超过 16Mb的文件,如果用户上传的文件过大,刚Flask会抛出一个 RequestEntityTooLarge 异常。

#!/usr/bin/env python
# encoding: utf-8
"""
File: prime_list.py
Created by Pan Tao on 2011-11-16.
Copyright (c) 2011 CosTony.Com. All rights reserved.
"""
prime_list = lambda n: set([i for i in range(2,n)]) ^ set([i for i in range(2,n) for x in range(2,int(i**0.5)+1) if i%x == 0])
def main():
	print(prime_list(int(raw_input('Enter the max number:'))))
if __name__ == '__main__':
	main()

不要看上面有那么多行字符哈,其实就 prime_list = lambda: .... 这一行就行了,如果你对质数感兴趣,也可以去看看我以前写的一个专门用来求质数的程序,见这里: Python 验证与获得素数(via Miller Rabin & AKS)

Drupal开发者的心智模式

刚才逛 Drupal Groups 的时候看到的这篇文章 Core Context UX: Page & Component library 不过让我想印象最深的就是下面这张图了:

Drupal Developers Mental Model

最近在开发一个Drupal站,发现Drupal 7 比Drupal 6还是方便了不少,哦,不是不少,而是方便了不知多少,最开始这个网站还是准备自己写程序的,因为自己写也没有很多代码量,但是客户要求了,用Drupal的话以后他们自己好升级维护,所以,还是Drupal了。

主题功能设定

IBM的官方网站其实也就以内容发布为主,带有一些简单的社交功能,其主页最主要是一个大的Slideshow,这个是我最喜欢的,还有就是他的导航条,是一个渐变的,导航条会跟随页面的滚动而变换高度,这个就算是响应式设计吧。

我自己的这个主题也没有计划弄这个,因为时间只有这么长,我是想页面的样子一定要像,另外我还会结合一下下 Apple 网站的一些细节设计(所谓的四不像不要出来了?),Slideshow是准备使用Views实现,这样的话可以更加方便的使用。

准备使用的模块

主题会允许仅仅使用系统模块的前提下运行,但是可能功能上面会少一些,如果要更强大和灵活的功能,我还是准备使用一些模块,比如下面这些:

Views

这个不可能不使用,太强大了,对于我这种不太喜欢写代码的人来说,这个是必须有的,用了它之后,包注百病。

Quicktabs

整站所有的标签区块就靠这个东西了,简单,方便实用。

jQuery Plugin

这个是一些JS效果的模块需要的,不安装也不行,唉。

界面相关的就这些了吧,另外我还会对使用其它模块提供一些建议和优化,争取能达到任何初级用户都可以直接下载,安装配置的地步,不过最终能不能达到,那是另外一回事儿哈。

另外,对于我等小人,IBM应该不会追究什么版权的吧?

IBM - 中国 - 首页

最近的一个Drupal项目中,要用到Drupal 7 的Image Style(也没有哪个项目不用这个东西吧?),以前一直都是使用 Apache服务器,还没出现什么问题,原因可能是因为Drupal默认就对Apache有更好的支持吧,在 .htaccess 文件中可能已经提供了规则,但是在Nginx中,因为并不是原生的Rewrite Rule,所以还是会出现问题的。

Drupal 7 中的Image Styles可以让我们上传一张图片,在不同的地方得到各种各样不同大小和效果的图片,它可以对图片进行去色,翻转,改变大小,裁切等各种基本操作,但是前提是,我们需要通过 Drupal 去访问这些图片,而不是直接访问图片在服务器上的URL地址,比如:http://www.lorecore.net/media/default/images/2011-11/1.jpg 这样图片,如果我想在想要调用它的 large 样式的复本,那么通过 Image Style的地址应该是下面这样的:

http://www.lorecore.net/media/default/images/styles/large/public/images/2011-11/1.jpg

这样访问在Apache中应该是没有问题,但是在Nginx中,可能根本就访问不到,我也是整了一整天,最后发现一个问题,在我的MAMP 里面,在处理这种图片的时候,PHP会产生Error,但是在我的VPS上面,却没有这个Error,当我把MAMP中的问题处理完了之后,Image Style可以正常工作了,但是在VPS上面,因为没有产生Error,那么很有可能就是:访问Image Style处理之后的图片,必须经过 Drupal ,而不能直接从服务器上下载。

这是因为Drupal的Image Style访问的图片会将起重写到 /?q=/media/default…. 这样的地址,而并不是直接让Apache来返回的,而Nginx因为没有相关的Rewrite Rule,所以并没有将静态文件的访问转到 Drupal 上,要修复 Drupal 在Nginx上面的这个问题,我们只需要让访问Image Style的Cache目录的图片的时候,都将其Rewrite到Drupal上即可,在Nginx的配置文件中加入如下代码:

location ^~ /media/default/styles/ {
    index  index.php index.html;
    if (!-e $request_filename) {
        rewrite  ^/(.*)$  /index.php?q=$1  last;
        break;
    }
}

上面的代码,可以让对 /media/default/styles/ 这个目录下所有文件的请求都Rewrite到 /?q=/media/default/styles/.. 上,在你的项目中,需要将 “/media/default/styles/” 修改成为你自己的 Styles Image Cache 目录,比如如果你使用的是Drupal默认的文件路径,那么应该是 “/sites/default/files/styles/”。

创建多栏"等高"布局的一个想法

我们经常会需要创建一个这样的布局,分左,中,右三栏(或者左右两栏,其实本质上是一样的),使用的最多的办法注是使用一张背景图片,来创建这样一种伪等高的效果,不过这样一来,其实有一个问题存在的,那就是如果我中间部分的内容需要宽一些,那么这张图片就得重新制作一次。

本文向大家介绍一个更好的办法,不使用一张图片,而且十分简单易用,并且所有分栏的位置可随意调整,宽度可随意更改,并且,它们永远都是“等高”的,要创建这样一种布局,我们得使用负外边距的方式来布局,负外边距的核心其实很简单,让所有分栏都向左,或者向右浮动(所有的都必须向一个方向浮动),并且,把主内容区域写在文档流的最前面,比如下面这样的:

<div class="columns">
    <div class="main"><div class="inner">位于正中间的主内容栏</div></div>
    <div class="sub">次级分栏</div>
    <div class="extra">扩展分栏</div>
</div>

在上面的这种结构中,Columns用来创建一个分栏的容器,它中间的三个容器则是分栏的容器(其实不止是三个,对于任何栏数都可以使用负外边距的方式创建),请注意,主分栏是由两个容器嵌套而成的,这个是必须这样做的,然后我们将所有元素都浮动(为了所有古老的浏览器里面都能不出问题,可能需要给 columns 这个容器指定一个宽度,我一般就使用 100%,整个布局的代码如下:

.columns {
    width: 100%;
}
.main, .sub, .extra {
    float: left;
}
.main {
    width: 100%;
}
.main .inner {
    margin: 0 20%;
}
.sub {
    width: 20%;
    margin-left: -100%;
}
.extra {
    width: 20%;
    margin-left;
}

这样就已经形成了三栏布局了,但是回到最上面所说的,我们需要让这三栏看起来是等高的,我们平常的做法是给Body(或者.columns,.main 等具有100%宽度的任何容器都行)加一个背景,背景图片要做得正和这三栏宽度一样,然后垂直平铺即可。

但是这种用图片的方式带来的问题还是很多的,就像上面说的,而且它没法在其它布局中使用,比如我现在想让主内容栏宽度增减一些就必须使用另一张图片,所以这里我们有一个小技巧,就是把 .main .innermargin 修改为0,然后使用边框的方式来将其内容区域压缩到中心位置,即上面代码改为:

.columns {
    overflow: hidden;
    width: 800px;
    margin: 1em auto;
}
.main, .sub, .extra {
    float: left;
}
.main {
    width: 100%;
}
.main .inner {
    border-left: 180px solid #f0f0f0;
    border-right: 180px solid #f0f0f0;
}
.sub, .extra {
    width: 180px;
}
.sub {
    margin-left: -100%;
}
.extra {
    margin-left: -180px;
}

这样一来,.sub 和 .extra 都还是在原来的位置,但是 .main .inner 却会在两个边框的下面画出与其高度一致的边框来,这个边框就可以作为边栏的背景,实现“伪等高”,而且我们要将右边栏去掉的话,只需要将 .main .inner 的右边框大小改为 0 即可,方便实用,不过有一个问题就是,似乎浏览器不能使用 百分比的形式表示边框大小,所以,在这种解决办法中,不能实现三栏同时自增减,只有中间的主分栏有这样的特权。

大家可以在去乐酷实验室查看该方式的实际效果:http://labs.lorecore.com/demos/html/columns-via-border.html

- Older Posts »