实时监听页面变化的Chrome Extenstion案例

工程名Chrome_Extenstion_Bider
适用于chrome内核的浏览器
目录结构

1
2
3
4
5
6
7
Chrome_Extenstion_Bider/Bider/css
|-Chrome_Extenstion_Bider/Bider/css/common.css
Chrome_Extenstion_Bider/Bider/include
|-Chrome_Extenstion_Bider/Bider/include/jquery-1.11.0.min.js
Chrome_Extenstion_Bider/Bider/scripts
|-Chrome_Extenstion_Bider/Bider/scripts/main.js
Chrome_Extenstion_Bider/Bider/manifest.json

Chrome_Extenstion_Bider/Bider/manifest.json

1
2
3
4
5
6
7
8
9
10
11
12
{
    "manifest_version": 2,
    "name": "Bider",
    "version": "0.1.0",
    "description": "Bider.",
    "content_scripts": [{
        "matches": ["http://www.hillmatrix.com/*"],
        "css": ["css/common.css"],
        "js": ["include/jquery-1.11.0.min.js", "scripts/main.js"],
        "all_frames": true
    }]
}

Chrome_Extenstion_Bider/Bider/css/common.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#ls_box {
    position: absolute;
    width: 500px;
    height: 300px;
    background-color: #fff;
    border-radius: 5px;
    border: 1px solid #ccc;
    left: 50%;
    top: 50%;
    margin-left: -250px;
    margin-top: -150px;
    z-index: 99999;
    padding: 10px;
}

#ls_box h3 {
    height: 30px;
    line-height: 30px;
    border-bottom: 1px solid #ccc;
    margin: 0 0 5px 0;
    padding: 0;
}

#ls_box #ls_panel {
    height: 105px;
    margin: 10px 0;
}

#ls_box #ls_panel #ls_ms {
    color: blue;
    display: inline-block;
}

#ls_box #ls_panel #ls_warn {
    color: red;
    width: 312px;
    text-align: right;
    display: inline-block;
}

#ls_box #ls_panel #ls_list {
    overflow-x: hidden;
    overflow-y: scroll;
    height: 90px;
    margin: 0;
    padding: 0;
}

#ls_box #ls_panel #ls_list ul li {
    height: 24px;
    line-height: 24px;
    border-bottom: 1px dotted #efefef;
}

#ls_box #ls_panel #ls_list ul li span {
    float: right;
    cursor: pointer;
}

#ls_box #ls_form {
    background-color: #efefef;
    border-radius: 5px;
    padding: 10px;
}

#ls_box #ls_form label {
    padding: 0 5px;
    display: inline-block;
}

#ls_box #ls_form #ls_panel {
    padding: 0 5px;
}

#ls_box #ls_form input {
    width: 120px;
    padding: 5px 10px;
    display: inline-block;
}

#ls_box #ls_form #ls_btnc {
    width: auto;
    padding: 5px 10px;
    text-align: center;
}

#ls_box #ls_form button {
    padding: 5px 10px;
    display: inline-block;
    margin-right: 20px;
}

Chrome_Extenstion_Bider/Bider/include/jquery-1.11.0.min.js

Chrome_Extenstion_Bider/Bider/scripts/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
var main = {
    flag: false,
    flash: 200,
    money: 0,
    // 初始化
    init: function(target) {
        // 创建界面
        this.create(target);

        // 获取页面数据
        this.listenPage();

        //绑定按钮
        this.bindBtn();
    },

    //绑定BTN
    bindBtn: function() {
        _this = this;

        var ls_start = $('#ls_start');
        var ls_stop = $('#ls_stop');
        var ls_max = $('#ls_max');
        var ls_step = $('#ls_step');

        if (!_this.flag) {
            ls_stop.attr("disabled", "disabled");
            ls_start.removeAttr("disabled");
            ls_max.removeAttr("disabled");
            ls_step.removeAttr("disabled");
        } else {
            ls_start.attr("disabled", "disabled");
            ls_stop.removeAttr("disabled");
            ls_max.attr("disabled", "disabled");
            ls_step.attr("disabled", "disabled");
        }

        ls_start.bind("click", function() {
            if (!_this.flag) {
                ls_start.attr("disabled", "disabled");
                ls_stop.removeAttr("disabled");
                ls_max.attr("disabled", "disabled");
                ls_step.attr("disabled", "disabled");
                _this.flag = true;
            }
        });

        ls_stop.bind("click", function() {
            if (_this.flag) {
                ls_stop.attr("disabled", "disabled");
                ls_start.removeAttr("disabled");
                ls_max.removeAttr("disabled");
                ls_step.removeAttr("disabled");
                _this.flag = false;
            }
        });
    },

    //动态竞标价
    activePrice: function() {
        _this = this;
        var page_sendbtn = $('#bidBtnId');
        var page_pi = $('.TB_priceInput');

        var ls_max = parseInt($('#ls_max').val());
        var ls_step = parseInt($('#ls_step').val());
        //console.log(_this.flag);
        if (_this.flag && ls_max > 0 && ls_step > 0) {
            var cmoney = parseInt(_this.money);
            var m1 = cmoney + ls_step;
            var m2 = ls_max + ls_step;
            if (m1 <= ls_max) {
                page_pi.val(m1);
                $('#ls_warn').html('当前出价:' + m1);
            } else if (cmoney == ls_max) {
                page_pi.val(m2);
                $('#ls_warn').html('当前出价(MAX+1):' + m2);
            } else {
                $('#ls_warn').html('已经超出最大限额+1步长,停止竞标');
                $('#ls_stop').delay(500).click();
            }
        } else if (!_this.flag) {
            $('#ls_warn').html('自动竞标系统停止中');
        } else {
            $('#ls_warn').html('请设置正确的参数');
        }
    },

    // 创建界面
    create: function(target) {
        var _html = '<div id="ls_box">' + '<h3>' + 'Bider' + '</h3>' + '<div id="ls_panel">' + '<div>毫秒计数器:<span id="ls_ms">0</span><span id="ls_warn"></span></div>' + '<ul id="ls_list">正在加载数据...' + '</ul>' + '</div>' + '<div id="ls_form">' + '<div id="ls_panel">' + '<h3>' + '策略' + '</h3>' + '<label>' + '最高价: ' + '</label>' + '<input type="text" id="ls_max" value="0" />' + '<label>' + '步长: ' + '</label>' + '<input type="text" id="ls_step" value="10" />' + '<br />' + '<div id="ls_btnc"><button id="ls_start">开始</button><button id="ls_stop">停止</button></div>' + '</div>' + '</div>' + '</div>';
        target.closest("body").append(_html);
    },

    /**
     * 监听页面数据变化
     */

    listenPage: function() {
        _this = this;
        var page_countDown = $('#countDown_counting'); //the element I want to monitor

        page_countDown.bind('DOMCharacterDataModified DOMSubtreeModified', function(e) {
            var page_cp = $('#currentPrice').html();
            var price_arr = page_cp.split("/");
            var page_cp_total = price_arr[0];
            var page_cp_single = price_arr[1];
            _this.money = page_cp_single;

            var dataList = ['当前状态:总价:' + page_cp_total + ',单价:' + page_cp_single];
            dataList.push('倒计时:' + $('#countDown_counting').html() + '秒');
            _this.printData(dataList);
        });
    },

    /**
     * 将已有数据写到页面上
     */

    printData: function(dataList) {
        if (!dataList || dataList.length == 0) {
            $("#ls_list").html('<p>获取数据失败</p>');
            return;
        }
        // 遍历对象,构建输出html
        var _html = [];
        for (var i in dataList) {
            _html.push('<li>' + dataList[i] + '</li>');
        }
        $("#ls_list").html(_html.join(''));
    },
}

var ext_c = $('#countDown_counting');
//console.log(ext_c[0]);
if (ext_c[0] != undefined) {
    main.init(ext_c);
    var ext_t = parseInt(ext_c.html()) * 1000;
    var ext_isclick = false;
    ext_c.bind('DOMCharacterDataModified DOMSubtreeModified', function(e) {
        if ($.isNumeric($(this).html())) {
            ext_t = parseInt($(this).html()) * 1000;
        }
    });

    var ext_ms = function() {
            var ext_s = 0;
            if (ext_t > 0) {
                ext_t -= 17;
                ext_s = ext_t;
            }
            if (ext_c.html() == '0') {
                ext_c.unbind();
                clearInterval(ext_run);
            }
            console.log(ext_s);
            $('#ls_ms').html(ext_s);
            if (ext_s <= main.flash && !ext_isclick && main.flag) {
                ext_isclick = true;
                console.log('倒计时剩余:' + ext_s + '毫秒,提交请求!');
                ext_c.unbind();
                clearInterval(ext_run);
                $('#bidBtnId').click();
            }
            main.activePrice();
        }

        //毫秒级计数器
    var ext_run = setInterval(ext_ms, 15);
}

Chrome_Extenstion_Bider

JS原生方法监听DOM结构改变事件

https://developer.mozilla.org/en-US/docs/XUL/Events#Mutation_DOM_events

1
2
3
document.addEventListener('DOMNodeInserted',function(){alert(1)},false);
document.addEventListener('DOMAttrModified',function(){alert(1)},false);
document.addEventListener('DOMNodeRemoved',function(){alert(1)},false);

变动事件包括以下不同事件类型:

1
2
3
4
5
6
7
DOMSubtreeModified; //在DOM结构中发生任何变化时触发
DOMNodeInserted; //在一个节点作为子节点被插入到另一个节点中时触发
DOMNodeRemoved; //在节点从其父节点中被移除时触发
DOMNodeRemovedFromDocument; //在一个节点被直接从文档中移除或通过子树间接从文档中移除之前触发
DOMNodeInsertedIntoDocument; //在一个节点被直接插入文档或通过子树间接插入文档之后触发
DOMAttrModified; //在属性被修改之后触发
DOMCharacterDataModified; //在文本节点的值发生变化时触发

SSH反向隧道链接及Autossh守护进程的使用

1.建立SSH反向隧道链接:

A要控制B

A主机:外网,ip:123.123.123.123,sshd端口:2221
B主机:内网,sshd端口:2223

无论是外网主机A,还是内网主机B都需要跑ssh daemon

1.1.首先在B上执行

1
$ ssh -NfR 1234:localhost:2223 user1@123.123.123.123 -p2221

这句话的意思是将A主机的1234端口和B主机的2223端口绑定,相当于远程端口映射(Remote Port Forwarding)。

这里每次需要输入A主机user1的登陆密码,后面会讲到解决办法。

1.2.这时在A主机上sshd会listen本地1234端口

1
2
3
$ ss -ant
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
LISTEN     0      128               127.0.0.1:1234                     *:*

1.3.像平时一样连接到A主机的1234端口就可以控制内网B主机了

1
$ ssh localhost -p1234

2.这种反向连接(Reverse Connection)不稳定,可能随时断开,需要内网主机B再次向外网A发起连接,将自动连接ssh的应用Autossh制作成daemon,每次开机自动运行,并且可以使用service进行开关控制。

在此之前还要解决之前的一个问题,那就是每次内网主机B连接外网主机A时都需要输入密码,这个问题ssh本身是提供另外一种验证方式——通过密钥验证用户身份,实现自动登录。

2.1.在内网B主机上生产公钥和私钥

1
2
3
4
$ ssh-keygen
...(一直按Enter,最后在~/.ssh/下生成密钥)
$ ls ~/.ssh/
id_rsa id_rsa.pub known_hosts

2.2.复制B主机上生成的id_rsa.pub公钥到外网A主机上,并将内容加入到~/.ssh/authorized_keys

ssh-copy-id命令添加到远程主机的自动验证

1
$ ssh-copy-id user1@123.123.123.123

2.3.制作Autossh的daemon

使用vim编辑,如果没有则新建

SysV:/etc/inid.d/autossh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/bin/bash  
### BEGIN INIT INFO  
#  
# Provides:  location_server  
# Required-Start:   $local_fs  $remote_fs  
# Required-Stop:    $local_fs  $remote_fs  
# Default-Start:    2 3 4 5  
# Default-Stop:     0 1 6  
# Short-Description:    initscript  
# Description:  This file should be used to construct scripts to be placed in /etc/init.d.  
#  
### END INIT INFO  
 
## Fill in name of program here.  
PROG=&quot;autossh&quot;  
PROG_PATH=&quot;/usr/bin&quot; ## Not need, but sometimes helpful (if $PROG resides in /opt for example).  
PROG_ARGS=&quot;-M 5678 -NR *:2222:127.0.0.1:8080 root@123.123.123.123 -p 22&quot;  
PID_PATH=&quot;/var/run/&quot;  
 
start() {  
    if [ -e &quot;$PID_PATH/$PROG.pid&quot; ]; then  
        ## Program is running, exit with error.  
        echo &quot;Error! $PROG is currently running!&quot; 1&amp;gt;&amp;amp;2  
        exit 1  
    else  
        ## Change from /dev/null to something like /var/log/$PROG if you want to save output.  
        $PROG_PATH/$PROG $PROG_ARGS 2&amp;gt;&amp;amp;1 &amp;gt;/var/log/$PROG &amp;amp;  
    $pid=`ps ax | grep -i 'location_server' | sed 's/^[0−9]{1,}.*/\1/g' | head -n 1`  
 
        echo &quot;$PROG started&quot;  
        echo $pid &amp;gt; &quot;$PID_PATH/$PROG.pid&quot;  
    fi  
}  
 
stop() {  
    echo &quot;begin stop&quot;  
    if [ -e &quot;$PID_PATH/$PROG.pid&quot; ]; then  
        ## Program is running, so stop it  
    pid=`ps ax | grep -i 'location_server' | sed 's/^[0−9]{1,}.*/\1/g' | head -n 1`  
    kill $pid  
         
        rm -f  &quot;$PID_PATH/$PROG.pid&quot;  
        echo &quot;$PROG stopped&quot;  
    else  
        ## Program is not running, exit with error.  
        echo &quot;Error! $PROG not started!&quot; 1&amp;gt;&amp;amp;2  
        exit 1  
    fi  
}  
 
## Check to see if we are running as root first.  
## Found at http://www.cyberciti.biz/tips/bash-root-user-check-script.html  
if [ &quot;$(id -u)&quot; != &quot;0&quot; ]; then  
    echo &quot;This script must be run as root&quot; 1&amp;gt;&amp;amp;2  
    exit 1  
fi  
 
case &quot;$1&quot; in  
    start)  
        start  
        exit 0  
    ;;  
    stop)  
        stop  
        exit 0  
    ;;  
    reload|restart|force-reload)  
        stop  
        start  
        exit 0  
    ;;  
    **)  
        echo &quot;Usage: $0 {start|stop|reload}&quot; 1&amp;gt;&amp;amp;2  
        exit 1  
    ;;  
esac

php多版本共存的配置(nginx+php5.2 & 5.5 & 5.6)

首先安装好不同版本的php

1
2
3
root@ubuntu:/usr/local# ls
autoconf-2.13 bin curl etc freetype games include lib man mysql nginx php php5.2 php5.6 sbin share src zend zend52
root@ubuntu:/usr/local#

配置
以防修改配置文件出错,可以先做好备份

1
vim etc/php-fpm.conf

需要注意下面几处配置

1
<value name="listen_address">127.0.0.1:9100</value>

这个表示php的fastcgi进程监听的ip地址以及端口。因为本地已经有一个5.6版本了所以这里改成9100 nobody

1
<value name="group">nobody</value>

表示php的fastcgi进程以什么用户以及用户组来运行,默认该行是注释掉的,需要打开

1
<value name="display_errors">0</value>

是否显示php错误信息

1
<value name="max_children">5</value>

最大的子进程数目
运行php-fpm: php-fpm用一个程序来控制fastcgi进程,这个文件在$PREFIX/sbin/php-fpm

php5.6版本的php-fpm.conf文件

成功运行php-fpm后
nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
server{
    listen 80;
    server_name php5.2.com;
    index index.html index.htm index.php;
    root /home/wwwroot/php5.2;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9100;      #这里把fastcgi_pass 改到本地的9100端口
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        include fastcgi_params;
    }
}

启动

1
/usr/local/php5.2/sbin/php-fpm start

php5.3之后官方收录了php-fpm,所以之后的版本不用加start参数
再把启动命令写入/etc/rc.local文件中,开机启动。
到此实现以不同域名访问同一主机。