用SSH Tunnel临时突破跨机房的限制

[文章作者:陈臻 本文版本:v1.0 最后修改:2008.11.20 转载请注明原文链接:http://www.54chen.com/c/94]

今天遇到一个测试机的环境要连通生产机的pgsql,后来用了SSH Tunnel,记录一下:
在hostA中执行
$ssh -N -f -L 9000:hostB:8080 user@hostB
N 不用建立shell
f 连线后在背景执行
L 连接
这样在hostB中执行localhost:8080相当于访问hostA,也就建立了B到A的信任连接,突破了限制。
算是一句话的备忘,不过冒似不止一句了。

一种在sns系统中统一应用平台的方式

SNS:概念略,像开心、校内等,今天要研究的是他们的应用程序的实施方案。

如果你和我一样在考虑如何简单的完成一套共享的能用的应用可扩展平台(看上去有点绕,不过它的确就是这样的)。

首先,我们需要在apache的rewrite上做一点手脚:

RewriteEngine On

 

RewriteRule ^/+apps/([^/]+)$ /apps/app.php?%{QUERY_STRING}&__app_path=$1 [L,PT]

RewriteRule ^/+apps/([^/]+)/+([^/]*)$ /apps/app.php?%{QUERY_STRING}&__app_path=$1&__app_page=$2 [L,PT]

这样,就可以将一个请求为http://url/apps/a.php?a=x的地址发给http://url/apps/app.php?a=x&__app_path=apps/a.php

请注意,这里多出了两个GET变量!

第二步,我们需要建立一个框架的入口,也就是实际访问的时候用的apps/app.php

apps/app.php(以下代码只供参考使用,未验证bug)

<?php

$__app_path = trim($_GET('__app_path'));

$__app_page = trim($_GET('__app_page'));

/*

* 此处可添加一个CONFIG

*/

if(!$__app_page)

$__app_page = "index.php";

$file_path = "./".$__app_path."/".$__app_page;

include($file_path);

?>

第三,建立我们的hello world!

进入apps/hello(没有则创建之),建立新文件index.php

<?php

echo 'hello world!';

?>

第四步,也许还可以扩展

这一步所考虑的是,如果应用的代码不在同一个服务器里,也就是说,跨域名的应用服务,应当怎么做。

修改apps/app.php

使用curl扩展这一功能,又或者直接iframe?这涉及更高要讨论的东西,例如权限和数据。

短片:叫你别往这儿舔[48秒]

Svn里的branch、trunk、tag的用处

[文章作者:陈臻 本文版本:v1.0 最后修改:2008.11.12 转载请注明原文链接:http://www.54chen.com/c/83]

这只是个说明,你不按说明来办事也不会怎么样,svn照样工作得很好。

branches:分枝

当多个人合作(Sally和John)时,可能有这样的情况出现:John突然有个想法,跟原先的设计不太一致,可能是功能的添加或者日志格式的改进等等,总而言之,这个想法可能需要花一段时间来完成,而这个过程中,John的一些作可能会影响Sally的工作,John从现有的状态单独出一个project的话,又不能及时得到Sally对已有代码做的修正,而且出来的话,John的尝试成功时,跟原来的合并也存在困难。这时最好的实践方法是使用branches。John建立一个自己的branch,然后在里面实验,必要的时候从Sally的trunk里取得更新,或者将自己的阶段成果汇集到trunk中。(svn copy SourceURL/trunk \ DestinationURL/branchName \ -m "Creating a private branch of xxxx/trunk." )

trunk:主干

主干,一般来说就是开发的主要呆的地方,

tag:

在经过了一段时间的开发后,项目到达了一个里程碑阶段,你可能想记录这一阶段的代码的状态,那么你就需要给代码打上标签。(svn cp file:///svnroot/mojavescripts/trunk \ file:///svnroot/mojavescripts/tags/mirrorutils_rel_0_0_1 \
-m "taged mirrorutils_rel_0_0_1")

另有一说,无所谓谁对谁错。

trunk:表示开发时版本存放的目录,即在开发阶段的代码都提交到该目录上。

branches:表示发布的版本存放的目录,即项目上线时发布的稳定版本存放在该目录中。

tags:表示标签存放的目录。

在这需要说明下分三个目录的原因,如果项目分为一期、二期、三期等,那么一期上线时的稳定版本就应该在一期完成时将代码copybranches上,这样二期开发的代码就对一期的代码没有影响,如新增的模块就不会部署到生产环境上。而branches上的稳定的版本就是发布到生产环境上的代码,如果用户使用的过程中发现有bug,则只要在branches上修改该bug,修改完bug后再编译branches上最新的代码发布到生产环境即可。tags的作用是将在branches上修改的bug的代码合并到trank上时创建个版本标识,以后branches上修改的bug代码再合并到trunk上时就从tagsversionbranches最新的version合并到trunk,以保证前期修改的bug代码不会在合并。

Perl Workshop 2008 归来

perl workshop 2008 归来

1.四十分钟的演讲中agent的演讲最具有吸引力,老何的演讲最生动。

2.关于0penResty的角色部分没讲完是个遗憾,以后实际运用的时候还得在公司问agent。

3.english的talk也会站着听了一会儿,完全听不懂。

4.照片欠奉

一句话记录备忘

apache或者yapache的虚拟主机设置时,出现许多个VirtualHost在一台机器时,只显示第一个VirtualHost的目录,这时需要在conf中增加一行NameVirtualHost *

Perl笔记

[文章作者:陈臻 本文版本:v1.2 最后修改:2008.11.5 转载请注明原文链接:http://www.54chen.com/c/75]

系统学习perl,基础问题复习期间,先提问题,再回答

1.@和$和%以及&的区别是什么?

@===

在数组名前加@(后没有中括号)来引用整个数;

$===

标量变量可以存放一个标量值。标量变量的名字由一个美圆符号($)后接Perl 标识符:由字母或下划线开头,后接字母,数字,或者下划线。或者说由字母,数字和下划线组成,但不能由数字开头。大小写是严格区分的:变量$Fred 和变量$fred是不同的;

%===

要引用整个hash,使用百分号(“%”)作为前缀。

%some_hash = (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye\n”);

my %last_name = (
“fred” => “flintstone”,
“dino” => undef,
“barney”=> “rubble”;
“betty”=> “rubble”,
);

&===

可以使用子程序的名字(前面带&)来调用子程序.

2.qw()做什么用的?

qw 表示“quoted words”或者“quoted by whitespace”,作用是将一串包含空格的字符串以空格拆分为字符列表。

3.两种上下文环境分别是?

标量和列表上下文

4.$_等默认的变量名都有哪些及用处?

$_----------------

如果在foreach 循环中省略了控制变量,那Perl 会使用其默认的变量:$_。除了其不寻常的名字外,这和普通变量类似,如
下面代码所示:
foreach(1..10){ #使用默认的变量$_
print “I can count to $_!\n”;
}

@_---------------

这也就是说此子程序参数的第一个值存放在$_[0]中,第二个存放在$_[1],依次类推。但必须强调的是这些变量和$_这个变量没有任何关系,如$dino[3](数组@dino 的一个元素)和$dino 的关系一样。这些参数必须存放在某个数组变量中,而Perl存放在@_这个变量中。

5.chomp()的作用是什么?

去掉换行符(\n)

6.<>的作用是什么?(例如while(<>))

尖括号作(<>)是一种特殊的行输入作。其输入可由用户选择;由于<>通常被用来处理所有的输入,因此在同一个序中重复使用是不正确的。

7.print @array;和print "@array"的区别是什么?

前者输出@array的值,后者输出其个数。

8.my是什么意思?用和不用my有什么区别?

默认情况下,Perl 中所有变量都是全局的;也就是说,这些变量可以在程序的任意部分使用。你也可以任意时候使用my创建私有变量。

9.列出控制循环的几个关键字 next last等及作用?

last 会立刻结束循环。(这同C 语言或其它语言中的“break”语句类似);

有时还不希望结束循环,但本次循环已经结束。这种情况下,next 是非常适用的。它跳到当前循环块的最后面(块内)。next 之后,又会进入下一轮循环(这和C 或者类似语言的“continue”相似);

循环控制的第三个作是redo。它会调到当前循环块的顶端,不进行条件表达式判断以及接着本次循环。(在C 或类似语言中没有这种作。);

 

10.$#rocks是什么意思?

rocks 数组最后一个元素的索引为$#rocks,和数组中元素的
个数是不同的,因为数组中包含元素0。

[中秋零献续集] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part4)getaccess线程内的故事

/***
* Author: cc0cc
* E-mail: cc0cc@126.com
* WebSite: http://www.54chen.com * Date: 11 01 2008
* FileName: Mythread.c
* 这个文件要从Access_Thread看起,因为在上一章节里,我们了解了 pthread_create(&getaccess,NULL,Access_Thread,NULL);创建了一个叫getaccess的线程,正是运行的Access_Thread,在Access_Thread里,将完成一系列的过程,802.1x从这里才真正开始了。
***/
#include <gnome.h>
#include <sys/select.h>
#include "Mythread.h"
#include "connect.h"
#include "support.h"
#include "interface.h"

int i=0;
typedef struct{
                  long    tv_sec;        
                  long    tv_uec;       
              }timeval;
           
gint
keeplink(gpointer data)
{ pthread_t keeptest;
    fd_set readfds;
    timeval timeout={5,0};//设置超时
    BYTE recvbuf[1024];
    BYTE cmd;
    CMD_RECORD *cmd_record;
    int recvlen;
    int index=0;
    BYTE tmp=0;
    send_keeplink_request();//这也在connect.c里,用来构造一个包含指令和验证信息的包并发给服务器
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    if(1!=select(sockfd + 1,&readfds,NULL,NULL,&timeout))
    {//超时
        Acc_Keep_Link=2;
        g_message("1.keep lost,thread keeptest ok!");
        pthread_create(&keeptest,NULL,Keep_Thread,NULL);
        return FALSE;
    }
    recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);
    if (recvlen==-1 ) {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("2.keep lost,thread keeptest ok!");
                    return FALSE;
    }
    amt_decrypt(recvbuf,recvlen);//与认证过程大同小异
    if(0==check_packet(recvbuf,recvlen))
    {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("3.keep lost,thread keeptest ok!");
                    return FALSE;
    }
    cmd_record=get_attr(recvbuf);
    cmd=*recvbuf;
    if(cmd==4)    //收到send_keeplink_request对应的包
    {
        index=0;
        tmp=0;
        for (;(index<8)&&(attr_id[index]);index++) {
            if (attr_id[index]==3) {
                if (attr_val[8*(index+4*index)]!=1) {//发送send_keeplink_request失败
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("4.keep lost,thread keeptest ok!");
                    return FALSE;
                }
            }
        }
        //AfxGetMainWnd()->PostMessage(WM_KEEPLINK_RESULT,KEEPLINK_SUCCESSED,NULL);
        g_message("keeplink result success");
    }
    else
    {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("5.keep lost,thread keeptest ok!");
                    return FALSE;
    }
return TRUE;//至此 全过程结束(当然,你不是按照从上到下读着来的,而是按照我的提示来阅读的话) 未来我会逐步分析connect.c和mdd.c里的几个函数,都是加密和解密的内容,主程序本身的流程关系不大,其中还包含了linux c中使用ASM的方法,敬请关注http://hi.baidu.com/cc0cc
}

void
Link_Thread(void *arg)
guint send_timer;
if(Acc_Keep_Link!=1)return;
g_message("keep thread online!");
send_timer=gtk_timeout_add(30000,keeplink,NULL);//802.1x了,每三十秒发送一个认证请求 看keeplink
从这里看起↓ void
Access_Thread()
{ if(Acc_Keep_Link!=0)return;//这是个全局的标,任何情况下标被修改都应当退出线程
pthread_t keeplink;//这是一个孙线程的名字,根据协议规则需要在认证通过后定时发包
int times=0;//超时次数
fd_set readfds;//这个东东不知道要去补一下网络编程,异步套接字。文件描述符集,select调用时用的 timeval timeout;//设置超时为5秒 这个timeval struct在本文件有定义
timeout.tv_sec=5;
timeout.tv_uec=0;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);   

BYTE recvbuf[1024];
BYTE cmd;
CMD_RECORD *cmd_record;
int recvlen;
int index=0;
BYTE tmp=0;

   
retry://这里没办法,用了个goto 看后面就知道了,大概就是超时两次就置标志位了,最后结束运行
        if (times>=2) {
        Acc_Keep_Link=-1;//ACCESS_FAILED_TIMEOUT;
        return ;
    }
send_access_request();//这是开始发送包给服务器了,将会发送用户名密码MAC等一系列的东西给远端的服务器,另一个文件中(connet.c)将专门来介绍

int rt=select(sockfd + 1,&readfds,NULL,NULL,&timeout);//等着看有没有返回
//g_message("select id :%d",rt);
if(1!=rt)
    {//超时
        g_message("time out this");
        times++;
        goto retry;
    }
//有返回了!
recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);//接受返回
    if (recvlen==-1) {
        g_message("recvfrom faild");
       
    }
    amt_decrypt(recvbuf,recvlen);//将收到的recvbuf里的东西去解密 amt_decrypt是原程序中的解密算法,接收到的数据包得经过本函数解密,将在mdd.c中介绍
    if(check_packet(recvbuf,recvlen)==0&&times<2)//check_packet检查解密amt_decrypt完后的数据包是否符合md5摘要
    {   g_message("check_packet bad here");
        times++;
        goto retry;//check_packet失败则重发数据包
    }
    cmd_record=get_attr(recvbuf);//取出对应的指令变成结构体链表CMD_RECORD
    cmd=*recvbuf;
    if(cmd==2)    //收到send_access_request对应的包
    {
        get_spec_attr(cmd_record);//把结构体链表CMD_RECORD里的东西分进全局变量attr_yy里 马上就要用到,attr_id存了cmd指令
        index=0;
        tmp=0;
       
        for (;(index<0x0A)&&(attr_id[index]!=0);index++) {
           
            if (attr_id[index]==3) {
                tmp=attr_val[8*(index+4*index)];////attr_val给每个命令40字节
            }
        }
        if (tmp==1) {//认证成功!
            //g_message("ok");
            gtk_widget_hide_all (linkwindow);
            Acc_Keep_Link=1;
            pthread_create(&keeplink,NULL,Link_Thread,NULL);//认证成功了,再创建一个线程用来保持连接 这回要去看Link_Thread了
            return;
        }
        else
        {   g_message("server_back_err");
            gtk_widget_hide_all (linkwindow);
            Acc_Keep_Link=-1;
            return ;
        }

    }

}

gint
keeptest(gpointer data)
{ pthread_t keeplink;
i++;
g_message("%d",i);
if (i>10){Acc_Keep_Link=-1;g_message("can't keeplink!");return FALSE;}
    fd_set readfds;
    timeval timeout={5,0};//设置超时
    BYTE recvbuf[1024];
    BYTE cmd;
    CMD_RECORD *cmd_record;
    int recvlen;
    int index=0;
    BYTE tmp=0;
    send_keeplink_request();
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    if(1!=select(sockfd + 1,&readfds,NULL,NULL,&timeout))
    {//超时
        g_message("1.keep lost,thread keeptest for once!");
        return TRUE;
    }
    recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);
    if (recvlen==-1 ) {
                    g_message("2.keep lost,thread keeptest for once!");
                    return TRUE;
    }
    amt_decrypt(recvbuf,recvlen);
    if(0==check_packet(recvbuf,recvlen))
    {
                    g_message("3.keep lost,thread keeptest for once!");
                    return TRUE;
    }
    cmd_record=get_attr(recvbuf);
    cmd=*recvbuf;
    if(cmd==4)    //收到send_keeplink_request对应的包
    {
        index=0;
        tmp=0;
        for (;(index<8)&&(attr_id[index]);index++) {
            if (attr_id[index]==3) {
                if (attr_val[8*(index+4*index)]!=1) {//发送send_keeplink_request失败
                    g_message("4.keep lost,thread keeptest for once!");
                    return TRUE;
                }
            }
        }
            g_message("keeptest result success");
            Acc_Keep_Link=1;
            pthread_create(&keeplink,NULL,Link_Thread,NULL);
            return FALSE;       
    }
    else
    {
                    g_message("5.keep lost,thread keeptest for once!");
                    return TRUE;
    }

return FALSE;
}

void
Keep_Thread()
{guint send_timer;
    if(Acc_Keep_Link!=2)return;
    send_timer=gtk_timeout_add(10000,keeptest,NULL);
/***
* Author: cc0cc
* E-mail: cc0cc@126.com
* WebSite: http://www.54chen.com * Date: 11 01 2008
* FileName: Mythread.c
***/