Thursday, May 31, 2007

网站检查脚本


LOOP=0
VART=0
DEST="www.google.cn"
OWGT="192.168.0.1"
USERS="test@test.com"
MSG="Cannot connect to google.cn."
VAR2=`ping -s 1 -c 1 $OWGT > /dev/null; echo $?`
if [ $VAR2 -eq 0 ]
then
while [ $LOOP -lt 11 ]
do
if [ $VART -eq 10 ]
then
VART=0
echo $MSG > /root/msg.txt
mail -s "Cannot connect to google.cn" $USERS < /root/msg.txt
else
VAR1=`ping -s 1 -c 1 $DEST > /dev/null; echo $?`
if [ $VAR1 -ne 0 ]
then
VART=$(($VART+1))
else
VART=0
fi
fi
LOOP=$(($LOOP+1))
done
fi

配合crontab执行,检查网站是否能连接上,如果无法连接则通知网管。
这个脚本实际使用还是需要调整,应该是用wget/curl等检查网站的状态,有的网站会禁ping或者ping久了封IP的。

CentOS添加语言包

要从语言(Languages)组安装附加语种支持,使用应用程序-添加/删除软件,或者运行命令:

shell> yum groupinstall <language>-support

在上面的命令中,<language> 是下列之一: assamese, bengali, chinese, gujarati, hindi, japanese, kannada, korean, malayalam, marathi, oriya, punjabi, sinhala, tamil, thai, 或 telegu。

Wednesday, May 30, 2007

rails script/console problem on ubuntu

shell> ruby script/console
Loading development environment.

/usr/local/lib/ruby/1.8/irb/completion.rb:10:in `require':

no such file to load -- readline (LoadError)

from /usr/local/lib/ruby/1.8/irb/completion.rb:10

from /usr/local/lib/ruby/1.8/irb/init.rb:252:in `load_modules'

from /usr/local/lib/ruby/1.8/irb/init.rb:250:in `load_modules'

from /usr/local/lib/ruby/1.8/irb/init.rb:21:in `setup'

from /usr/local/lib/ruby/1.8/irb.rb:54:in `start'

from /usr/local/bin/irb:13

Check them out:
http://ubuntuforums.org/showthread.php?t=169891
http://blog.nanorails.com/articles/2006/03/06/installing-readline-on-kubuntu

1.) Download ruby source.
Download Here
2.) Extract the tar file.
tar -xvf ruby-1.8.5-p12.tar.gz
3.) Change to that directory
cd ruby-1.8.5-p12.tar.gz
4.) Type these commands.
./configure
make
sudo make install
5.) Install readline and ncurses.
apt-get install libncurses5-dev libreadline5-dev
6.) go back to the folder ruby source folder.
ruby-1.8.5-p12.tar.gz
7.) Type these commands
cd ext
cd readline
ruby extconf.rb
make
sudo make install

Thats it. The console bug no longer appears.

Tuesday, May 29, 2007

postfix最简安装与卸载

groupadd postfix
groupadd postdrop
useradd -g postfix postfix

mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
mv /usr/bin/newaliases /usr/bin/newaliases.OFF
mv /usr/bin/mailq /usr/bin/mailq.OFF
chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF /usr/bin/mailq.OFF

make -f Makefile.init makefiles \
'CCARGS=-DUSE_SASL_AUTH -I/usr/include/sasl' \
'AUXLIBS=-L/usr/lib/sasl2 -lsasl2 -lz -lm'

make install

postfix start

卸载Postfix,请按如下方法卸载:



postfix stop

rm -f /usr/sbin/sendmail

rm -f /usr/bin/newaliases

rm -f /usr/bin/mailq

rm -rf /usr/libexec/postfix

rm -rf /etc/postfix

rm -f /usr/sbin/post*



mv /usr/sbin/sendmail.OFF /usr/sbin/sendmail

mv /usr/bin/newaliases.OFF /usr/bin/newaliases

mv /usr/bin/mailq.OFF /usr/bin/mailq

Monday, May 28, 2007

通过webrick console直接打开log里的链接

如webrick console log:
127.0.0.1 - - [28/May/2007:16:43:49 CST] "POST /manage/delete/51643 HTTP/1.1" 200 466
http://localhost/browse/groups/47 -> /manage/delete/51643
移动http://localhost/browse/groups/47上右键'open link'则可以在Firefox里直接打开些link

Ubuntu7.04 下安装mysql-ruby及dbi-ruby

shell> sudo apt-get install libdbi-ruby1.8 libdbi-ruby libdbd-mysql-ruby1.8 libdbd-mysql-ruby

shell> irb
irb(main):001:0> require 'dbi'
=> true
irb(main):002:0> exit

shell> sudo apt-get install libmysqlclient15-dev zlib1g-dev
shell> sudo apt-get install libdbm-ruby1.8 libfcgi-ruby1.8 libfcgi0 libgdbm-ruby1.8 libopenssl-ruby1.8 libruby1.8-dbg
shell> sudo gem install mysql

shell> irb
irb(main):001:0> require 'mysql'
=> true
irb(main):002:0> require 'rubygems'
=> true
irb(main):004:0> require_gem 'mysql'
=> true
irb(main):005:0> exit

In case you're having trouble installing gems

Posted by chad February 06, 2007 @ 07:54 PM
Bulk updating Gem source index for: http://gems.rubyforge.org
ERROR: While executing gem ... (Gem::GemNotFoundException)
Could not find rails (= 1.2.2) in any repository

A significant number of Rails developers have reported problems installing gems with the updated RubyGems release. If you’re experiencing a problem that looks anything like this:

$ gem update sqlite3-ruby Updating installed gems… ERROR: While executing gem … (NoMethodError) undefined
method `refresh’ for #

...you should remove your local source_cache file. This is the file that locally caches any gem metadata from the gem server to avoid having to re-download it every time you execute a gem command.

To discover the location of this file on your system, run the following command:

$ gem env
RubyGems Environment:
- VERSION: 0.9.2 (0.9.2)
- INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
- GEM PATH:
- /usr/local/lib/ruby/gems/1.8
- REMOTE SOURCES:
- http://gems.rubyforge.org

The source_cache file should be in the path labeled by GEM PATH. Removing that file should clear up any related issues.

This solution is a workaround pending a fix by the RubyGems team.

Sunday, May 27, 2007

[mysql5.1 manual 3.8] 与Apache一起使用MySQL

还有一些项目,你可以从MySQL数据库鉴别用户,并且你还可以将日志文件写入MySQL数据库表。
你可以将以下内容放到Apache配置文件中,更改Apache日志格式,使MySQL更容易读取:

LogFormat \
"\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\", \
\"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
要想将该格式的日志文件装载到MySQL,你可以使用以下语句:

LOAD DATA INFILE '/local/access_log' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
所创建的表中的列应与写入日志文件的LogFormat行对应。

另外可以在apache2 http.conf里在日志记录时利用管道命令直接将apache2 access log写入mysql中,还有个apache2的module可以直接实现此功能:mod_log_mysql,具体到其网站上查看设置使用方法,这种直接将access log写入mysql中的方法个人认为不是很妥当,还是用日志循回,再将日志导入mysql中比较好。
也可以利用php, perl, ruby写个脚本分析access_log后写入mysql中。

上面提到将apache2 access log写入mysql中的3个方法,我个人还是觉得最后自己写个脚本导入日志到mysql中比较好。

在MYSQL使用用户变量

可以清空MySQL用户变量以记录结果,不必将它们保存到客户端的临时变量中。(参见 9.3节,“用户变量”.)。

例如,要找出价格最高或最低的物品的,其方法是:

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;

useful mysql sql

\c cancel current sql
\q quit mysql command shell

mysql> select 'a' union select 3;
+---+
| a |
+---+
| a |
| 3 |
+---+
2 rows in set (0.29 sec)

Useful Shell Shortcuts

from Nuby on Rails by topfunky

A few weeks ago someone asked me to recommend a few useful books on Ruby. The first one? Using csh & tcsh. I spend a lot of time in the terminal and these shortcuts help in both tcsh and bash.
Reuse previous arguments

The ! operator gives you a quick way to refer to parts of the previous command.
!! (Full contents of previous command)

How many times have you tried to edit a file, then realize that you need to be root to do it? Use bang-bang to quickly repeat the previous command, with other commands before or after.

emacs /etc/init.d/mongrel_cluster
=> Permission Denied
sudo !!
=> Now opens the file as root

!$ (Last arg of previous command)

Sometimes I need to reuse the last argument with another command, like here where I forgot to quote a string.

wget http://weather.yahooapis.com/forecastrss?p=98117
=> wget: No Match
wget '!$'
=> Now it works

!^ (First argument of previous command)

I rarely use this, although it could have been used in the previous tip.

echo fish and chips
echo !^
=> fish # First argument

!:1 (Argument by number)

!:1 is the same as !^. The difference is that you can reference any element of the previous command.

echo fish and chips
=> fish and chips
echo !:1
=> fish # Same thing as !^

echo fish and chips
echo !:2
=> and # Word 2 in previous command, zero-indexed

echo fish and chips
echo !:0
=> echo # The very first word in the previous command

echo fish and chips
echo !:1-3
=> fish and chips # A range

!pattern (Repeat last command in history with pattern)

The bang is useful for re-running a command that you’ve run before. Spell out the first few letters and hit ENTER (or TAB to show the completion in tcsh). The shell will search backwards in your history until it finds a command that starts with the same letters.

I like the tcsh behavior since you can hit TAB to see what you’re asking for. Using this in bash can be more adventurous since you don’t know what command will be run until you hit ENTER.

rake test:recent
...
!rak
=> Runs 'rake test:recent' or last command starting with 'rak'

Sets
{a,b} (A set)

How often to you rename just part of a file? The {} syntax is convenient.

mv file.{txt,xml}
=> Expands to 'mv file.txt file.xml'

mv file{,.orig}
=> Expands to 'mv file file.orig'

mkdir foo{1,2,3}
=> Expands to 'mkdir foo1 foo2 foo3'

Mac OS X-specific
pbcopy and pbpaste

In Mac OS X, you can copy things to the clipboard and read them back out. This is nice because you can reuse it in the shell or back in the OS with Apple-C or Apple-V.

./generate_random_password | pbcopy

pbpaste > file.txt

Saturday, May 26, 2007

mysqld_safe 启动选项文件使用说明

--defaults-file=FILE Use the specified defaults file, 如果给出,必须首选该选项。
--defaults-extra-file=FILE Also use defaults from the specified file, 如果给出,必须首选该选项。

执行mysqld_safe时,后面参数必须先给出--defaults-file或--defaults-extra-file,否则选项文件不生效。例如,该命令将不使用选项文件:
mysqld_safe --port=port_num --defaults-file=file_name
相反,使用下面的命令,则选项文件生效:
mysqld_safe --defaults-file=file_name --port=port_num

Friday, May 25, 2007

mysql5.1 启动关闭和重启命令并添加系统启动项

在安装目录下运行:
support-files/mysql.server start
support-files/mysql.server stop
support-files/mysql.server restart
support-files/mysql.server reload

执行:
shell> cp support-files/mysql.server /etc/init.d/mysql
shell> chmod +x /etc/init.d/mysql
旧的Red Hat系统使用/etc/rc.d/init.d目录,不使用/etc/init.d。相应地调节前面的命令。
后即安装了mysql server以便自己重启和关闭。
安装脚本后,用来激活它以便在系统启动时运行所需要的命令取决于你的操作系统。在Linux中,你可以使用chkconfig:
shell> chkconfig --list mysql
mysql 服务支持 chkconfig,但它在任何级别中都没有被引用(运行“chkconfig --add mysql”)
shell> chkconfig --add mysql
再用list查看:
mysql 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
shell> ntsysv
可以看到 [ * ] mysql 这一行,表示开机后会自动启动mysql server。
在一些Linux系统中,还需要下面的命令来完全激活MySQL脚本:
shell> chkconfig --level 345 mysql on

便可以用:
service mysql start
service mysql stop
service mysql restart
控制mysql server(不同Linux分发版本这个命令不一样)。


另外上面的内容是基于mysql5.1二进制分发版操作,源码包里support-files文件夹下面有的是mysql.server.sh,这个文件就算按上面一样操作也是不能启动mysql server的,需要make之后用mysql安装目录下生成的share/mysql/mysql.server按照上面的操作执行后即可以,直接用二进制分发包里提供的mysql.server也可以。

[转mysql 5.1 manual 2.3.16] Windows版MySQL同Unix版MySQL对比

已经证明,Windows版MySQL很稳定。Windows版MySQL的功能与相应的Unix版相同,只有以下例外:

· Windows 95和线程

Windows 95创建一个线程时大约需要200字节的主内存。MySQL的每个连接都会创建一个新线程,因此如果你的服务器正处理许多连接,你不应当在Windows 95中运行mysqld。

· 有限的端口数目

Windows系统有大约4,000个端口供客户端连接,某个端口的连接关闭后,在能够重新利用该端口前,需要2至4分钟。在客户端频繁连接并从服务器上断开时,在可以重新使用关闭的端口前,有可能用完了所有可用的端口。如果发生这种情况,MySQL服务器不会响应,即使它仍在运行。请注意机器上运行的其它应用程序也可以使用端口,此时可供MySQL使用的端口数要少。

详细信息参见http://support.microsoft.com/default.aspx?scid=kb;en-us;196271 。

· 并行读

MySQL依靠pread()和pwrite()系统调用来同时使用INSERT和SELECT。目前我们使用互斥来竞争pread()和pwrite()。我们将来想用虚拟接口替换文件级接口,因此要想更快,我们可以在NT、2000和XP上使用readfile()/writefile()接口。目前MySQL 5.1可以打开的文件的限制数目为2,048,意味着在Windows NT,2000,XP和2003上可以运行的并行线程不如Unix上多。

· 阻塞读

MySQL为每个连接使用阻塞读取,如果启用了命名管道连接,其含义如下:

o 连接不会在8小时后自动断开,而在Unix版MySQL中会发生。

o 如果连接被挂起,不杀掉MySQL则不会将其中断。

o mysqladmin kill不会杀掉睡眠中的连接。

o 只要有睡眠连接,mysqladmin shutdown不会中断。

我们计划在将来修复该问题。

· ALTER TABLE

执行ALTER TABLE语句时,将该表锁定不让其它线程使用。在Windows中,你不能删除正被另一个线程使用的文件。在将来,我们会找出办法解决该问题。

· DROP TABLE

在Windows中对一个被MERGE表应用的表执行DROP TABLE不会实现,因为MERGE处理器将表从MySQL上层映射隐藏起来。由于Windows不允许删除打开的文件,必须在删除表之前首先清空所有MERGE表(使用FLUSH TABLES)或删掉MERGE表。

· DATA DIRECTORY and INDEX DIRECTORY

在Windows中将忽略DATA DIRECTORY和INDEX DIRECTORY选项,因为Windows不支持符号连接。在具有非功能realpath()调用的系统中,这些选项也被忽略。

· DROP DATABASE

你不能删掉正被线程使用的数据库。

· 从Task Manager(任务管理器)杀掉MySQL

你不能从Task Manager(任务管理求)或使用Windows 95的shutdown工具来杀掉MySQL。你必须通过mysqladmin shutdown停止它。

· 大小写名

由于Windows对文件名大小写不敏感。因此在Windows中MySQL数据库名和表名对大小写也不敏感。唯一的限制是在同一个语句中,必须同时使用大写或小写指定数据库名和表名。请参见9.2.2节,“识别符大小写敏感性”。

· ‘\’路径名间隔符

Windows中的路径名用‘\’符间隔开,在MySQL中还是转义字符。如果你使用LOAD DATA INFILE或SELECT ... INTO OUTFILE,用‘/’符使用Unix-类文件名:

mysql> LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
你还可以使用双‘\’符:

mysql> LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
· 管道问题。

管道不能在Windows命令行提示符下可靠地工作。如果管道包括字符^Z/CHAR(24),Windows认为遇到了文件末尾并中断程序。

这主要是按照如下所示使用二进制日志的主要问题:

C:\>mysqlbinlog binary-log-name | mysql --user=root
如果使用日志时出现问题,怀疑是由于^Z / CHAR(24)字符,你可以使用下面的程序:

C:\> mysqlbinlog binary-log-file --result-file=/tmp/bin.sql
C:\> mysql --user=root --execute "source /tmp/bin.sql"
后面的命令还可以用来可靠读取任何包含二进制数据的SQL文件。

· Access denied for user错误

如果你试图运行MySQL客户端程序来连接同一机器上运行的服务器,但是遇到错误Access denied for user 'some-user'@'unknown' to database 'mysql',这意味着MySQL不能正确识别你的主机名。

要解决该问题,你应当创建一个名为\windows\hosts包含下面信息的文件:

127.0.0.1 localhost

Thursday, May 24, 2007

mysql server and client config file on windows

MySQL客户端和实用程序,例如mysql命令行客户端和mysqldump不能将my.ini文件放到服务器安装目录中。要想配置客户端和实用工具,根据Windows 版本,在C:\Windows或C:\WINNT目录下创建一个新的my.ini/my.cnf文件。

对于Windows MySQL服务器,根据下面规则确定服务器使用的服务名和选项文件:

· 如果在服务安装命令中,没有在--install选项后面指定了服务名或使用默认服务名(MySQL),服务器则使用MySQL服务名并从标准选项文件的[mysqld]组读取选项。

· 如果在服务安装命令中,在--install选项后面指定的服务名不是默认服务名(MySQL)。则从具有相同服务名的组中读取选项,并从标准选项文件读取选项。

服务器还从标准选项文件的[mysqld]组读取选项。你可以使用[mysqld]组中的选项用于所有MySQL 服务,还可以使用具有相同服务名的组,用于该服务名所对应的服务器。

· 如果在服务安装命令中,在服务名后面指定了--defaults-file选项,服务器只从命名文件的[mysqld]组中读取选项,忽略标准选项文件。

对于更复杂的例子可以考虑使用命令:

C:\> C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld --install MySQL --defaults-file=C:\my-opts.cnf
该命令中,--install选项后面给出了默认服务名(MySQL)。如果未给出--defaults-file选项,该命令可以让服务器从标准选项文件的[mysqld]组中读数。由于提供了--defaults-file选项,服务器只从命名文件的[mysqld]组读取选项。

还可以在启动MySQL服务之前,在Windows Services工具中指定启动参数选项。

MySQL服务器安装为服务后,Windows启动时自动启动服务。还可以从Services工具直接启动服务,或使用命令NET START MySQL。NET命令忽略大小写。

mysql configure 安装参数及其查看方法

在bash里运行 export VISUAL=vi
然后直接运行bin/mysqlbug,可以在vim里看到最后一行里的configure line,就是configure安装时的参数。

MySQL AB提供的二进制文件configure参数:
Linux 2.4.xx x86中的gcc 2.95.3:

CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2 -mcpu=pentiumpro -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static

Mac OS X 10.x:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql \
--with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile --disable-share

如果编译静态链接程序(例如,制作二进制分发版、获得更快的速度或与解决与RedHat分发版的一些问题),configure 里加上--with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static

如果正在使用gcc并且没有安装libg++或libstdc++,可以告诉configure使用gcc作为C++编译器:
shell> CC=gcc CXX=gcc ./configure
当使用gcc作为C++编译器用时,它将不试图链接libg++或libstdc++。即使安装了这些库,这样也很好,因为过去使用MySQL时,它们的部分版本会出现一些奇怪的问题。

如果在x86机器上运行Linux,在大多数情况下最好使用Mysql提供的二进制文件。Mysql已经将二进制连接到了Mysql能找到的打了最好补丁的glibc版本,并使用了最优的编译器选项,尽力使它适合高负荷服务器。对于典型用户,即使对于超过2GB限制的大量并行连接或表设置,在大多数情况下,Mysql的二进制仍然是最佳选择。如果不清楚怎样做,先试用Mysql的二进制看它是否满足需求。如果发现它不够完善,那么可以尝试自己构建。

当开始自己make二进制文件时,如果使用的gcc版本足够新,并可以识别-fno-exceptions选项,则configure时要使用该选项。否则,编译二进制时可能会出现问题。Mysql建议同时使用-felide-constructors和-fno-rtti选项。执行下面操作:

CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \
-felide-constructors -fno-exceptions -fno-rtti" ./configure \
--prefix=/usr/local/mysql \
--without-debug \
--with-charset=gbk \
--with-extra-charsets=complex \
--enable-thread-safe-client \
--enable-local-infile \
--enable-assembler \
--disable-shared \
--with-bdb \
--with-innodb \
--with-client-ldflags=-all-static \
--with-mysqld-ldflags=-all-static \
--with-big-tables \
--with-ndbcluster \
--with-ndb-port \
--with-ndb-port-base \
--without-ndb-debug

配置并编译完源码分发后,便开始安装。默认情况下,可以将文件安装到/usr/local/mysql,即在下面的子目录中:

bin
include/mysql
info
lib/mysql
libexec
share/mysql
sql-bench
var

在一个安装目录内,源码安装的布局在下列方面不同于二进制安装:

· mysqld服务器被安装在“libexec”目录而不是“bin”目录内。

· 数据目录是“var”而非“data”。

· mysql_install_db被安装在“bin”目录而非“scripts”内。

· 头文件和库目录是“include/mysql”和“lib/mysql”而非“include”和“lib”。

Wednesday, May 23, 2007

replace Tab with Space

在bash下试了sed , expand , awk等去替换一个文件里的Tab(shell里这样按出Tab: CTRL+V->CTRL+I->TAB), 但是都比较麻烦,最后google到一个人用perl做的命令:
perl -pi.bak -e 's/\t/ /g' myfile.txt相当有用。
在learnig Perl书中有这个例子:
perl –p –i.bak –w –e ‘s/Randall/Randal/g’fred*.dat,原理同上,这个命令行相当于构建了以下脚本的功能:
#! /usr/bin/perl –w
$^I = “.bak”;
while(<>){
s/Randall/Randal/g;
print;
}

Tuesday, May 22, 2007

postfix启动失败

[root@localhost postfix]# postfix start
postfix/postfix-script: starting the Postfix mail system
但是用ps命令查看却发现postfix没有启动,查看/var/log/maillog
May 22 10:27:58 localhost postfix/master[13426]: fatal: bind 0.0.0.0 port 25: Address already in use
原来旧的sendmail已经运行并占用了25这个端口,因为当时系统安装我没选择邮件服务器,所以忘了去停掉原来的sendmail服务。

Monday, May 21, 2007

route命令详解

[localhost ~yu]# ping -c 4 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.683 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.671 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.683 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.670 ms

--- 192.168.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.670/0.676/0.683/0.032 ms
说明局域网是正常的。

[localhost ~yu]# ping 202.101.63.200
connect: Network is unreachable
这是因为路由没有设置,在ifcfg-eth0文件里设置GATEWAY即可,或者是利用route命令,在命令行里添加一个路由或者默认路由。

[localhost ~yu]#route add default gw 192.168.1.1

route命令详解:
来源于iputils
语法 route [参数] 内部指令 [内部指令参数]
参数略
内部指令
del|add 删除增加路由
-net|-host 指定网段地址或主机地址
target 目的地址或者网络表示

内部指令参数:
netmask NM
gw IPADDR
metric M 设置路由表中的长度字段
mss M 设置TCP最大的区块长度为MB
refect 指定拒绝的路由。
def IF 指定该路由绑定特定的设备IF(如eth0)

范例:
通过eth0的设备增加一个路由到192.168.1.0(子网掩码为255.255.255.0)网段:
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth0

要把目标地址是202.101.x.x的数据包通过202.101.62.254路由出去,使用:
route add –net 202.101.0.0 netmask 255.255.0.0 gw 202.101.62.254

删除添加默认路由:
route del default gw 192.168.0.1
route add default gw 192.168.1.1

Friday, May 18, 2007

Linux服务器拒绝外部ping命令

执行:
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

即可。

Thursday, May 17, 2007

ifconfig 详解

1.作用
ifconfig用于查看和更改网络接口的地址和参数,包括IP地址、网络掩码、广播地址,使用权限是超级用户

2.格式
ifconfig -interface [options] address

3.主要参数

-interface:指定的网络接口名,如eth0和eth1。
up:激活指定的网络接口卡。
down:关闭指定的网络接口。
broadcast address:设置接口的广播地址。
pointopoint:启用点对点方式。
address:设置指定接口设备的IP地址。
netmask address:设置接口的子网掩码。
更多可man ifconfig查看说明。

4.应用说明
ifconfig是用来设置和配置网卡的命令行工具。为了手工配置网络,这是一个必须掌握的命令。使用该命令的好处是无须重新启动机器。要赋给eth0接口IP地址207.164.186.2,并且马上激活它,使用下面命令:
ifconfig eth0 192.168.1.11 netmask 255.255.255.0 broadcast 255.255.255.255
虚拟一块网卡:
ifconfig eth0:1 192.168.1.21 netmask 255.255.255.0 broadcast 255.255.255.255

该命令的作用是设置网卡eth0的IP地址、网络掩码和网络的本地广播地址。若运行不带任何参数的ifconfig命令,这个命令将显示机器所有激活接口的信息。带有“-a”参数的命令则显示所有接口的信息,包括没有激活的接口。注意,用ifconfig命令配置的网络设备参数,机器重新启动以后将会丢失,可设置启动运行此命令,也可以配置ifcfg-eth0文件,重启也就不会丢失了,虚拟的网卡也可以复制一份原文件ifcfg-eth0修改IPADDR即可。
5. 如果要暂停某个网络接口的工作,可以使用down参数:
ifconfig eth0 down
ifconfig eth0:1 up

另外Redhat里还有个ifup 和ifdown 命令与上面二个作用相似,只是暂时起作用。

Wednesday, May 16, 2007

Linux 安装时分区需要注意的几点内容[原创]

1.分区时最好是建立一个120M左右的分区划为/boot,并且 必须 是第一个分区,如/dev/hda1。
2.分区时Primary+Extention总共可以分四个区,一个可以有四个主分区(如四个区都分为主分区时)。一般情况会设置3个主分区加上1个扩展分区,并在扩展分区内再进行逻辑分区。
3.最好是启用LVM,为以后调整硬盘空间及添加额外的磁盘带来方便。
4.RAID现在一般是建议硬件RAID5或者RAID1,所以这里不需要去设置了。
5.SWAP这个一般都是设置为1.8~2.5倍内存大小,据说是这个比例性能最优。但是建议32位机器的单个SWAP不要超过2G(REDHAT官方建议),如果要更大的SWAP,可以再划一个交换分区即可。对于64位机器的单个SWAP建议不超过8G,如果需要8G以上的SWAP则可以再划分一个交换分区即可。另外据linus torvalts本人测试说SWAP多划分一些是不会影响机器性能的。所以就算内存加得很大也是建议设置一个稍大点的SWAP,反正硬盘现在也便宜的很,不要太在意这点空间,如果不是专家就不要去费力分析到底分多大的SWAP,分区性能最佳了。
6.一般应用程序和数据最好是能分在不同的磁盘分区上,以提高效率(如apache和htdocs, mysql和data等)。
7./home, /tmp, /var和/usr建议单独分区挂载到逻辑分区上,/var下面记录了许多系统日志文件,硬盘读取比较多,跟/tmp一样,不正常的关机经常会使机器挂掉。
8. /etc/, /sbin/, /bin/, /dev/ 以及 /lib/ 最好不要单独挂载到分区上,这些目录是绑定/根分区上的。系统启动后就会加载/及其下面的目录。
9.分区格式如无特殊理由请不要使用ext2。

POP3 SSL on Ruby

http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/net/pop.rb?revision=12083&pathrev=12083


# = net/pop.rb
#
# Copyright (c) 1999-2007 Yukihiro Matsumoto.
#
# Copyright (c) 1999-2007 Minero Aoki.
#
# Written & maintained by Minero Aoki .
#
# Documented by William Webber and Minero Aoki.
#
# This program is free software. You can re-distribute and/or
# modify this program under the same terms as Ruby itself,
# Ruby Distribute License.
#
# NOTE: You can find Japanese version of this document at:
# http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=net%2Fpop.rb
#
# $Id$
#
# See Net::POP3 for documentation.
#

require 'net/protocol'
require 'digest/md5'
require 'timeout'

begin
require "openssl"
rescue LoadError
end

module Net

# Non-authentication POP3 protocol error
# (reply code "-ERR", except authentication).
class POPError < ProtocolError; end

# POP3 authentication error.
class POPAuthenticationError < ProtoAuthError; end

# Unexpected response from the server.
class POPBadResponse < POPError; end

#
# = Net::POP3
#
# == What is This Library?
#
# This library provides functionality for retrieving
# email via POP3, the Post Office Protocol version 3. For details
# of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt).
#
# == Examples
#
# === Retrieving Messages
#
# This example retrieves messages from the server and deletes them
# on the server.
#
# Messages are written to files named 'inbox/1', 'inbox/2', ....
# Replace 'pop.example.com' with your POP3 server address, and
# 'YourAccount' and 'YourPassword' with the appropriate account
# details.
#
# require 'net/pop'
#
# pop = Net::POP3.new('pop.example.com')
# pop.start('YourAccount', 'YourPassword') # (1)
# if pop.mails.empty?
# puts 'No mail.'
# else
# i = 0
# pop.each_mail do |m| # or "pop.mails.each ..." # (2)
# File.open("inbox/#{i}", 'w') do |f|
# f.write m.pop
# end
# m.delete
# i += 1
# end
# puts "#{pop.mails.size} mails popped."
# end
# pop.finish # (3)
#
# 1. Call Net::POP3#start and start POP session.
# 2. Access messages by using POP3#each_mail and/or POP3#mails.
# 3. Close POP session by calling POP3#finish or use the block form of #start.
#
# === Shortened Code
#
# The example above is very verbose. You can shorten the code by using
# some utility methods. First, the block form of Net::POP3.start can
# be used instead of POP3.new, POP3#start and POP3#finish.
#
# require 'net/pop'
#
# Net::POP3.start('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |pop|
# if pop.mails.empty?
# puts 'No mail.'
# else
# i = 0
# pop.each_mail do |m| # or "pop.mails.each ..."
# File.open("inbox/#{i}", 'w') do |f|
# f.write m.pop
# end
# m.delete
# i += 1
# end
# puts "#{pop.mails.size} mails popped."
# end
# end
#
# POP3#delete_all is an alternative for #each_mail and #delete.
#
# require 'net/pop'
#
# Net::POP3.start('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |pop|
# if pop.mails.empty?
# puts 'No mail.'
# else
# i = 1
# pop.delete_all do |m|
# File.open("inbox/#{i}", 'w') do |f|
# f.write m.pop
# end
# i += 1
# end
# end
# end
#
# And here is an even shorter example.
#
# require 'net/pop'
#
# i = 0
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# File.open("inbox/#{i}", 'w') do |f|
# f.write m.pop
# end
# i += 1
# end
#
# === Memory Space Issues
#
# All the examples above get each message as one big string.
# This example avoids this.
#
# require 'net/pop'
#
# i = 1
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# File.open("inbox/#{i}", 'w') do |f|
# m.pop do |chunk| # get a message little by little.
# f.write chunk
# end
# i += 1
# end
# end
#
# === Using APOP
#
# The net/pop library supports APOP authentication.
# To use APOP, use the Net::APOP class instead of the Net::POP3 class.
# You can use the utility method, Net::POP3.APOP(). For example:
#
# require 'net/pop'
#
# # Use APOP authentication if $isapop == true
# pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110)
# pop.start(YourAccount', 'YourPassword') do |pop|
# # Rest of the code is the same.
# end
#
# === Fetch Only Selected Mail Using 'UIDL' POP Command
#
# If your POP server provides UIDL functionality,
# you can grab only selected mails from the POP server.
# e.g.
#
# def need_pop?( id )
# # determine if we need pop this mail...
# end
#
# Net::POP3.start('pop.example.com', 110,
# 'Your account', 'Your password') do |pop|
# pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
# do_something(m.pop)
# end
# end
#
# The POPMail#unique_id() method returns the unique-id of the message as a
# String. Normally the unique-id is a hash of the message.
#
class POP3 < Protocol

Revision = %q$Revision$.split[1]

#
# Class Parameters
#

def POP3.default_port
default_pop3_port()
end

# The default port for POP3 connections, port 110
def POP3.default_pop3_port
110
end

# The default port for POP3S connections, port 995
def POP3.default_pop3s_port
995
end

def POP3.socket_type #:nodoc: obsolete
Net::InternetMessageIO
end

#
# Utilities
#

# Returns the APOP class if +isapop+ is true; otherwise, returns
# the POP class. For example:
#
# # Example 1
# pop = Net::POP3::APOP($is_apop).new(addr, port)
#
# # Example 2
# Net::POP3::APOP($is_apop).start(addr, port) do |pop|
# ....
# end
#
def POP3.APOP(isapop)
isapop ? APOP : POP3
end

# Starts a POP3 session and iterates over each POPMail object,
# yielding it to the +block+.
# This method is equivalent to:
#
# Net::POP3.start(address, port, account, password) do |pop|
# pop.each_mail do |m|
# yield m
# end
# end
#
# This method raises a POPAuthenticationError if authentication fails.
#
# === Example
#
# Net::POP3.foreach('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# file.write m.pop
# m.delete if $DELETE
# end
#
def POP3.foreach(address, port = nil,
account = nil, password = nil,
isapop = false, &block) # :yields: message
start(address, port, account, password, isapop) {|pop|
pop.each_mail(&block)
}
end

# Starts a POP3 session and deletes all messages on the server.
# If a block is given, each POPMail object is yielded to it before
# being deleted.
#
# This method raises a POPAuthenticationError if authentication fails.
#
# === Example
#
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# file.write m.pop
# end
#
def POP3.delete_all(address, port = nil,
account = nil, password = nil,
isapop = false, &block)
start(address, port, account, password, isapop) {|pop|
pop.delete_all(&block)
}
end

# Opens a POP3 session, attempts authentication, and quits.
#
# This method raises POPAuthenticationError if authentication fails.
#
# === Example: normal POP3
#
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword')
#
# === Example: APOP
#
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword', true)
#
def POP3.auth_only(address, port = nil,
account = nil, password = nil,
isapop = false)
new(address, port, isapop).auth_only account, password
end

# Starts a pop3 session, attempts authentication, and quits.
# This method must not be called while POP3 session is opened.
# This method raises POPAuthenticationError if authentication fails.
def auth_only(account, password)
raise IOError, 'opening previously opened POP session' if started?
start(account, password) {
;
}
end

#
# SSL
#

@use_ssl = false
@verify = nil
@certs = nil

# Enable SSL for all new instances.
# +verify+ is the type of verification to do on the Server Cert; Defaults
# to OpenSSL::SSL::VERIFY_NONE.
# +certs+ is a file or directory holding CA certs to use to verify the
# server cert; Defaults to nil.
def POP3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE, certs = nil)
@use_ssl = true
@verify = verify
@certs = certs
end

# Disable SSL for all new instances.
def POP3.disable_ssl
@use_ssl = nil
@verify = nil
@certs = nil
end

def POP3.use_ssl?
@use_ssl
end

def POP3.verify
@verify
end

def POP3.certs
@certs
end

#
# Session management
#

# Creates a new POP3 object and open the connection. Equivalent to
#
# Net::POP3.new(address, port, isapop).start(account, password)
#
# If +block+ is provided, yields the newly-opened POP3 object to it,
# and automatically closes it at the end of the session.
#
# === Example
#
# Net::POP3.start(addr, port, account, password) do |pop|
# pop.each_mail do |m|
# file.write m.pop
# m.delete
# end
# end
#
def POP3.start(address, port = nil,
account = nil, password = nil,
isapop = false, &block) # :yield: pop
new(address, port, isapop).start(account, password, &block)
end

# Creates a new POP3 object.
#
# +address+ is the hostname or ip address of your POP3 server.
#
# The optional +port+ is the port to connect to.
#
# The optional +isapop+ specifies whether this connection is going
# to use APOP authentication; it defaults to +false+.
#
# This method does *not* open the TCP connection.
def initialize(addr, port = nil, isapop = false)
@address = addr
@use_ssl = POP3.use_ssl?
@port = port || (POP3.use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port)
@apop = isapop
@certs = POP3.certs
@verify = POP3.verify

@command = nil
@socket = nil
@started = false
@open_timeout = 30
@read_timeout = 60
@debug_output = nil

@mails = nil
@n_mails = nil
@n_bytes = nil
end

# Does this instance use APOP authentication?
def apop?
@apop
end

# does this instance use SSL?
def use_ssl?
@use_ssl
end

# Enables SSL for this instance. Must be called before the connection is
# established to have any effect.
# +verify+ is the type of verification to do on the Server Cert; Defaults
# to OpenSSL::SSL::VERIFY_NONE.
# +certs+ is a file or directory holding CA certs to use to verify the
# server cert; Defaults to nil.
# +port+ is port to establish the SSL connection on; Defaults to 995.
def enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE, certs = nil,
port = POP3.default_pop3s_port)
@use_ssl = true
@verify = verify
@certs = certs
@port = port
end

def disable_ssl
@use_ssl = false
@verify = nil
@certs = nil
end

# Provide human-readable stringification of class state.
def inspect
"#<#{self.class} #{@address}:#{@port} open=#{@started}>"
end

# *WARNING*: This method causes a serious security hole.
# Use this method only for debugging.
#
# Set an output stream for debugging.
#
# === Example
#
# pop = Net::POP.new(addr, port)
# pop.set_debug_output $stderr
# pop.start(account, passwd) do |pop|
# ....
# end
#
def set_debug_output(arg)
@debug_output = arg
end

# The address to connect to.
attr_reader :address

# The port number to connect to.
attr_reader :port

# Seconds to wait until a connection is opened.
# If the POP3 object cannot open a connection within this time,
# it raises a TimeoutError exception.
attr_accessor :open_timeout

# Seconds to wait until reading one block (by one read(1) call).
# If the POP3 object cannot complete a read() within this time,
# it raises a TimeoutError exception.
attr_reader :read_timeout

# Set the read timeout.
def read_timeout=(sec)
@command.socket.read_timeout = sec if @command
@read_timeout = sec
end

# +true+ if the POP3 session has started.
def started?
@started
end

alias active? started? #:nodoc: obsolete

# Starts a POP3 session.
#
# When called with block, gives a POP3 object to the block and
# closes the session after block call finishes.
#
# This method raises a POPAuthenticationError if authentication fails.
def start(account, password) # :yield: pop
raise IOError, 'POP session already started' if @started
if block_given?
begin
do_start account, password
return yield(self)
ensure
do_finish
end
else
do_start account, password
return self
end
end

def do_start(account, password)
s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
if use_ssl?
raise 'openssl library not installed' unless defined?(OpenSSL)
context = OpenSSL::SSL::SSLContext.new
context.verify_mode = @verify
if @certs
if File.file?(@certs)
context.ca_file = @certs
elsif File.directory?(@certs)
context.ca_path = @certs
else
raise ArgumentError, "certs path is not file/directory: #{@certs}"
end
end
s = OpenSSL::SSL::SSLSocket.new(s, context)
s.sync_close = true
s.connect
end
@socket = InternetMessageIO.new(s)
logging "POP session started: #{@address}:#{@port} (#{@apop ? 'APOP' : 'POP'})"
@socket.read_timeout = @read_timeout
@socket.debug_output = @debug_output
on_connect
@command = POP3Command.new(@socket)
if apop?
@command.apop account, password
else
@command.auth account, password
end
@started = true
ensure
# Authentication failed, clean up connection.
unless @started
s.close if s and not s.closed?
@socket = nil
@command = nil
end
end
private :do_start

def on_connect
end
private :on_connect

# Finishes a POP3 session and closes TCP connection.
def finish
raise IOError, 'POP session not yet started' unless started?
do_finish
end

def do_finish
@mails = nil
@command.quit if @command
ensure
@started = false
@command = nil
@socket.close if @socket and not @socket.closed?
@socket = nil
end
private :do_finish

def command
raise IOError, 'POP session not opened yet' \
if not @socket or @socket.closed?
@command
end
private :command

#
# POP protocol wrapper
#

# Returns the number of messages on the POP server.
def n_mails
return @n_mails if @n_mails
@n_mails, @n_bytes = command().stat
@n_mails
end

# Returns the total size in bytes of all the messages on the POP server.
def n_bytes
return @n_bytes if @n_bytes
@n_mails, @n_bytes = command().stat
@n_bytes
end

# Returns an array of Net::POPMail objects, representing all the
# messages on the server. This array is renewed when the session
# restarts; otherwise, it is fetched from the server the first time
# this method is called (directly or indirectly) and cached.
#
# This method raises a POPError if an error occurs.
def mails
return @mails.dup if @mails
if n_mails() == 0
# some popd raises error for LIST on the empty mailbox.
@mails = []
return []
end

@mails = command().list.map {|num, size|
POPMail.new(num, size, self, command())
}
@mails.dup
end

# Yields each message to the passed-in block in turn.
# Equivalent to:
#
# pop3.mails.each do |popmail|
# ....
# end
#
# This method raises a POPError if an error occurs.
def each_mail(&block) # :yield: message
mails().each(&block)
end

alias each each_mail

# Deletes all messages on the server.
#
# If called with a block, yields each message in turn before deleting it.
#
# === Example
#
# n = 1
# pop.delete_all do |m|
# File.open("inbox/#{n}") do |f|
# f.write m.pop
# end
# n += 1
# end
#
# This method raises a POPError if an error occurs.
#
def delete_all # :yield: message
mails().each do |m|
yield m if block_given?
m.delete unless m.deleted?
end
end

# Resets the session. This clears all "deleted" marks from messages.
#
# This method raises a POPError if an error occurs.
def reset
command().rset
mails().each do |m|
m.instance_eval {
@deleted = false
}
end
end

def set_all_uids #:nodoc: internal use only (called from POPMail#uidl)
command().uidl.each do |num, uid|
@mails.find {|m| m.number == num }.uid = uid
end
end

def logging(msg)
@debug_output << msg + "\n" if @debug_output
end

end # class POP3

# class aliases
POP = POP3
POPSession = POP3
POP3Session = POP3

#
# This class is equivalent to POP3, except that it uses APOP authentication.
#
class APOP < POP3
# Always returns true.
def apop?
true
end
end

# class aliases
APOPSession = APOP

#
# This class represents a message which exists on the POP server.
# Instances of this class are created by the POP3 class; they should
# not be directly created by the user.
#
class POPMail

def initialize(num, len, pop, cmd) #:nodoc:
@number = num
@length = len
@pop = pop
@command = cmd
@deleted = false
@uid = nil
end

# The sequence number of the message on the server.
attr_reader :number

# The length of the message in octets.
attr_reader :length
alias size length

# Provide human-readable stringification of class state.
def inspect
"#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>"
end

#
# This method fetches the message. If called with a block, the
# message is yielded to the block one chunk at a time. If called
# without a block, the message is returned as a String. The optional
# +dest+ argument will be prepended to the returned String; this
# argument is essentially obsolete.
#
# === Example without block
#
# POP3.start('pop.example.com', 110,
# 'YourAccount, 'YourPassword') do |pop|
# n = 1
# pop.mails.each do |popmail|
# File.open("inbox/#{n}", 'w') do |f|
# f.write popmail.pop
# end
# popmail.delete
# n += 1
# end
# end
#
# === Example with block
#
# POP3.start('pop.example.com', 110,
# 'YourAccount, 'YourPassword') do |pop|
# n = 1
# pop.mails.each do |popmail|
# File.open("inbox/#{n}", 'w') do |f|
# popmail.pop do |chunk| ####
# f.write chunk
# end
# end
# n += 1
# end
# end
#
# This method raises a POPError if an error occurs.
#
def pop( dest = '', &block ) # :yield: message_chunk
if block_given?
@command.retr(@number, &block)
nil
else
@command.retr(@number) do |chunk|
dest << chunk
end
dest
end
end

alias all pop #:nodoc: obsolete
alias mail pop #:nodoc: obsolete

# Fetches the message header and +lines+ lines of body.
#
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
def top(lines, dest = '')
@command.top(@number, lines) do |chunk|
dest << chunk
end
dest
end

# Fetches the message header.
#
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
def header(dest = '')
top(0, dest)
end

# Marks a message for deletion on the server. Deletion does not
# actually occur until the end of the session; deletion may be
# cancelled for _all_ marked messages by calling POP3#reset().
#
# This method raises a POPError if an error occurs.
#
# === Example
#
# POP3.start('pop.example.com', 110,
# 'YourAccount, 'YourPassword') do |pop|
# n = 1
# pop.mails.each do |popmail|
# File.open("inbox/#{n}", 'w') do |f|
# f.write popmail.pop
# end
# popmail.delete ####
# n += 1
# end
# end
#
def delete
@command.dele @number
@deleted = true
end

alias delete! delete #:nodoc: obsolete

# True if the mail has been deleted.
def deleted?
@deleted
end

# Returns the unique-id of the message.
# Normally the unique-id is a hash string of the message.
#
# This method raises a POPError if an error occurs.
def unique_id
return @uid if @uid
@pop.set_all_uids
@uid
end

alias uidl unique_id

def uid=(uid) #:nodoc: internal use only
@uid = uid
end

end # class POPMail


class POP3Command #:nodoc: internal use only

def initialize(sock)
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
@apop_stamp = res.slice(/<.+>/)
end

def inspect
"#<#{self.class} socket=#{@socket}>"
end

def auth(account, password)
check_response_auth(critical {
check_response_auth(get_response('USER %s', account))
get_response('PASS %s', password)
})
end

def apop(account, password)
raise POPAuthenticationError, 'not APOP server; cannot login' \
unless @apop_stamp
check_response_auth(critical {
get_response('APOP %s %s',
account,
Digest::MD5.hexdigest(@apop_stamp + password))
})
end

def list
critical {
getok 'LIST'
list = []
@socket.each_list_item do |line|
m = /\A(\d+)[ \t]+(\d+)/.match(line) or
raise POPBadResponse, "bad response: #{line}"
list.push [m[1].to_i, m[2].to_i]
end
return list
}
end

def stat
res = check_response(critical { get_response('STAT') })
m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or
raise POPBadResponse, "wrong response format: #{res}"
[m[1].to_i, m[2].to_i]
end

def rset
check_response(critical { get_response('RSET') })
end

def top(num, lines = 0, &block)
critical {
getok('TOP %d %d', num, lines)
@socket.each_message_chunk(&block)
}
end

def retr(num, &block)
critical {
getok('RETR %d', num)
@socket.each_message_chunk(&block)
}
end

def dele(num)
check_response(critical { get_response('DELE %d', num) })
end

def uidl(num = nil)
if num
res = check_response(critical { get_response('UIDL %d', num) })
return res.split(/ /)[1]
else
critical {
getok('UIDL')
table = {}
@socket.each_list_item do |line|
num, uid = line.split
table[num.to_i] = uid
end
return table
}
end
end

def quit
check_response(critical { get_response('QUIT') })
end

private

def getok(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
check_response(recv_response())
end

def get_response(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
recv_response()
end

def recv_response
@socket.readline
end

def check_response(res)
raise POPError, res unless /\A\+OK/i =~ res
res
end

def check_response_auth(res)
raise POPAuthenticationError, res unless /\A\+OK/i =~ res
res
end

def critical
return '+OK dummy ok response' if @error_occured
begin
return yield()
rescue Exception
@error_occured = true
raise
end
end

end # class POP3Command

end # module Net

Tuesday, May 15, 2007

用Ruby程序接收邮件


require 'net/pop'

pop = Net::POP3.new('pop3.126.com')
pop.start('test', 'password') # (1)
if pop.mails.empty?
puts 'No mail.'
else
i = 0
# pop.each_mail do |m| # or "pop.mails.each ..." # (2)
# File.open("#{i}", 'w') do |f|
# f.write m.pop
# end
# m.delete
# i += 1
# end
pop.mails.each do |m|
File.open("mail", 'a') do |f|
f.write m.pop
end
end
puts "#{pop.mails.size} mails popped."
end
pop.finish

Linux fetchmail 使用实例

fetchmail 工具需要一个名为 .fetchmailrc 的配置文件才能正常工作。 这个文件中包含了服务器信息, 以及登录使用的凭据。 由于这个文件包含敏感内容, 建议将其设置为只有属主所有, 使用下面的命令:

$> chmod 600 .fetchmailrc

下面的 .fetchmailrc 提供了一个将某一用户的信箱通过 POP 下载到本地的例子。

poll pop3.163.com proto pop3:
username "test", with password "password", is "yu" here;

更多的资料可参考官方手册,另此软件作者Eric Steven Raymond是个开源项目牛人,出过一篇有影响力的文章《大教堂与集市》。

telnet 收发邮件

Initiative - est's Blog
收邮件 开始 运行 cmd 回车,OK, Let's go!

telnet 202.115.22.199 110
USER electronixtar
PASS 我的密码啦

可以看到统计了,接下来

STAT 可以查看统计

LIST 看所有信件

RETR 1 收第一封啦。可惜邮件是 Base64 编码的。不过习惯就对了,以后我们应聘的时候可以吹会第三门外语Base64呢,哇咔咔

TOP 1 10 收最前面的1封的前10行内容

DELE 1 删除第一封

QUIT 断开连接,闪人鸟~

发邮件 开始 运行 cmd 回车,OK, Let's go on!

telnet 202.115.22.199 25

EHLO Multiversal 偶的电脑名字,双方协商呢,看来蛮友好的嘛。服务器返回:
250-mail.dormforce.net
250-AUTH CRAM-MD5 PLAIN LOGIN DIGEST-MD5 NTLM
250-SIZE 10485760
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-PIPELINING
250-ETRN
250-DSN
250 HELP
可能列出了一些命令吧,继续,

AUTH LOGIN 用一般登陆模式。从上面的服务器返回可以看到居然支持 AUTH CRAM-MD5 PLAIN LOGIN DIGEST-MD5 NTLM,爽啊,支持这么多 ^_^
服务器返回,
AUTH LOGIN
334 VXNlcm5hbWU6
服务器问你用户名呢,不过是 Username: Base64编码后的字符
ZWxlY3Ryb25peHRhcg==
偶的用户名 Base64编码后,看来以后如果用 telnet 收邮件,得背用户名的Base64写法啊
334 UGFzc3dvcmQ6
回答是你的密码 Base64 加密后的字符串,这里偶就不敢写了。
235 2.0.0 Authentication successful

然后开始写邮件啦。注意准备好Base64翻译器:

MAIL FROM: 发件人吧
250 2.1.0 Sender ok

RCPT TO: 收件人吧
250 2.1.5 Recipient ok (remote)

DATA
然后就是正文了,符合 MIME 规范就可以了。贴一个例子:

From: electronixtar@dormforce.net
To: electronicstar@dormforce.net
Subject: Hello From telnet
Mime-Version: 1.0
Content-Type: text/plain

Hello!

.

最后结束,打一个回车,一个 句号 . 英文半角的,然后再一个回车,写信完毕!

QUIT 断开连接,闪人。

btw,今天抓包发现,DreamMail发邮件速度快的原因是采用了异步读取,真是NB啊~

Monday, May 14, 2007

Mysql unauthenticated user problems

当用show processlist;看到如下信息时
unauthenticated user | 192.168.0.3:1112 | NULL | Connect | NULL | login | NULL

请参阅:http://codenode.com/dns

解决办法:
1、启动时带参数  --skip-name-resolve
2、访问的主机授权时用IP,最好把该主机的IP及主机名写到/etc/hosts文件中

Sunday, May 13, 2007

Mysql字符串及赋值操作符

可以使用“ ” ”(双引号)或“ ’ ”(单引号)括住字符串,而不仅是“ ’ ”(单引号)。在字符串中使用“ \ ”作为转义字符。
能够在带有“:=”赋值操作符的语句中设置变量。
mysql> SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg
-> FROM test_table;
mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;

MySQL服务器能够理解“||”和“&&”操作符,将其当作逻辑OR和AND,就像在C编程语言中那样。在MySQL服务器中,||和OR是同义词,&&和AND也是同义词。由于采用了该优异的语法体系,MySQL服务器不支持SQL针对字符串连接的“||”操作符,而采用了CONCAT()取而代之。由于CONCAT()能够接受任意数目的参量,很容易将使用“||”操作符的情况转换为MySQL服务器支持的类型。
默认情况下,所有的字符串比较均区分大小写,其分类顺序由当前字符集确定(默认为cp1252 Latin1)。如果你不喜欢该点,应使用BINARY属性或BINARY cast声明列,这样,就会使用基本的字符代码值进行比较,而不是词汇顺序。
“%”操作符等同于MOD()。也就是说“N % M”等同于MOD(N,M)。Cyuyan的程序员支持“%”,而且它也是为了兼容PostgreSQL而使用的。
BIT_COUNT()、CASE、ELT()、FROM_DAYS()、FORMAT()、IF()、PASSWORD()、ENCRYPT()、MD5()、ENCODE()、DECODE()、PERIOD_ADD()、PERIOD_DIFF()、TO_DAYS()、以及WEEKDAY()函数。
GROUP BY函数STD()、BIT_OR()、BIT_AND()、BIT_XOR()、以及GROUP_CONCAT()。请参见12.10节,“与GROUP BY子句同时使用的函数和修改程序”。

Saturday, May 12, 2007

SQL Transaction in Rails

http://snippets.dzone.com:80/posts/show/3995


def fetch_value
sql = ActiveRecord::Base.connection();
sql.execute "SET autocommit=0";
sql.begin_db_transaction
id, value =
sql.execute("SELECT id, value FROM sometable WHERE used=0 LIMIT 1 FOR UPDATE").fetch_row;
sql.update "UPDATE sometable SET used=1 WHERE id=#{id}";
sql.commit_db_transaction

value;
end

Make a remote URL work like a file upload (in Rails)

Popular @ dzone.com

Want to load a remote URL into an acts_as_attachment/attachment_fu model? Use this little utility class.


class UrlUpload
# Add valid extensions here if you want stuff other than images --
# this helps the webserver set the right content type
EXTENSIONS = {
"image/jpeg" => ["jpg", "jpeg", "jpe"],
"image/gif" => ["gif"],
"image/png" => ["png"]
}
attr_reader :original_filename, :content_type, :attachment_data
def initialize(url)
@attachment_data = open(url)
@content_type = self.attachment_data.content_type
@original_filename = determine_filename
end

private
def determine_filename
# Grab the path - even though it could be a script and not an actual file
path = self.attachment_data.base_uri.path
# Get the filename from the path, make it lowercase to handle those
# crazy Win32 servers with all-caps extensions
filename = File.basename(path).downcase
# If the file extension doesn't match the content type, add it to the end, changing any existing .'s to _
filename = [filename.gsub(/\./, "_"), EXTENSIONS[self.content_type].first].join(".") unless EXTENSIONS[self.content_type].any? {|ext| filename.ends_with?("." + ext) }
# Return the result
filename
end
end



Now when you have the URL you want to load, do something like this:

@model.uploaded_data = UrlUpload.new(url)


Or better yet, make a pseudo-accessor on your aaa/attachment_fu model so you can stay "model-heavy".

def url=(value)
self.uploaded_data = UrlUpload.new(value)
end

DNS的一些相关基础知识

1、DNS就是域名服务器,他的任务就是确定域名的解析,比如A记录MX记录等等。

2、任何域名都至少有一个DNS,一般是2个。为什么要2个以上呢?因为DNS可以轮回处理,第一个解析失败可以找第二个。这样只要有一个DNS解析正常,就不会影响域名的正常使用。

3、如何确定域名的DNS?
很简单到http://www.internic.net/whois.html输入你要查询的域名就可以看到了。这个是国际域名管理中心。唯一的权威。只要这里能查到某个域名,就表示域名是生效的。它说你什么时候到期,就是什么时候到期。

4、有效的DNS表示当前正在起作用的DNS服务器是谁,比如查询结果是NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)就表示当前域名是由NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)负责解析。其他DNS的设置,都是无效的。

5、DNS是可以修改的。修改以后需要24-72小时以后,全世界才能刷新过来。internic的信息一般在24小时以后可以看到。另外,修改的过程,并不表示域名会停止解析,只要你在2边都做好了解析。如果生效了就是新的DNS在起作用。如果没生效。就是旧的DNS在起作用。要么生效,要么不生效。不存在2个都不起作用的时间。所以域名解析,不会中断。前提是两边都做了解析。

6、DNS是有缓存的。
1、访问者的电脑;2、你的ISP接入商。
简单举例:比如你访问www.tydncn.com,你的电脑首先查询本机上有没有缓存www.tydncn.com的记录。如果有就直接调用不再去查寻。就是说如果你前面刚访问过www.tydncn.com,这个时候就算电信的DNS和NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)都不能解析。也是能够正常解析出域名的。
清除本机DNS缓存方法很简单。关闭IE然后清除历史记录,或者重启电脑。
然后还有一个就是isp接入商的DNS的缓存。
isp就是当地网络接入商。比如我们这里的福建电信;福州网通、南平铁通等等。每个地方都是不一样的。isp的DNS和NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)这样的DNS是不同的。NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)只负责具体的解析,不负责缓存。isp的DNS只负责查询和缓存,不负责解析。
简单描述下刚才访问www.tydncn.com的情况。如果本机上不存在www.tydncn.com的记录。你的电脑就会去查询当地ISP的DNS。isp的DNS只有缓存。就是说他会检查有没有www.tydncn.com的缓存。如果有,他就直接把www.tydncn.com 的记录发送给用户。用户也就能访问了。如果ISP的缓存里面也没有www.tydncn.com 的记录,那么他进一步去查询tydncn.com的DNS是什么?然后再到对应的DNS上直接去取得数据,并返回给用户。当第一个用户访问了www.tydncn.com以后,isp的dns上也就开始缓存了www.tydncn.com 的记录。以后他就不必再去 NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)去找了。除非有新的域名,他才会去查。比如访问bbs.tydncn.com的时候,他就要重新去查了。

7、isp的DNS缓存是有时间限制的。一般是1个小时。前后2次间隔1个小时的话,他就去域名的DNS上重新取得数据。这里说的是最前面一次和当前的比较。也就是说如果时间差距较大,就重新去域名的DNS服务器上找。所以刷新就变的很有必要,否则缓存了一次以后。域名记录改了以后。ISP就永远不去找新的记录了。知道了这个原理以后,大家就会明白,为什么原来没有的记录注册并生效会很快。修改的话生效会很慢。就是因为缓存的原因。但如果没有缓存,访问的效率会很低,因为任何一次输入www.tydncn.com都得跑到NS.XINNETDNS.COM、NS.XINNET.CN(新网信海)去查询记录。

备注:很多域名商的域名解析系统也不是实时刷新的。一般会设置下时间,比如10分钟.就是说,你设置了一个新的A记录以后,域名服务器会在10分钟内为你添加。目的就是为了节约服务器资源。怕客户的DNS不断的刷新记录。刷新记录肯定需要消耗一定的资源。而且刷新过程中是不能解析的。另外刷新过程大概5秒。就是说这个5秒内域名商的的DNS是不能用的。
原文:http://panshiwangluo.blog.bokee.net/bloggermodule/blog_viewblog.do?id=553268

Friday, May 11, 2007

How To Back Up MySQL Databases Without Interrupting MySQL

This article describes how you can back up MySQL databases without interrupting the MySQL service. Normally, when you want to create a MySQL backup, you either have to stop MySQL or issue a read lock on your MySQL tables in order to get a correct backup; if you don't do it this way, you can end up with an inconsistent backup. To get consistent backups without interrupting MySQL, I use a little trick: I repplicate my MySQL database to a second MySQL server, and on the second MySQL server I use a cron job that creates regular backups of the replicated database.

How To Back Up MySQL Databases Without Interrupting MySQL

nslookup 查询MX和NS等

yu$ nslookup
> set TYPE=A
> www.google.com
Server: 219.233.241.166
Address: 219.233.241.166#53

Non-authoritative answer:
www.google.com canonical name = www.l.google.com.
www.l.google.com canonical name = www-china.l.google.com.
Name: www-china.l.google.com
Address: 64.233.189.104
> set TYPE=MX
> www.gmail.com
Server: 219.233.241.166
Address: 219.233.241.166#53

Non-authoritative answer:
www.gmail.com canonical name = mail.google.com.
mail.google.com canonical name = googlemail.l.google.com.

Authoritative answers can be found from:
l.google.com
origin = d.l.google.com
mail addr = dns-admin.google.com
serial = 1309884
refresh = 900
retry = 900
expire = 1800
minimum = 60
> set TYPE=NS
> www.google.com
Server: 219.233.241.166
Address: 219.233.241.166#53

Non-authoritative answer:
www.google.com canonical name = www.l.google.com.
www.l.google.com canonical name = www-china.l.google.com.

Authoritative answers can be found from:
l.google.com
origin = b.l.google.com
mail addr = dns-admin.google.com
serial = 1309885
refresh = 900
retry = 900
expire = 1800
minimum = 60
> exit

Firefox和IE的本地域名解析区别

Firefox 会在启动时就读取/etc/hosts(linux)里的设置,如果修改了这个文件,IE是即时生效的,而firefox只有再次重启才会使/etc/hosts文件里的解析生效,windows 里这个文件一般是在C:/windows/system32/drivers/etc/中。

PING命令中TTL的具体含义

http://www.gbunix.com/htmldata/2006_05/16/29/article_1305_1.html
  简单来说,TTL全程Time to Live,意思就是生存周期。

  首先要说明ping命令是使用的网络层协议ICMP,所以TTL指的是一个网络层的网络数据包(package)的生存周期,这句话不懂的先回去复习OSI7层协议去。

  第一个问题,为什么要有生存周期这个概念。

  很显然,一个package从一台机器到另一台机器中间需要经过很长的路径,显然这个路径不是单一的,是很复杂的,并且很可能存在环路。如果一个数据包在传输过程中进入了环路,如果不终止它的话,它会一直循环下去,如果很多个数据包都这样循环的话,那对于网络来说这就是灾难了。所以需要在包中设置这样一个值,包在每经过一个节点,将这个值减1,反复这样操作,最终可能造成2个结果:包在这个值还为正数的时候到达了目的地,或者是在经过一定数量的节点后,这个值减为了0。前者代表完成了一次正常的传输,后者代表包可能选择了一条非常长的路径甚至是进入了环路,这显然不是我们期望的,所以在这个值为0的时候,网络设备将不会再传递这个包而是直接将他抛弃,并发送一个通知给包的源地址,说这个包已死。

  其实TTL值这个东西本身并代表不了什么,对于使用者来说,关心的问题应该是包是否到达了目的地而不是经过了几个节点后到达。但是TTL值还是可以得到有意思的信息的。

  每个操作系统对TTL值得定义都不同,这个值甚至可以通过修改某些系统的网络参数来修改,例如Win2000默认为128,通过注册表也可以修改。而Linux大多定义为64。不过一般来说,很少有人会去修改自己机器的这个值的,这就给了我们机会可以通过ping的回显TTL来大体判断一台机器是什么操作系统。

以我公司2台机器为例
看如下命令

D:\Documents and Settings\hx>ping 61.152.93.131

Pinging 61.152.93.131 with 32 bytes of data:

Reply from 61.152.93.131: bytes=32 time=21ms TTL=118
Reply from 61.152.93.131: bytes=32 time=19ms TTL=118
Reply from 61.152.93.131: bytes=32 time=18ms TTL=118
Reply from 61.152.93.131: bytes=32 time=22ms TTL=118

Ping statistics for 61.152.93.131:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss
Approximate round trip times in milli-seconds:
Minimum = 18ms, Maximum = 22ms, Average = 20ms

D:\Documents and Settings\hx>ping 61.152.104.40

Pinging 61.152.104.40 with 32 bytes of data:

Reply from 61.152.104.40: bytes=32 time=28ms TTL=54
Reply from 61.152.104.40: bytes=32 time=18ms TTL=54
Reply from 61.152.104.40: bytes=32 time=18ms TTL=54
Reply from 61.152.104.40: bytes=32 time=13ms TTL=54

Ping statistics for 61.152.104.40:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss
Approximate round trip times in milli-seconds:
Minimum = 13ms, Maximum = 28ms, Average = 19ms

  第一台TTL为118,则基本可以判断这是一台Windows机器,从我的机器到这台机器经过了10个节点,因为128-118=10。而第二台应该是台Linux,理由一样64-54=10。

  了解了上面的东西,可能有人会有一些疑问,例如以下:

  1,不是说包可能走很多路径吗,为什么我看到的4个包TTL都是一样的,没有出现不同?

  这是由于包经过的路径是经过了一些最优选择算法来定下来的,在网络拓扑稳定一段时间后,包的路由路径也会相对稳定在一个最短路径上。具体怎么算出来的要去研究路由算法了,不在讨论之列。

  2,对于上面例子第二台机器,为什么不认为它是经过了74个节点的Windows机器?因为128-74=54。

  对于这个问题,我们要引入另外一个很好的ICMP协议工具。不过首先要声明的是,一个包经过74个节点这个有些恐怖,这样的路径还是不用为好。

  要介绍的这个工具是tracert(*nix下为traceroute),让我们来看对上面的第二台机器用这个命令的结果

D:\Documents and Settings\hx>tracert 61.152.104.40

Tracing route to 61.152.104.40 over a maximum of 30 hops

1 13 ms 16 ms 9 ms 10.120.32.1
2 9 ms 9 ms 11 ms 219.233.244.105
3 12 ms 10 ms 10 ms 219.233.238.173
4 15 ms 15 ms 17 ms 219.233.238.13
5 14 ms 19 ms 19 ms 202.96.222.73
6 14 ms 17 ms 13 ms 202.96.222.121
7 14 ms 15 ms 14 ms 61.152.81.86
8 15 ms 14 ms 13 ms 61.152.87.162
9 16 ms 16 ms 28 ms 61.152.99.26
10 12 ms 13 ms 18 ms 61.152.99.94
11 14 ms 18 ms 16 ms 61.152.104.40

Trace complete.

  从这个命令的结果能够看到从我的机器到服务器所走的路由,确实是11个节点(上面说10个好像是我犯了忘了算0的错误了,应该是64-54+1,嘿嘿),而不是128的TTL经过了70多个节点。

  既然已经说到这里了,不妨顺便说说关于这两个ICMP命令的高级一点的东西。

  首先是ping命令,其实ping有这样一个参数,可以无视操作系统默认TTL值而使用自己定义的值来发送ICMP Request包。

  例如还是用那台Linux机器,用以下命令:

D:\Documents and Settings\hx>ping 61.152.104.40 -i 11

Pinging 61.152.104.40 with 32 bytes of data:

Reply from 61.152.104.40: bytes=32 time=10ms TTL=54
Reply from 61.152.104.40: bytes=32 time=13ms TTL=54
Reply from 61.152.104.40: bytes=32 time=10ms TTL=54
Reply from 61.152.104.40: bytes=32 time=13ms TTL=54

Ping statistics for 61.152.104.40:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 10ms, Maximum = 13ms, Average = 11ms

D:\Documents and Settings\hx>

  这个命令我们定义了发包的TTL为11,而前面我们知道,我到这台服务器是要经过11个节点的,所以这个输出和以前没什么不同。现在再用这个试试看:

D:\Documents and Settings\hx>ping 61.152.104.40 -i 10

Pinging 61.152.104.40 with 32 bytes of data:

Reply from 61.152.99.94: TTL expired in transit.
Reply from 61.152.99.94: TTL expired in transit.
Reply from 61.152.99.94: TTL expired in transit.
Reply from 61.152.99.94: TTL expired in transit.

Ping statistics for 61.152.104.40:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

D:\Documents and Settings\hx>

  可以看到,结果不一样了,我定义了TTL为10来发包,结果是TTL expired in transit.就是说在到达服务器之前这个包的生命周期就结束了。注意看这句话前面的ip,这个ip恰好是我们前面tracert结果到服务器之前的最后1个ip,包的TTL就是在这里减少到0了,根据我们前面的讨论,当TTL减为0时设备会丢弃包并发送一个TTL过期的ICMP反馈给源地址,这里的结果就是最好的证明。

  通过这里再次又证明了从我机器到服务器是经过了11个节点而不是70多个,呵呵。

  最后再巩固一下知识,有人可能觉得tracer这个命令很神奇,可以发现一个包所经过的路由路径。其实这个命令的原理就在我们上面的讨论中。

  想象一下,如果我给目的服务器发送一个TTL为1的包,结果会怎样?

  根据前面的讨论,在包港出发的第一个节点,TTL就会减少为0,这时这个节点就会回应TTL失效的反馈,这个回应包含了设备本身的ip地址,这样我们就得到了路由路径的第一个节点的地址。

  因此,我们继续发送TTL=2的包,也就受到第二个节点的TTL失效回应

  依次类推,我们一个一个的发现,当最终返回的结果不是TTL失效而是ICMP Response的时候,我们的tracert也就结束了,就是这么简单。

  顺便补一句ping命令还有个-n(linux -c)的参数指定要发包的数量,指定了这个数字就会按照你的要求来发包了而不是默认的4个包。如果使用-t参数的话,命令会一直发包直到你强行中止它。

Thursday, May 10, 2007

Dump a table to YAML dump

from DZone Snippets: rails code by rohan_kini (ROhan Kini)


//Dump a table to YAML dump


require 'yaml'

task :dump_fixtures => :environment do |t|
File.open('dump.yml', "w") do |f|
js.each do |j|
f.print YAML.dump ({"record_#{j.id}" => j.attributes})
end
end
end

Wednesday, May 09, 2007

Ubuntu scim 五笔输入法设置

默认安装后SCIM无法调出五笔,需要安装中文支持,在新立得和Administrator->Language support里安装或者是直接在命令行里输入:
$> apt-get install language-support-zh

如果报错说找不到包language-support-zh时,可以到网上到一些中文的sourses.lists更新源文件后运行:
$> sudo apt-get update
然后再到Administrator->Language support里安装中文字体。

安装字体库:
$> apt-get install ttf-bitstream-vera ttf-arphic-*

之后修改/etc/environment这个配置文件如下:

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
LANGUAGE="en_US:en"
LANG="zh_CN.UTF-8"
LC_ALL="zh_CN.UTF-8"
#GST_ID3_TAG_ENCODING="GBK"

这样注销重新登录即可看到输入法,并且系统托盘看得到一个键盘标志。
不过这样子原来会转为中文系统,如果不想改变系统语言属性,则可以在Language support里点选上Input method下面的checkbox,注销后再进就能看到这个键盘标志,scim已经可以使用。

Tuesday, May 08, 2007

Prompting for Rails Database Password

from PragDave by Dave Thomas

Mike and I are running a Rails Studio in Denver. We were talking about database configuration, and an attendee asked "How can I make Rails prompt me for the database password, rather than hard code it into a configuration file?" It turns out that's easy to do, because the Rails configuration files are processed through the ERb templating system.

Here's what the production stanza looks like in the default database.yml file:

production:
adapter: mysql
database: events_production
username: root
password:

If we want to prompt at the console for a password, we can change it like this:


<%
def get_password
print "Password: "
`stty -echo`
STDIN.gets.chomp ensure `stty echo`
end
%>

production:
adapter: mysql
database: events_production
username: root
password: <%= get_password %>

Now, when Rails reads the configuration file, it gets to the password field and discovers it needs to run the get_password method. We define that method in the code block between <% and %>. This prompts for the password (with no echo--this only works on Unix boxes).

Does this really work in production: I don't know. It seems to, but I haven't tested it exhaustively.