小小程序员

小小程序员
随笔 - 5, 文章 - 0, 评论 - 0, 引用 - 0
数据加载中……

2011年6月21日

sudo的环境变量获取

sudo的环境变量获取
问题描述:
    yuyu用户设置了自定义的环境变量,提升到sudo执行,无法获取该环境变量
解决方法:
    在/etc/sudoers.d目录下添加任意文件,前提是不包括~结尾和.字符,权限要设置成440,具体要求看改目录下的README文件
    文件内容Defaults env_keep += "CONFIG_DIR"
以上在yuyu中设置的变量CONFIG_DIR 就能在sudo中使用

posted @ 2011-06-21 10:08 余坚 阅读(280) | 评论 (0)编辑 收藏

2010年6月21日

[源码学习]Tomcat6 源码学习

Tomcat6 源码学习
2010-3-29
【tomcat启动类Bootstrap】
t1.tomcat的人口函数,启动类
org.apache.catalina.startup. Bootstrap.java   Main函数

t2.Bootstrap类
初始化 ClassLoader, 然后利用 Java Reflection 调用 Catalina 类来启动 tomcat server

【tomcat扩展-日志】
a1.private static Log log = LogFactory.getLog(Bootstrap.class);
日志可以定义为private 和static

a2.只在本类中使用的方法,使用private,降低访问权限,需要的时候,再考虑重构或者提高访问权限public

a.日志打印前加if(log.isInfoEnabled())
如果代码中含有logger.debug(“string”);此类语句,尽管在log4j.xml配置文件中对该类logger的level为 ERROR,但是仍然会产生较大的内存开销,通常是所要输出的string的几十倍甚至上百倍大小,对内存开销非常大。优化方法为:使用logger进行 判断。


2010-3-30
【tomcat扩展-classloader】
a3.如果两个类属于同一个包下,但是由不同的classloader加载,那么他们也不能互访default类型方法,属性

a4.classloader:与C或C++编写的程序不同,Java程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件基本上 对应于一个类。此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader是JVM中将类装入内存的那部分

a5.定制的ClassLoader应用:
1.在执行非置信代码之前,自动验证数字签名
2.使用用户提供的密码透明地解密代码
3.动态地创建符合用户特定需要的定制化构建类
4.任何您认为可以生成Java字节码的内容都可以集成到应用程序中

a6.findClass方法是创建定制的ClassLoader时唯一需要覆盖的方法。
ClassLoader loadClass方法
Class c = findLoadedClass(name);
if (c == null) {
    try {
if (parent != null) {
    c = parent.loadClass(name, false);
} else {
    c = findBootstrapClass0(name);
}
    } catch (ClassNotFoundException e) {
        // If still not found, then invoke findClass in order
        // to find the class.
        c = findClass(name);
    }
}

a7.ClassLoader(CCL)的任务是确保代码被编译和更新。
下面描述了它的工作方式:1、当请求一个类时,先查看它是否在磁盘的当前目录或相应的子目录。
2、如果该类不存在,但源码中有,那么调用Java编译器来生成类文件。
3、如果该类已存在,检查它是否比源码旧。如果是,调用Java编译器来重新生成类文件。
4、如果编译失败,或者由于其它原因不能从现有的源码中生成类文件,返回ClassNotFoundException。
5、如果仍然没有该类,也许它在其它库中,所以调用findSystemClass来寻找该类。
6、如果还是没有,则返回ClassNotFoundException。
7、否则,返回该类。
8、调用findLoadedClass来查看是否存在已装入的类。
9、如果没有,那么采用那种特殊的神奇方式来获取原始字节。
10、如果已有原始字节,调用defineClass将它们转换成Class对象。
11、如果没有原始字节,然后调用findSystemClass查看是否从本地文件系统获取类。
12、如果resolve参数是true,那么调用resolveClass解析Class对象。
13、如果还没有类,返回ClassNotFoundException。
14、否则,将类返回给调用程序。

【tomcat启动类classloader】
t3.tomcat自定义了三个类,catalinaLoader commonLoader,sharedLoader
Common - 载入$CATALINA_HOME/common/...它们对TOMCAT和所有的WEB APP都可见
Catalina - 载入$CATALINA_HOME/server/..它们仅对TOMCAT可见,对所有的WEB APP都不可见
Shared-载入$CATALINA_HOME/shared/它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)

t4.Bootstrap通过反射初始化Catalina类,
反射调用Catalina方法setParentClassLoader,传递SharedClassloader
反射call Catalina方法load 利用server.xml中的配置初始化Service,Server,Engine,Host
反射call Catalina方法start Start the new server  该server是通过  解析xml文件生成的org.apache.catalina.core.StandardServer类


【tomcat-xml解析】
1.Tomcat取了Digester中的interface和几个Rule,并且自己实现了一些 Rule 来解析xml.
2.tomcat解析xml创建以下几个类
Server:
org.apache.catalina.core.StandardServer
Resources:
org.apache.catalina.deploy.NamingResources
Server's Listener:( 监听server事件)
org.apache.catalina.core.AprLifecycleListener
org.apache.catalina.core.JasperListener
org.apache.catalina.mbeans.ServerLifecycleListener
org.apache.catalina.mbeans.GlobalResourcesLifecycleListener
Service:
org.apache.catalina.core.StandardService
Executor:
org.apache.catalina.core.StandardThreadExecutor
Engine:
org.apache.catalina.core.StandardEngine
Connector:
org.apache.catalina.connector.Connector

【tomcat-流程】
3.StandardServer启动StandardService,StandardService启动Connector,
Connector启动Http11Protocol,Http11Protocol启动JIoEndpoint,
JioEndpoint启动server Socket,listern 8080端口,处理http请求

4.Http11Processor
Processes HTTP requests.
由http11ConnectionHandler调用,Http11ConnectionHandler由JioEndpoint中的Work 调用

5.A connector passes the request and reponse objects to the Container by calling the Container interface's invoke method
public void invoke(Request request, Response response)
        throws IOException, ServletException;

inside the invoke method ,the container loads the servlet class,call its sevice method ,manage sessions,etc.

6.Connector 方法initialize中
// Initializa adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
adapter通过protocolHandler(Http11Protocol)传给Http11Processor,
Http11Processor解析,create request和response,通过adapter传送给Container

7.Tomcat使用Pipeline模式在各层容器间传递请求,将请求通过管道依次通过Engine,Host,Context和 Wrapper。另外,每一个容器  
都可以设置一系列的Valve去对请求进行拦 截,就像管道中的阀一样对请求的行为进行一些干涉。


2010-3-31
【tomcat-流程】
1.tomcat的pipeline/valve是标准的责任链模式,每个级别的容器中pipeline所有的valve都完成动作后会将 request/response传到下一个容器的pipeline中的valve,
这样一直传递下去直到Wrapper的BaseValve.
Ps:每个容器的BaseValve会调用下个容器的起始valve

2.StandardEngine
属性Pipeline  pipeline = new StandardPipeline(this);
构造函数里会设置最底层的阀门
pipeline.setBasic(new StandardEngineValve());
如果需要设置新阀门处理需求,只需要调用 pipeline.addValve(Valve valve);

3.CoyoteAdapter中会执行
connector.getContainer().getPipeline().getFirst().invoke(request, response);
该行代码会一层一层调用添加的阀门,处理下去.

2010-4-1
【tomcat-流程】
1.jk插件负责tomcat和其它http容器进行通信

2.连接器协议AJP/1.3是tomcat用来与其它http容器进行连接的协议

3.把指定Context的classloader付给当前线程。
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); 这样request就只看见指定的context下面的classes和jar包,而看不见tomcat本身的类。

2010-4-7
【tomcat-socke与worker线程】
/**
* Process an incoming TCP/IP connection on the specified socket.  Any
* exception that occurs during processing must be logged and swallowed.
* <b>NOTE</b>:  This method is called from our Connector's thread.  We
* must assign it to our own thread so that multiple simultaneous
* requests can be handled.
* @param socket TCP socket to process
*/
synchronized void assign(Socket socket) {
// Wait for the Processor to get the previous Socket
while (available) {
try {
              wait();
       } catch (InterruptedException e) {
       }
    }
    // Store the newly available Socket and notify our thread
    this.socket = socket;
    available = true;
    notifyAll();
}

/**
* Await a newly assigned Socket from our Connector, or <code>null</code
* if we are supposed to shut down.
*/
private synchronized Socket await() {
// Wait for the Connector to provide a new Socket
while (!available) {
try {
wait();
} catch (InterruptedException e) {
}
}
    // Notify the Connector that we have received this Socket
    Socket socket = this.socket;
    available = false;
    notifyAll();
return (socket);
}
连接器线程调用worker类的assign类,worker类的执行线程run方法会调用await方法获取socket,通过 available变量的设置和wait/notify方法来协调彼此的操作。当连接器线程未传输socket,worker类线程就执行wait等待,
当worker类执行线程在处理忙的时候,连接器线程wait。

posted @ 2010-06-21 10:28 余坚 阅读(831) | 评论 (0)编辑 收藏

[版本控制]svn命令行笔记

svn命令行操作

1.svn update 更新 (简写up)
svn update -r 500 test.java(将版本库中的文件test.java还原到版本500)

2.svn commit -m"u" (简写ci)
提交变更的文件

3.查看文件信息svn info path
查看文件内容svn cat path

4.svn status path
会目录下的文件和子目录的状态,正常状态的则不显示,很正常,不然在项目根目录执行,将会罗列出一大堆文件了
显示的状态信息中?:表示不在svn的控制中 M:表示本地文件被修改过 C:表示本地文件与服务器文件发生冲突(如果不带-u选项,即时冲突也不会显示) A:表示预定要加入到版本库 K:表示被锁定
'!'  表示丢失,一般是将受控文件直接删除导致
svn st -u path   -u选项表示不仅仅本地,服务器上的变更也将会显示

5.删除文件
svn delete test.java 然后再svn ci -m 'delete‘,将在本地和服务器上都删除该文件

6. 添加新文件
svn add test.java(添加test.java)  然后再svn ci -m"add",将再服务器上添加该文件
如果不执行commit操作,服务器上将不会添加

7.svn: Commit failed (details follow):
svn: Directory '/home/yuyu/f/workspace/ouyu/WebRoot/WEB-INF/classes' is missing
解决方法:svn update /home/yuyu/f/workspace/ouyu/WebRoot/WEB-INF/classes

8. 服务器覆盖本地文件
执行svn revert test.java命令撤销自己的修改,再执行update,
则服务器的文件会覆盖自己修改的文件。

9.svn list path(or url)
显示目标下的文件和目录列表。

10.svn diff
svn diff path                 查看文件的不同处(本地版本的变更比较)
svn diff -r n1:n2 path   n1和n2版本的同一文件比较

11. 发生冲突
执行svn update后会紧跟选择性操作,一种直接选择解决,修改文件;
一种选择推迟解决,则之后需要执行svn resolved test.java,才能最终commit

posted @ 2010-06-21 10:02 余坚 阅读(892) | 评论 (0)编辑 收藏

2010年5月10日

javaio-WriteStringToFile

package cn.yu.test.io;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
/**
 * WriteStringToFile
 * 
@version 1.0
 * @date 2010/5/10
 *
*/
public class WriteStringToFile {
    
public static void main(String[] args) {
        
try {
            String aString 
= "Hello你好";
        
            FileWriter fw 
= new FileWriter("c:/out.fw.txt");
            fw.write(aString);
            fw.close();   
//默认gbk编码9字节
            ////////////////////////////////////////////////////////////////////////////
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:/out.osw.txt"),"UTF-8");
            osw.write(aString);
            osw.close();  
//utf-8编码 11字节
            
            
///////////////////////////////////////////////////////////
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("c:/out.dos.txt"));
            dos.writeChars(aString);
            dos.close();  
//14个字节, 每个字符用该字符2字节的unicode表示
            //////////////////////////////////////////////////////////////
            PrintStream ps = new PrintStream(new FileOutputStream("c:/out.ps.txt"));
            ps.print(aString);
            ps.close(); 
//默认gbk编码9字节
            //////////////////////////////////////////////
            PrintWriter pw = new PrintWriter(new FileOutputStream("c:/out.pw.txt"));
            pw.print(aString);
            pw.close(); 
//默认gbk编码9字节  
             ///////////////////////////////////////////////
            RandomAccessFile ra = new RandomAccessFile("c:/out.fa.txt""rw");
            ra.writeUTF(aString); 
//
            ra.close(); //13个字节 ,前两个直接表示一个无符号整数,值是这个字符串的字符所需要的字节数
            ////////////////////////////////////////////////
            RandomAccessFile ra2 = new RandomAccessFile("c:/out.fa2.txt""rw");
            ra2.writeChars(aString);
            ra2.close(); 
//14个字节, 每个字符用该字符2字节的unicode表示
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

posted @ 2010-05-10 13:57 余坚 阅读(325) | 评论 (0)编辑 收藏

2010年5月6日

perl记事本

perl记事本

1. 'yu' x 3    #  print yuyuyu

2.print "yu jian ${age}s" # 加{}  促使变量不会变成$ages

3. 4 ** 2  #4的平方

4.(1..5) #  -->(1,2,3,4,5)

5.qw ( yu jian's book)  # 简洁,更少输入

6.($yu,$jian)=($jian,$yu) # 值互换

7.($yu,$jian)=qw(yu jian) # 赋值

8.@array=qw/yu jian/; #数组 

9.@array=5..9;
$yu=pop(@array)  # $yu=9  and @array=(5,6,7,8)
$yu=pop @array  # $yu=8  and @array=(5,6,7)

10.如果数组为空 pop不会报错,什么也不返回,直接返回undef

11.push(@array,0)  # @array=(5,6,7,0)

12.pop和push都操作数组末尾

13.shift和unshift是对数组的开始端操作

14.$_  perl的默认变量
for(1...10){
    print $_;  # $_ = 1 or 2 or 3...
}

15.perl会正确处理上下文
@people=qw{yu gao};
@list=@people #得到列表
$n=@people #得到人数2

16.scalar @array #scalar 导致切换为标量上下文
@array =qw/yu jian gao su/;
print "love is ".@array."\n"; #love is 4
print "love is ",@array,"\n"; #love is yujiangaosu
print "love is ".scalar @array,"\n";#love is 4

17.@lines=<STDIN> #在列表上下文中读取标准输入


18.chomp 去掉所有的换行符 chmop(@lines)

19.调用自定义方法  &methodName;

20.sub max{
    if(@_!=2){  #判断参数个数
        print "waning!!!";
        return -1;
    }
    my($m,$n); #创建新的所有变量
    ($m,$n)=@_; #将参数赋值给变量
    if($m > $n){$m}else{$n}
}

21.my($num)=@_ #获取数组的第一个元素
    my $num=@_ #数组的数量

22.use strice ; #强制使用一些严格的良好的程序语言规则

23.sub division{
        $_[0] / $_[1]; #第一个参数和第二个参数
}

24.@ARGV=qw# file1 file2 #;# 强制让砖石操作符读取这两个文件
while(<>){
    chomp;
    print "It was $_\n":
}

25.printf "Hello, %s; your password in %d days!\n",$user,$days;#格式化输出
%d 整数 %g 浮点数

27.die处理错误输出

28.读取文件
open CONFIG,"c:/test.txt";
while(<CONFIG>){
print $_."\n";
}

29. say == print  xxxx ."\n"  # say  相当 等于print 加换行符

30.hash
$family_name{"fred"}="flint";
$family_name{"bar"} ="rubble";

%family_name("fred","flint","bar","rubble");

my %family_name=(
    "fred" => "flint",
    "bar" => "rubblle";
)

my @k=keys %family_name;
my @v=values %family_name;  #return array

31.
each函数
while( ($key,$value)=each %family_name ){
        print "$key => $value\n";
}
exists函数
if(exists $family_name("dino")){

}
delete函数
delete $family{"fred"};

32.\1,\2使用反向引用
$_=""abba;
if(/(.)\1/){#匹配到 bb
    print "it matched";
}

33. \d = [0-9]
\w = [A-Za-z0-9_]
[^\d] 非数字
[^\w]非词
[^\s]非空白字符

34./yes/i  # /i 不区分大小写

35./s 匹配任意字符 , 不包括换行

36./x运行加入空白,便于阅读理解

37.m//模式匹配搜索功能
S/// 模式匹配替换功能
/g 全局替换

38.@fields = split /separator/ , $string;

39.my $result = join $glue,@pieces;
my $x = join ":",4,5,6; # $x = "4:5:6";

40.*贪婪 *?非贪婪版本

41.从命令行进行在线编辑
perl -p -w -e "s/ran/ra/g" fred.dat
-p 打印  -n 去掉自动打印  -w 打开警告选项  -e 表示后面更得是代码,而不是普通的参数

42.last 类似break 

43.my $stuff="Howdy world!";
my $where=index($stuff,"wor"); # $where =  6

44.my $mineral=substr("Fred J. Flintstone",8,5); # 值为Flint

45.智能匹配对应不同德操作数,不同德处理方式
%a ~~ %b         哈希的键是否一致
%a ~~@b          至少%a中的一个键在列表@b之中
%a ~~ /Fred/     至少一个键匹配给定的模式
%a ~~ 'Fred'      哈希中某一指定键$a{'Fred'} 是否存在
@a ~~ /Fred/     有一个元素匹配给定的模式
@a ~~ 123        至少有一个元素转化为数字后事123

$name ~~ undef  $name确实尚未定义

46.system 启动子进程
system "date";

14.my $tarfile="some*.tar";
my @dirs=qw(fred|flinet<bar&rubble> betty);
system "tar"."cvf",$tarfile,@dirs;  带参数的系统命令调用

47.system的所有语法对exec都适用
执行exec类似goto语句,跳转到另个进程进行执行,当前perl进程会关闭
chdir "/tmp" or die "cannot chdir /tmp: #!";
ecec "bedrock","-o","args1",@ARGV;

48.$ENV{'PATH'}="/home/rootbeer/bin:$ENV{'PATH'}";
delete $ENV{'IFS'};
my $make_result= system "make";
改修改并不能影响shell或者其他父进程

49.my $now =`date`;
print "The time is now $now";
魔力反引号调用进程

50.perl -p -i.old -e "s/try//g" test.txt 替换文件中的内容,重新写入文件, 原文件备份为old后缀的文件.
windows下要用双引号

51.

posted @ 2010-05-06 14:29 余坚 阅读(248) | 评论 (0)编辑 收藏