Thursday, April 30, 2009

Linux|screen使用方法命令和解释

[求助]真心求screen使用方法! [论坛存档] - LinuxSir.Org

以下是命令和解释。
运行:
screen

Ctrl-a S 新建水平分割窗口
Ctrl-a Tab 切换窗口
Ctrl-a :screen bash 新建 screen 终端,并运行 bash
Ctrl-a :quit 退出 screen,将关闭所有 screen 终端,结束其中所有任务



screen 常用命令,

Ctrl-a c 新建 bash screen 终端
Ctrl-a " 列出
Ctrl-a A 重命名
Ctrl-a n 在当前窗口中切换到下一个 screen 终端
Ctrl-a p 在当前窗口中切换到上一个 screen 终端

Ctrl-a d 断开所有 screen 终端,返回 screen 执行前状态,但 screen 内所有终端的任务都在执行
screen -ls 列出当前用户的所有 screen 实例,包括联接和断开的
screen -R <pid> 重新联接到已断开的 screen 实例,如果有多个已断开的 screen 实例,则用 <pid> 区分

Ctrl-a S 新建水平分割窗口
Ctrl-a Tab 切换窗口
Ctrl-a X 关闭当前窗口
Ctrl-a + 扩大当前窗口,默认增加3行
Ctrl-a - 缩小当前窗口,默认减小3行

Ctrl-a :screen <command> 新建 screen 终端,并运行命令<command>
Ctrl-a :resize <height> 改变当前窗口高度为<height>
Ctrl-a :quit 退出 screen,将关闭所有 screen 终端,结束其中所有任务

Ctrl-a <Esc> 进入选择模式
<PageUp> 或 Ctrl-u 光标上移一页
<PageDown> 或 Ctrl-d 光标下移一页
<Left> 或 h 光标左移一格
<Down> 或 j 光标下移一行
<Up> 或 k 光标上移一行
<Right> 或 l 光标右移一格
<Space> 选择开始,选择结束
<Esc> 退出选择模式

Ctrl-a ] 粘贴选择的内容

Linux 技巧:使用 screen 管理你的远程会话

linux 技巧:使用 screen 管理你的远程会话

linux 技巧:使用 screen 管理你的远程会话

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 中级

田 强 (tianq@cn.ibm.com), 软件工程师, IBM中国软件开发中心

2007 年 7 月 31 日

你是不是经常需要远程登录到Linux服务器?你是不是经常为一些长时间运行的任务头疼?还在用 nohup 吗?那么来看看 screen 吧,它会给你一个惊喜!

你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是不是经常为一些长时间运行的任务而头疼,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为他们执行的时间太长了。必须等待它执行完毕,在此期间可不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

元凶:SIGHUP 信号

让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。

在Linux/Unix中,有这样几个概念:

  • 进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
  • 会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
  • 会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。

根据POSIX.1定义:

  • 挂断信号(SIGHUP)默认的动作是终止程序。
  • 当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
  • 如果会话期首进程终止,则该信号发送到该会话期前台进程组。
  • 一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。

因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。

我们来看一个例子。打开两个SSH终端窗口,在其中一个运行top命令。

 [root@tivf09 root]# top

在另一个终端窗口,找到top的进程ID为5180,其父进程ID为5128,即登录shell。

 [root@tivf09 root]# ps -ef|grep top root      5180  5128  0 01:03 pts/0    00:00:02 top root      5857  3672  0 01:12 pts/2    00:00:00 grep top

使用pstree命令可以更清楚地看到这个关系:

 [root@tivf09 root]# pstree -H 5180|grep top |-sshd-+-sshd---bash---top             

使用ps-xj命令可以看到,登录shell(PID 5128)和top在同一个会话期,shell为会话期首进程,所在进程组PGID为5128,top所在进程组PGID为5180,为前台进程组。

 [root@tivf09 root]# ps -xj|grep 5128  5126  5128  5128  5128 pts/0     5180 S        0   0:00 -bash  5128  5180  5180  5128 pts/0     5180 S        0   0:50 top  3672 18095 18094  3672 pts/2    18094 S        0   0:00 grep 5128

关闭第一个SSH窗口,在另一个窗口中可以看到top也被杀掉了。

 [root@tivf09 root]# ps -ef|grep 5128 root     18699  3672  0 04:35 pts/2    00:00:00 grep 5128

如果我们可以忽略SIGHUP信号,关掉窗口应该就不会影响程序的运行了。nohup命令可以达到这个目的,如果程序的标准输出/标准错误是终端,nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令只是使得程序忽略SIGHUP信号,还需要使用标记&把它放在后台运行。

 nohup <command> [argument…] &

虽然nohup很容易使用,但还是比较“简陋”的,对于简单的命令能够应付过来,对于复杂的需要人机交互的任务就麻烦了。

其实我们可以使用一个更为强大的实用程序screen。流行的Linux发行版(例如Red Hat Enterprise Linux 4)通常会自带screen实用程序,如果没有的话,可以从GNU screen的官方网站下载。

 [root@tivf06 ~]# rpm -qa|grep screen xscreensaver-4.18-5.rhel4.11 screen-4.0.2-5             

开始使用Screen

简单来说,Screen是一个可以在多个进程之间多路复用一个物理终端的窗口管理器。Screen中有会话的概念,用户可以在一个screen会话中创建多个screen窗口,在每一个screen窗口中就像操作一个真实的telnet/SSH连接窗口那样。在screen中创建一个新的窗口有这样几种方式:

1.直接在命令行键入screen命令

 [root@tivf06 ~]# screen

Screen将创建一个执行shell的全屏窗口。你可以执行任意shell程序,就像在ssh窗口中那样。在该窗口中键入exit退出该窗口,如果这是该screen会话的唯一窗口,该screen会话退出,否则screen自动切换到前一个窗口。

2.Screen命令后跟你要执行的程序。

 [root@tivf06 ~]# screen vi test.c

Screen创建一个执行vi test.c的单窗口会话,退出vi将退出该窗口/会话。

3.以上两种方式都创建新的screen会话。我们还可以在一个已有screen会话中创建新的窗口。在当前screen窗口中键入C-a c,即Ctrl键+a键,之后再按下c键,screen 在该会话内生成一个新的窗口并切换到该窗口。

screen还有更高级的功能。你可以不中断screen窗口中程序的运行而暂时断开(detach)screen会话,并在随后时间重新连接(attach)该会话,重新控制各窗口中运行的程序。例如,我们打开一个screen窗口编辑/tmp/abc文件:

 [root@tivf06 ~]# screen vi /tmp/abc

之后我们想暂时退出做点别的事情,比如出去散散步,那么在screen窗口键入C-a d,Screen会给出detached提示:


暂时中断会话
暂时中断会话

半个小时之后回来了,找到该screen会话:

 [root@tivf06 ~]# screen -ls There is a screen on:         16582.pts-1.tivf06      (Detached) 1 Socket in /tmp/screens/S-root.

重新连接会话:

 [root@tivf06 ~]# screen -r 16582

看看出现什么了,太棒了,一切都在。继续干吧。

你可能注意到给screen发送命令使用了特殊的键组合C-a。这是因为我们在键盘上键入的信息是直接发送给当前screen窗口,必须用其他方式向screen窗口管理器发出命令,默认情况下,screen接收以C-a开始的命令。这种命令形式在screen中叫做键绑定(key binding),C-a叫做命令字符(command character)。

可以通过C-a ?来查看所有的键绑定,常用的键绑定有:


C-a ?显示所有键绑定信息
C-a w显示所有窗口列表
C-a C-a切换到之前显示的窗口
C-a c创建一个新的运行shell的窗口并切换到该窗口
C-a n切换到下一个窗口
C-a p切换到前一个窗口(与C-a n相对)
C-a 0..9切换到窗口0..9
C-a a发送 C-a到当前窗口
C-a d暂时断开screen会话
C-a k杀掉当前窗口
C-a [进入拷贝/回滚模式

Screen常用选项

使用键绑定C-a ?命令可以看到, 默认的命令字符(Command key)为C-a,转义C-a(literal ^a)的字符为a:


Screen 常用选项
Screen 常用选项

因为screen把C-a看作是screen命令的开始,所以如果你想要screen窗口接收到C-a字符,就要输入C-a a。Screen也允许你使用-e选项设置自己的命令字符和转义字符,其格式为:

-exy x为命令字符,y为转义命令字符的字符

下面命令启动的screen会话指定了命令字符为C-t,转义C-t的字符为t,通过C-t ?命令可以看到该变化。

 [root@tivf18 root]# screen -e^tt


自定义命令字符和转义字符
自定义命令字符和转义字符

其他常用的命令选项有:


-c file使用配置文件file,而不使用默认的$HOME/.screenrc
-d|-D [pid.tty.host]不开启新的screen会话,而是断开其他正在运行的screen会话
-h num指定历史回滚缓冲区大小为num行
-list|-ls列出现有screen会话,格式为pid.tty.host
-d -m启动一个开始就处于断开模式的会话
-r sessionowner/ [pid.tty.host]重新连接一个断开的会话。多用户模式下连接到其他用户screen会话需要指定sessionowner,需要setuid-root权限
-S sessionname创建screen会话时为会话指定一个名字
-v显示screen版本信息
-wipe [match]同-list,但删掉那些无法连接的会话

下例显示当前有两个处于detached状态的screen会话,你可以使用screen -r <screen_pid>重新连接上:

 [root@tivf18 root]# screen –ls There are screens on:         8736.pts-1.tivf18       (Detached)         8462.pts-0.tivf18       (Detached) 2 Sockets in /root/.screen.  [root@tivf18 root]# screen –r 8736

如果由于某种原因其中一个会话死掉了(例如人为杀掉该会话),这时screen -list会显示该会话为dead状态。使用screen -wipe命令清除该会话:

 [root@tivf18 root]# kill -9 8462 [root@tivf18 root]# screen -ls   There are screens on:         8736.pts-1.tivf18       (Detached)         8462.pts-0.tivf18       (Dead ???) Remove dead screens with 'screen -wipe'. 2 Sockets in /root/.screen.  [root@tivf18 root]# screen -wipe There are screens on:         8736.pts-1.tivf18       (Detached)         8462.pts-0.tivf18       (Removed) 1 socket wiped out. 1 Socket in /root/.screen.  [root@tivf18 root]# screen -ls   There is a screen on:         8736.pts-1.tivf18       (Detached) 1 Socket in /root/.screen.  [root@tivf18 root]#

-d –m 选项是一对很有意思的搭档。他们启动一个开始就处于断开模式的会话。你可以在随后需要的时候连接上该会话。有时候这是一个很有用的功能,比如我们可以使用它调试后台程序。该选项一个更常用的搭配是:-dmS sessionname

启动一个初始状态断开的screen会话:

 [root@tivf06 tianq]# screen -dmS mygdb gdb execlp_test

连接该会话:

 [root@tivf06 tianq]# screen -r mygdb

管理你的远程会话

先来看看如何使用screen解决SIGHUP问题,比如现在我们要ftp传输一个大文件。如果按老的办法,SSH登录到系统,直接ftp命令开始传输,之后。。如果网络速度还可以,恭喜你,不用等太长时间了;如果网络不好,老老实实等着吧,只能传输完毕再断开SSH连接了。让我们使用screen来试试。

SSH登录到系统,在命令行键入screen。

 [root@tivf18 root]# screen

在screen shell窗口中输入ftp命令,登录,开始传输。不愿意等了?OK,在窗口中键入C-a d:


管理你的远程会话
管理你的远程会话

然后。。退出SSH登录?随你怎样,只要别杀掉screen会话。

是不是很方便?更进一步,其实我们可以利用screen这种功能来管理你的远程会话,保存你所有的工作内容。你是不是每次登录到系统都要开很多窗口,然后每天都要重复打开关闭这些窗口?让screen来帮你“保存”吧,你只需要打开一个ssh窗口,创建需要的screen窗口,退出的时候C-a d“保存”你的工作,下次登录后直接screen -r <screen_pid>就可以了。

最好能给每个窗口起一个名字,这样好记些。使用C-a A给窗口起名字。使用C-a w可以看到这些窗口名字,可能名字出现的位置不同。使用putty:


putty
putty

使用telnet:


telnet
telnet

更多Screen功能

Screen提供了丰富强大的定制功能。你可以在Screen的默认两级配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如设定screen选项,定制绑定键,设定screen会话自启动窗口,启用多用户模式,定制用户访问权限控制等等。如果你愿意的话,也可以自己指定screen配置文件。

以多用户功能为例,screen默认是以单用户模式运行的,你需要在配置文件中指定multiuser on 来打开多用户模式,通过acl*(acladd,acldel,aclchg...)命令,你可以灵活配置其他用户访问你的screen会话。更多配置文件内容请参考screen的man页。

参考资料

Tuesday, April 28, 2009

Django|reverse函数

python BlogSpot: django reverse函数

Wednesday

django reverse函数

在0.96版中新加入了django.core.urlresolvers.reverse
reverse()是干什么的?反解析url以直接访问其它视图方法

在django的mvc(mvt也可以)中,url和view是通过url.py和views.py实现分离的,具体view的访问是通过url.py中设置的对应方法来实现的。

有一个view最后实现页面跳转:

views.py
def redirect(request):
return HttpResponseRedirect("/vote/1/")

url.py
(r'^/vote/(?P\d+)/$','mysite.poll.vote')

这样做起来就有1个问题:如果未来某天我们的url发生了改变,我们将不得不同时修改这两个文件。这和DRY哲学思想是冲突的,
---------
那么有什么办法能让我们只用修改url.py呢,答案就是使用reverse().
reverse的用例如下:

views.py

from django.core.urlresolvers import reverse

def redirect(request):
return HttpResponseRedirect(reverse('mysite.polls.views.detail',args=(1,)))

很容易明白,第一个参数就直接添入要使用的view方法,第二个args里边顺序填入方法的参数,(extra_context也从这里传入)然后剩下的就全部交给django去完成拉。
...

Sunday, April 26, 2009

Django|Debugging Django

Debugging Django

Debugging Django

I gave a talk on Debugging Django applications at Monday's inaugural meeting of DJUGL, the London Django Users Group. I wanted to talk about something that wasn't particularly well documented elsewhere, so I pitched the talk as "Bug Driven Development"—what happens when Test Driven Development goes the way of this unfortunate pony.

The slides are up on SlideShare, but don't provide quite enough context so I'm going to cover the tips in full here.

Making the most of the error page

Django's default error page is great—it provides a detailed traceback with local variables, lets you expand out the lines of code around the problem, provides a plain text exception suitable for e-mailing to colleagues and even a one-click button to send details to http://dpaste.com/ so you can go and talk about the error on IRC. It also serves the same purpose as phpinfo()—it shows you your application's settings, the GET, POST and COOKIE data from the request and the all important META fields assembled from the HTTP environment (great for remembering how to miss-spell HTTP_REFERER).

Useful tip number one is that you can trigger the error page from any view just by adding the following line:

assert False

You can serve up an expression with the assertion as well; it will be displayed at the top of the error page:

assert False, request.GET

One particularly useful place to use this is when you are building a complex form. If you want to see the data that was submitted, drop an assert False in to the view that the form targets and use the error page to inspect the data.

Logging to the development server console

If you want to know what's going on inside a view, the quickest way is to drop in a print statement. The development server outputs any print statements directly to the terminal; it's the server-side alternative to a JavaScript alert().

If you want to be a bit more sophisticated with your logging, it's worth turning to Python's logging module (part of the standard library). You can configure it in your settings.py:

import logging logging.basicConfig(     level = logging.DEBUG,     format = '%(asctime)s %(levelname)s %(message)s', )

Then call it from any of your views:

def my_view(request):     import logging     logging.debug("A log message")     ...

Again, this will log things to the terminal where the development server is running. If you want to log things to a file you can do so by extending the basicConfig call:

logging.basicConfig(     level = logging.DEBUG,     format = '%(asctime)s %(levelname)s %(message)s',     filename = '/tmp/myapp.log',     filemode = 'w' )

You can then use tail -f /tmp/myapp.log to see log lines being appended to that file in real-time. This can be used in production as well as development.

The above just scratches the surface of Python's logging module; with a bit of digging around in the documentation you can use it to rotate log files, send log messages over the network and even POST log events to an HTTP server somewhere.

Often you find yourself dealing with an error that only occurs in certain circumstances—a function might be called from dozens of different places in your program but only runs in to trouble in a very specific case. You can use the traceback module to log the current stack, which will allow you to tell how a function was called when something went wrong:

import logging, traceback, pprint  def my_buggy_function(arg):     ...     if error_condition:         stack = pprint.pformat(traceback.extract_stack())         logging.debug('An error occurred: %s' % stack)

The tuple returned by traceback.extract_stack() includes line numbers, function names and paths to Python files so you can use it to reconstruct a good amount of information about your program.

Using the debugger

By far the most powerful weapon in my debugging toolkit is the Python debugger, pdb. Again, this ships with the standard library so there's nothing extra to install. pdb is a command line debugger (if you want a GUI options include PyEclipse and Komodo, but I haven't used either myself). There are a bunch of ways to activate pdb, but the most straight forward is to simply drop the following line directly in to a Django view function:

import pdb; pdb.set_trace()

If you try to load that page in your browser, the browser will hang—the page will appear to be loading extremely slowly. What's actually happened is the developer server has paused execution and thrown up the pdb interface—you can switch over to your console and start interacting directly with the server mid view.

Did I mention you should never, ever leave this on in production?

So, you've got a hung development server and a pdb prompt. What can you do with it? The answer is pretty much anything. I won't provide a full pdb tutorial here (this is a good introduction), but the commands I find most useful are the following:

list
Shows the lines of source code around your current point of execution. You can run it multiple times to increase the amount of source code displayed.
n
Execute the next line
s
Same as n, but steps in to any functions that are called. You can quickly get lost in a twisty maze of code with this command, but that's OK because...
r
Continues execution until the current function returns
u
Goes UP one level in the stack—so you can see the function that called the function you are currently in
d
Goes DOWN again
locals()
not a pdb command, but handy for seeing what's in your current scope

The pdb docs have a full list of commands.

The pdb prompt doubles up as a full Python interactive shell, so you can not only access variables but you can modify them, call functions and generally mess around with the internals of your application as much as you like, while it's running. It's kind of a poor man's imitation of being a Smalltalk developer.

Remember though, the whole time you're messing around in pdb your browser is still stuck there, waiting for the HTTP request to come back. If you hit "c" (for continue) your application will kick in again, the request will be served and your browser will breathe a sigh of relief.

Thankfully you don't have to use pdb in a way that freezes your development server; it also works great in the interactive shell. If you've got a buggy function, one way to explore it is to run it interactively, then use the following idiom:

>>> def function_that_raises_an_exception(): ...   assert False ...  >>> function_that_raises_an_exception() Traceback (most recent call last):   File "<stdin>", line 1, in <module>   File "<stdin>", line 2, in function_that_raises_an_exception AssertionError >>> import pdb; pdb.pm() > <stdin>(2)function_that_raises_an_exception() (Pdb)

pdb.pm() stands for post-mortem, and is probably my favourite feature of the debugger—it lets you jump back in to debug the most recently raised exception, even if you hadn't imported pdb at the time the exception was raised.

One last pdb tip: you can use it to debug Python command line scripts such as Django's custom ./manage.py commands. The trick is to run the script like this:

python -i manage.py buggy_command

The -i argument causes Python to drop in to the interactive prompt after executing the script. If the script raised an exception, you can then use pdb.pm() to debug it.

Handling errors in production

Django's default behaviour in production (that is, when the DEBUG setting is set to False) is to e-mail exception reports to anyone listed in the ADMINS section. You can also turn on e-mail reports on every 404 error with the SEND_BROKEN_LINK_EMAILS setting, which will send them to addresses in the MANAGERS setting. As far as I know these settings don't do anything else—they're a pretty ancient bit of Django.

On a high traffic site you probably don't want to be e-mailed on every server error. One neat alternative is David Cramer's django-db-log, which logs exceptions to a database table. It cleverly uses an MD5 hash of the traceback to aggregate many reports of the same error. More importantly though, it acts as a really straight forward example of how to use Django middleware's process_exception hook to roll your own error reporting. Take a look at the code to see how simple this is.

More useful middleware

In the talk I demoed a couple of other handy pieces of middleware. The first was the ProfilerMiddleware (one of several profiling tools on Django Snippets) which allows you to add ?prof to the end of any URL to see the output of Python's cProfile module run against that request. The second is one that I've just released: DebugFooter, which adds a footer showing exactly which templates were loaded from where (handy for debugging complex template paths) as well as every executed SQL query and how long each one took.

Abusing the test client

A final tip for exploring your application interactively is to learn to use Django's TestClient. Although designed for use in unit tests, this tool is equally useful for use at the interactive prompt. It allows you to simulate an in-process request against your application from within your Python code. Here's an example:

>>> from django.test.client import Client >>> c = Client() >>> response = c.get("/") # The homepage >>> response <django.http.HttpResponse object at 0x2300470> >>> print response Vary: Cookie Content-Type: text/html; charset=utf-8  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"     "http://www.w3.org/TR/html4/strict.dtd"> <html> ...

The response object you get back is the HttpResponse returned by the view, ready to be explored interactively.

There's another function from the unit testing tools that can help with interactively exploring an application: setup_test_environment(). This function monkey-patches in some additional hooks used by the unit tests, including one that intercepts template render calls and adds information on them to the request object. Here's an example:

>>> from django.test.utils import setup_test_environment >>> setup_test_environment() >>> from django.test.client import Client >>> c = Client() >>> response = c.get("/") >>> response.template [<django.template.Template object at 0x2723dd0>,  <django.template.Template object at 0x2723f30>,  <django.template.Template object at 0x273ee10>] >>> response.context [ list of Context objects ]

This allows you to explore not just the HTML returned by a view, but also the templates and contexts that were used to render it.

Your tips welcome

If you have any useful tips on debugging Django applications, please share them in the comments on this entry.