win10安装openssl

下载安装

openssl官网:https://www.openssl.org/

openssl下载地址:http://slproweb.com/products/Win32OpenSSL.html

下载Win64 OpenSSL v1.1.0e(win10 64位),点击依次点击下一步,即可完成安装;

设置环境变量

找到“系统->高级系统设置->环境变量”窗口里面的系统变量;

添加变量名为“OPENSSL_HOME”,变量值:“C:\OpenSSL-Win64\bin”(根据本机openssl安装目录配置),然后在变量名为“Path”中添加“%OPENSSL_HOME%”

如图:

配置1

配置2

注意:设置完环境变量后的cmd窗口必须重新打开,设置的环境变量才会起作用,否则依然提示命令不可用。

使用WinSCP软件在windows和Linux中进行文件传输

官方的解释:WinSCP 是一个 Windows 环境下使用 SSH 的开源图形化 SFTP 客户端。同时支持 SCP 协议。它的主要功能就是在本地与远程计算机间安全的复制文件等。

官网网站:http://winscp.net/eng/docs/lang:chs

下载地址:http://winscp.net/eng/download.php

Portable executables是绿色版,不需要安装。
下载完成之后打开可执行文件,填写登录信息,选择协议之后,就可以进行图形化管理了。

配置

我们只需要填写3个地方:1. host name 2.user name 3.password。hostname是虚拟机的IP地址。
最好是填写root用户时的用户名和密码。点击登陆就进入到Linux系统了
界面中,左边属于windows操作系统的目录,右边属于Linux(CentOS)操作系统的目录。可以用鼠标直接把文件拖过来拖过去的。

参考:

http://www.cnblogs.com/shanyou/archive/2012/08/25/2656753.html

CentOS7使用Jexus部署.NetCore应用

安装Jexus

安装 Jexus 直接使用一下命令即可(需要在root身份下执行):

1
curl https://jexus.org/release/x64/install.sh|sh

安装成功后会提示:OK, Jexus has been installed in /usr/jexus.

发布程序到CentOS7服务器

/usr/local建立www文件夹,将应用程序包放在www文件夹下

如果www不存在,则使用命令创建:

1
mkdir /usr/local/www

将发布好的程序,拷贝到linux系统/usr/local/www文件夹中

参考使用

WinSCP配置

配置Jexus

1
2
3
cd /usr/jexus/siteconf #切换到jexus配置文件目录
cp default test #复制默认配置文件test
vim test #编辑

参考配置:

1
2
3
4
5
6
7
8
9
port=82  # 外部访问的端口号,可以改成你想要的端口号,外部访问通过 ip/域名:端口号 即可访问
roott=/ /usr/local/www/SessionTest/ # 应用程序的工作根目录(全路径)
hosts=* #OR your.com,*.your.com 如果为服务器设置了DNS解析,则可以填写解析到服务器的域名,如:www.myweb.com

AppHost={
cmd=dotnet SessionTest.dll; # 命令,启动Asp.Net Core应用要执行的命令
root=/usr/local/www/SessionTest/; # Asp.Net Core应用程序所在的全路径
port=0;
}
1
2
3
4
5
6
port=0;
# Asp.Net Core应用程序所使用的端口号,如果在程序中使用了UsrUrls自定义端口则使用UsrUrls中填写的端口

(不建议使用UsrUrls自定义端口), 在没有使用UsrUrls自定义端口的情况下端口号设置为 0,Jexus会在运行时与

Asp.Net Core进行"协商"具体使用的端口号,避免多个应用分配端口的麻烦和冲突的风险。

反向代理

1
reproxy=/ http://192.168.1.132:5100,http://192.168.1.130:5100

启动/重启 Jexus

当配置文件编辑完成后使用以下命令对Jexus进行 启动/重启

1
2
3
4
5
# 如果已启动 Jexus:
sh /usr/jexus/jws restart

# 如果未启动 Jexus:
sh /usr/jexus/jws start

开启远程访问端口

开放jexus配置的82端口,以供外部访问:

1
firewall-cmd --zone=public --add-port=82/tcp --permanent

命令含义:

1
2
3
4
5
6
7
--zone #作用域

--add-port=82/tcp #添加端口,格式为:端口/通讯协议

--permanent #永久生效,没有此参数重启后失效

firewall-cmd --reload #重启防火墙

参考:

http://www.cnblogs.com/staneee/p/6852559.html

https://www.jexus.org/

https://www.linuxdot.net/bbsfile-3084

Nginx安装

Yum安装方式

1
2
3
4
5
[root@localhost /]# yum install epel-release
[root@localhost /]# yum install nginx
[root@localhost /]# systemctl start nginx #启动
[root@localhost /]# systemctl enable nginx #可用
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

将nginx 设置为启动系统自动启动nginx

1
[root@localhost /]# echo "/usr/local/nginx/sbin/nginx" >> /etc/rc.local

nginx.conf配置文件

1
2
[root@localhost /]# cd /etc/nginx #定位到nginx安装目录
[root@localhost nginx]# vim nginx.conf #通过vim打开nginx.conf配置文件进行配置

在http节点中,添加配置

1
2
3
4
5
6
7
#设定负载均衡的服务器列表
upstream load_balance_server {
#weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.1.131:5100 weight=5;
server 192.168.1.132:5100 weight=1;
server 192.168.1.130:5100 weight=6;
}

在http->server节点中添加配置:

1
2
3
4
5
6
7
8
9
10
location / {
root html;
index index.aspx index.html index.htm;
#其中load_balance_server 对应着upstream设置的集群名称
proxy_pass http://load_balance_server;
#设置主机头和客户端真实地址,以便服务器获取客户端真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

报错

nginx 启动失败

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost nginx]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
[root@localhost nginx]# systemctl status nginx -l
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Thu 2017-05-18 09:34:41 CST; 6s ago
Process: 121270 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
Process: 121265 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 117382 (code=exited, status=0/SUCCESS)

May 18 09:34:41 localhost.localdomain systemd[1]: Starting The nginx HTTP and reverse proxy server...
May 18 09:34:41 localhost.localdomain nginx[121270]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
May 18 09:34:41 localhost.localdomain nginx[121270]: nginx: [emerg] bind() to 0.0.0.0:5100 failed (13: Permission denied)
May 18 09:34:41 localhost.localdomain nginx[121270]: nginx: configuration file /etc/nginx/nginx.conf test failed
May 18 09:34:41 localhost.localdomain systemd[1]: nginx.service: control process exited, code=exited status=1
May 18 09:34:41 localhost.localdomain systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
May 18 09:34:41 localhost.localdomain systemd[1]: Unit nginx.service entered failed state.
May 18 09:34:41 localhost.localdomain systemd[1]: nginx.service failed.

权限拒绝,经检查发现是开启selinux 导致的。 直接关闭

getenforce 这个命令可以查看当前是否开启了selinux 如果输出 disabled 或 permissive 那就是关闭了

如果输出 enforcing 那就是开启了 selinux

1、临时关闭selinux

1
2
setenforce 0    ##设置SELinux 成为permissive模式
setenforce 1 ##设置SELinux 成为enforcing模式

2、永久关闭selinux,

修改 /etc/selinux/config 文件

SELINUX=enforcing 改为 SELINUX=disabled

重启机器即可

重启nginx服务

1
service nginx restart

参考:

http://www.cnblogs.com/Andon_liu/p/5353522.html

http://www.cnblogs.com/jingmoxukong/p/5945200.html

安装

官网下载

下载地址:redis-3.2.8.tar.gz

依赖包

1
yum install gcc

编译安装

1
2
3
4
5
6
wget http://download.redis.io/releases/redis-3.2.8.tar.gz # 获取包
tar -zxvf redis-3.2.8.tar.gz
cd redis-3.2.8
cd src
make distclean
make && make install

移动文件夹

移动文件,便于管理:(所有源代码安装的软件都安装在/usr/local下)

创建两个文件夹,bin用于存放命令,etc拥有存放配置文件。

1
2
mkdir -p /usr/local/redis/etc
mkdir -p /usr/local/redis/bin

-p是递归创建。

接下来,将redis-3.2.8文件夹下的redis.conf复制到/usr/local/redis/etc/

并将src目录下的6个命令文件(绿色的),移动到/usr/local/redis/bin/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost src]# mkdir -p /usr/local/redis/etc
[root@localhost src]# mkdir -p /usr/local/redis/bin
[root@localhost src]# cd ..
[root@localhost redis-3.2.8]# ls
00-RELEASENOTES COPYING Makefile redis.conf runtest-sentinel tests
BUGS deps MANIFESTO runtest sentinel.conf utils
CONTRIBUTING INSTALL README.md runtest-cluster src
[root@localhost redis-3.2.8]# mv ./redis.conf /usr/local/redis/etc
[root@localhost redis-3.2.8]# ls
00-RELEASENOTES COPYING Makefile runtest sentinel.conf utils
BUGS deps MANIFESTO runtest-cluster src
CONTRIBUTING INSTALL README.md runtest-sentinel tests
[root@localhost redis-3.2.8]# cd src
[root@localhost src]# mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-sentinel redis-server /usr/local/redis/bin/

启动redis服务

1
2
[toor@localhost redis]$ cd bin
[toor@localhost bin]$ ./redis-server

显示结果:

结果

但是,这样做的话,我们并没有使用etc的下的配置文件进行启动(图中红线部分)。

如果希望通过指定的配置文件启动,需要在启动时指定配置文件:

使用ctrl+C终止服务(显示错误,可以重试几次),然后查看redis服务是否终止干净了,之后通过设置配置文件来启动服务

运行:pstree -p | grep redis 发现redis服务已经被终止干净

现在我们带上配置文件 /usr/local/etc/redis.conf 运行redis

1
[toor@localhost bin]$  ./redis-server /usr/local/redis/etc/redis.conf

启动结果:
启动结果

这样启动redis仍然在前台运行;

redis后台运行需要将daemonize由no改为yes

首先在超级权限下打开redis.conf。

1
[root@localhost bin]# vim /usr/local/redis/etc/redis.conf

保存退出,然后再次使用配置文件启动redis-server

1
2
3
4
5
6
7
[root@localhost bin]# ./redis-server /usr/local/redis/etc/redis.conf
[root@localhost bin]# ps -ef|grep redis
root 101598 1 0 17:04 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 101607 101338 0 17:04 pts/0 00:00:00 grep --color=auto redis
[root@localhost bin]# pstree -p|grep redis
|-redis-server(101598)-+-{redis-server}(101601)
| `-{redis-server}(101602)

详细参数说明:

daemonize 如果需要在后台运行,把该项改为yes

pidfile 配置多个pid的地址 默认在/var/run/redis.pid

bind 绑定ip,设置后只接受来自该ip的请求

port 监听端口,默认是6379

loglevel 分为4个等级:debug verbose notice warning

logfile 用于配置log文件地址

databases 设置数据库个数,默认使用的数据库为0

save 设置redis进行数据库镜像的频率。

rdbcompression 在进行镜像备份时,是否进行压缩

dbfilename 镜像备份文件的文件名

Dir 数据库镜像备份的文件放置路径

Slaveof 设置数据库为其他数据库的从数据库

Masterauth 主数据库连接需要的密码验证

Requriepass 设置 登陆时需要使用密码

Maxclients 限制同时使用的客户数量

Maxmemory 设置redis能够使用的最大内存

Appendonly 开启append only模式

Appendfsync 设置对appendonly.aof文件同步的频率(对数据进行备份的第二种方式)

vm-enabled 是否开启虚拟内存支持 (vm开头的参数都是配置虚拟内存的)

vm-swap-file 设置虚拟内存的交换文件路径

vm-max-memory 设置redis使用的最大物理内存大小

vm-page-size 设置虚拟内存的页大小

vm-pages 设置交换文件的总的page数量

vm-max-threads 设置VM IO同时使用的线程数量

Glueoutputbuf 把小的输出缓存存放在一起

hash-max-zipmap-entries 设置hash的临界值

Activerehashing 重新hash

Redis服务端默认连接端口是6379.

mysql 服务端默认连接端口是3306

Mogodb 服务端默认连接端口是27017,还有28017。

在平时,我们往往需要查看6379端口是否被占用。可以用以下命令:

1
2
3
4
5
6
7
8
9
10
11
[toor@localhost bin]$ netstat -tunpl | grep 6379
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN -
[toor@localhost bin]$ sudo netstat -tunpl | grep 6379
[sudo] password for toor:
toor is not in the sudoers file. This incident will be reported.
[toor@localhost bin]$ su root
Password:
[root@localhost bin]# netstat -tunpl | grep 6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 101598/./redis-serv

注意,redis服务需要su权限才能查看,不然只能检查到6379被某个进程占用,但是看不到进程名称。

至此,redis服务已经按照配置文件启动成功!!

客户端登陆

进入 /usr/local/redis/bin/

1
2
3
4
5
6
[root@localhost bin]# redis-cli
127.0.0.1:6379>

[root@localhost bin]# redis-cli -h 192.168.1.131 -p 6379 # 指定主机,端口 -a password #指定密码
192.168.1.131:6379>
[root@localhost bin]# redis-cli -h 192.168.1.131 -p 6379 shutdown # 关闭redis服务

关闭Redis服务

1
2
3
4
5
6
7
[root@localhost bin]# pkill redis-server
[root@localhost bin]# netstat -tunpl | grep 6379
[root@localhost bin]# pstree -p | grep redis
[root@localhost bin]# redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>

也可以使用/usr/local/redis/bin/redis-cli shutdown,这种方法使用客户端命令redis-cli

1
2
3
4
5
6
7
[root@localhost bin]# ./redis-server /usr/local/redis/etc/redis.conf
[root@localhost bin]# pstree -p | grep redis
|-redis-server(101927)-+-{redis-server}(101929)
| `-{redis-server}(101930)
[root@localhost bin]# /usr/local/redis/bin/redis-cli shutdown
[root@localhost bin]# pstree -p | grep redis
[root@localhost bin]# sudo netstat -tunpl | grep 6379

开启远程访问端口

开启端口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --reload #重启防火墙

## 重新查询端口是否开放
firewall-cmd --query-port=6379/tcp

## 查看监听的端口
netstat -lnpt

#关闭6379端口
firewall-cmd --zone=public --remove-port=6379/tcp --permanent

## 查看防火墙所有开放的端口
firewall-cmd --zone=public --list-ports

命令含义:

1
2
3
--zone #作用域
--add-port=6379/tcp #添加端口,格式为:端口/通讯协议
--permanent #永久生效,没有此参数重启后失效

配置密码认证

找到/usr/local/redis/etc/redis.conf文件中

1
requirepass foobared

去掉注释,并且设置密码

重启redis

1
2
3
4
[root@localhost bin]# ./redis-server /usr/local/redis/etc/redis.conf
[root@localhost bin]# redis-cli -h 192.168.1.131 -p 6379 -a toor
192.168.1.131:6379> keys *
(empty list or set)
1
2
3
4
5
6
7
8
[root@localhost bin]# ./redis-server /usr/local/redis/etc/redis.conf
[root@localhost bin]# redis-cli -h 192.168.1.131 -p 6379
192.168.1.131:6379> keys *
(error) NOAUTH Authentication required.
192.168.1.131:6379> auth toor
OK
192.168.1.131:6379> keys *
(empty list or set)

master配置了密码,slave如何配置

若master配置了密码则slave也要配置相应的密码参数否则无法进行正常复制的。

slave中配置文件内找到如下行,移除注释,修改密码即可

1
#masterauth  mstpassword

参考:

http://www.open-open.com/lib/view/open1426468117367.html

centos7/rhel7: 如何重启/停止/启动网络服务

重启网络服务

1
2
3
systemctl retart network.service

systemctl restart network

启动网络服务

1
2
3
systemctl start network.service

systemctl start network

停止网络服务

1
2
3
systemctl stop network.service

systemctl stop network

参考:http://www.osetc.com/archives/1191.html

流程

下载

官网下载网址

找到CentOS7最新下载包,

mongodb-linux-x86_64-rhel70-3.4.4.tgz

官方手册

解压

在终端输入命令,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 解压
tar xzvf mongodb-linux-x86_64-rhel70-3.4.4.tgz

# 移动
mv mongodb-linux-x86_64-rhel70-3.4.4 mongodb-3.4.4

# 创建目录
cd mongodb-3.4.4
mkdir logs
mkdir db

# 创建配置文件
cd bin
vim mongodb.conf

配置文件如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# idae - MongoDB config start - 2017-05-10

# 设置数据文件的存放目录
dbpath = /usr/local/mongodb/mongodb-3.4.4/db

# 设置日志文件的存放目录及其日志文件名
logpath = /usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log

# 设置端口号(默认的端口号是 27017)
port = 27017

# 设置为以守护进程的方式运行,即在后台运行
fork = true

# nohttpinterface = true
nohttpinterface = true
# idae - MongoDB config end - 2016-05-10

参数解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--dbpath 数据库路径(数据文件)
--logpath 日志文件路径
--master 指定为主机器
--slave 指定为从机器
--source 指定主机器的IP地址
--pologSize 指定日志文件大小不超过64M.因为resync是非常操作量大且耗时,最好通过设置一个足够大的oplogSize来避免resync(默认的 oplog大小是空闲磁盘大小的5%)。
--logappend 日志文件末尾添加,即使用追加的方式写日志
--journal 启用日志
--port 启用端口号
--fork 在后台运行
--only 指定只复制哪一个数据库
--slavedelay 指从复制检测的时间间隔
--auth 是否需要验证权限登录(用户名和密码)
--syncdelay 数据写入硬盘的时间(秒),0是不等待,直接写入
--notablescan 不允许表扫描
--maxConns 最大的并发连接数,默认2000
--pidfilepath 指定进程文件,不指定则不产生进程文件
--bind_ip 绑定IP,绑定后只能绑定的IP访问服务(服务器本地IP,非访问服务器客户端IP)

启动mongodb服务

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
# 进入mongodb-3.4.4/bin目录
# 自定义的 mongodb 配置文件方式启动
./mongod --config mongodb.conf

# 停止:
./mongod --config mongodb.conf --shutdown

# 修复模式启动 mongodb
./mongod --repair -f mongodb.conf

# 以参数方式启动(在mongodb-3.4.4/bin目录下):
./mongod --dbpath=/usr/local/mongodb/mongodb-3.4.4/db --logpath=/usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log --fork

# 停止:添加 --shutdown
./mongod --dbpath=/usr/local/mongodb/mongodb-3.4.4/db --logpath=/usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log --fork --shutdown

# 添加认证: --auth
# 连接
./mongo 192.168.1.131:27017/admin -u root1 -p root1

# 如果报如下错误:

ERROR: child process failed, exited with error number 1
# 很可能是 mongodb.conf 中配置的路径不一致问题;

# 如果报如下错误:

ERROR: child process failed, exited with error number 100
# 很可能是没有正常关闭导致的,那么可以删除 mongod.lock 文件
# number 100 :端口问题

查看 mongodb 进程:

ps aux | grep mongodb

查看 mongodb 服务的运行日志:

tail -200f /usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log

检查端口是否已被启动:

netstat -lanp | grep 27017

杀死 mongodb 进程,即可关闭 mongodb 服务:(禁止使用,容易出现问题)

1
kill -15 PID

连接错误

1.若数据库出现如上不能连接的原因,可能是data目录下的mongod.lock文件问题,可以用如下命令修复:
./bin/mongod --repair

2.直接删除mongod.lock
rm -f /usr/local/mongodb/db/mongod.lock

3.然后再启动 mongodb 服务:
./mongod --config mongodb.conf

4.如果以上两部依然解决不掉,则是路径文件,我们可以删除 /usr/local/mongodb/mongodb-3.4.4/db 目录及其子目录,并采用绝对路径的方式:

1
./mongod /usr/local/mongodb/mongodb-3.4.4/bin/mongod --dbpath=/usr/local/mongodb/mongodb3.4.4/db --logpath=/usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log --fork

将 mongodb 服务加入到自启动文件中:

vi /etc/rc.local

在文件末尾追加如下命令:

/usr/local/mongodb/mongodb-3.4.4/bin/mongod --config mongodb.conf

保存并退出:
:wq!

/usr/local/mongodb/mongodb3.4.4/bin/ 目录中,键入如下命令,打开一个 mongodb 的客户端程序,即打开一个 mongodb 的 shell 客户端,这个 shell 客户端同时也是一个 JavaScript 编辑器,即可用输入任何的 JavaScript 脚本:

./mongo

在浏览器中输入 IP:27017,如:

http://127.0.0.1:27017/

开启远程访问端口

开启端口:

firewall-cmd --zone=public --add-port=27017/tcp --permanent

命令含义:
–zone #作用域
–add-port=27017/tcp #添加端口,格式为:端口/通讯协议
–permanent #永久生效,没有此参数重启后失效

重启防火墙:

firewall-cmd --reload

安全和认证

限制特定IP地址访问(MongoDB服务器IP地址)

1
./mongod --bind_ip 192.168.1.131 --port 27017 --dbpath /usr/local/mongodb/mongodb-3.4.4/db --logpath /usr/local/mongodb/mongodb-3.4.4/logs/mongodb.log --fork

设置监听端口,并且需要在防火墙配置

1
--port 27017

设置登录用户名和口令

启用mongodb授权认证的方法:

1、以–auth 启动mongod

2、在配置文件mongod.conf 中加入 auth = true

添加用户:

1
2
3
4
5
6
7
db.createUser(
... {
... user: "root1",
... pwd: "root1",
... roles: [ { role: "__system", db: "admin" } ]
... }
... )

重新登录:
./mongo 192.168.1.131:27017 -u root1 -p root1

展示角色:
show roles

获取用户:
db.getUsers();

参考网址:

http://www.linuxidc.com/Linux/2016-06/132675.htm

CSharp lock锁深入理解

定义

临界区(Critical Section)

临界区是一段在同一时候只被一个线程进入/执行的代码块。

Lock关键字

将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:

1
2
3
4
5
6
Object thisLock = new Object();

lock (thisLock)
{
// Critical code section
}
  • lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

Lock使用准则

Lock 调用块开始位置的 Enter 和块结束位置的 Exit。

通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock (“myLock”) 违反此准则:

  • 如果实例可以被公共访问,将出现 lock (this) 问题。

  • 如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。

  • 由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现lock(“myLock”) 问题。

最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。

针对上述三点原则我们用具体的代码来加深理解

为什么不要Lock值类型

为什么不能lock值类型,比如lock(1)呢?让我们对上面的实例代码进行修改,将lock(thisLock)改为Lock(1),编译器时会出现int不是Lock语句要求的引用对象

编译失败

lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。lock其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。

不要使用lock((object)1)

经lock(thisLock)改为Lock((object)1)编译可以成功,说明代码块并没有锁.究其原因是因为Lock(对象)中,对象为引用类型,其是通过判断object.ReferenceEquals((object)1, (object)1)始终返回false(因为每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能够访问里面的代码,达不到同步的效果。

不要使用Lock(this)

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace TestLock
{
public class TestLockThis
{
private bool deadlocked = true;
private static readonly object lockobject = new object();

//这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
public void LockMethod(object o)
{
//lock (this)
lock (lockobject)
{
while (deadlocked)
{
deadlocked = (bool)o;
Console.WriteLine("I am locked ");
Thread.Sleep(500);
}
}
}

//所有线程都可以同时访问的方法
public void NotLockMethod()
{
Console.WriteLine("I am not locked ");
}

}
}
static void Main(string[] args)
{
TestLockThis TestLockThis = new TestLockThis();

//在t1线程中调用LockMe,并将deadlock设为true(将出现死锁)
Thread t1 = new Thread(TestLockThis.LockMethod);
t1.Start(true);
Thread.Sleep(100);

//在主线程中lock c1
lock (TestLockThis)
{
//调用没有被lock的方法
TestLockThis.NotLockMethod();
//调用被lock的方法,并试图将deadlock解除
TestLockThis.LockMethod(false);
}

Console.Read();
}

在t1线程中,LockMethod调用了lock(this), 也就是Main函数中的c1,这时候在主线程中调用lock(TestLockThis)时,因为TestLockThis已经被锁定,所以必须要等待t1中的lock块执行完毕之后才能访问锁定的代码,即lock块中的所有操作都无法完成,于是我们看到连TestLockThis.NotLockMethod()都没有执行。

Lock为什么不要Lock(null对象)

使用Lock(null),会抛出异常

Lock 本质

Lock 关键字就是用Monitor 类来实现的。例如:

1
2
3
4
lock(x)
{
DoSomething();
}

这等效于:

1
2
3
4
5
6
7
8
9
10
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
DoSomething();
}
finally
{
System.Threading.Monitor.Exit(obj);
}

使用 lock 关键字通常比直接使用 Monitor 类更可取,一方面是因为 lock 更简洁,另一方面是因为 lock 确保了即使受保护的代码引发异常,也可以释放监视器。这是通过 finally 关键字来实现的,无论是否引发异常它都执行关联的代码块。

Lock 对象推荐为只读静态对象

1
private static readonly object obj = new object();

为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false。

更准确的说,如果lock(object),object是静态的。那么说要该类的实例请求的都是一个object,所有实例执行的lock的时候只有一个能running。其他都必须等等。
lock(this)则表示锁住当前实例,实例内的所有线程必须等待,同一类的其他实例则可以有一个线程runing.

简单说lock(static objcet)在所有实例里锁住这段代码。
lock(this)锁住当前实例的这段代码。

参考:

http://www.cnblogs.com/chengqscjh/archive/2010/12/12/1903784.html

CSharp中equal与==的区别

C#中,判断相等有两种方式,一种是传统的==操作,一种是object提供的Equals方法。

二者的区别在于:

  • 一、==操作符判断的是堆栈中的值,Equlas判断的是堆中的值。

    C#提供值类型和引用类型,值类型存储在栈上,故用==判断是直接判断其值是否相等,因为值类型不存在堆中的数据,因此值类型的Equals也是判断数据。
    即,对于值类型而言,==与Equals相同,均是判断其值是否相等。

    对于引用类型而言,其栈中存储的是对象的地址,那么==就是比较两个地址是否相等,即是否指向同一个对象;Equals函数则是比较两个对象在堆中的数据
    是否一样,即两个引用类型是否是对同一个对象的引用。

  • 二、String类型特殊

    String类型虽然是引用类型,但是对String对象的赋值却按照值类型操作。

    例如:

    1
    2
    String s1="hello";
    String s2="hello";

    对s2初始化的时候,并没有重新开辟内存,而是直接将其地址指向s1的内容“hello”。这样一来,string类型虽然是引用类型,但是其==操作和Equals操作
    都是一样的,均比较值是否相等。

  • 三、与GetHashCode()的关系

    若两对象Equals相等,那么其GetHashCode()必定相等;但是反过来,若GetHashCode()相等,那么这两个对象Equals方法比较结果不一定相同。

    (为了获取最佳性能,hash函数为对象内容生成的数字是随机分布的,这就意味着,内容不同的对象,有可能生成的数字是一样的,但可以认为这种概率非常小)。

    下面示例说明:

    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConsoleApplication1
    {
    class People
    {
    private string name;

    public string Name
    {
    get { return name; }
    set { name = value; }
    }

    public People(string name)
    {
    this.name = name;
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    string a = "hello";
    string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
    Console.WriteLine(a == b);
    Console.WriteLine(a.Equals(b));
    Console.WriteLine("\n");

    Int32 m = 3;
    Int32 n = 3;
    Console.WriteLine(n == m);
    Console.WriteLine(n.Equals(m));
    Console.WriteLine("\n");

    object g = a;
    object h = b;
    Console.WriteLine(g == h);
    Console.WriteLine(g.Equals(h));
    Console.WriteLine(g.GetHashCode() + " " + h.GetHashCode());
    Console.WriteLine("\n");

    People p1 = new People("Jimmy");
    People p2 = new People("Jimmy");
    Console.WriteLine(p1 == p2);
    Console.WriteLine(p1.Equals(p2));
    Console.WriteLine(p1.GetHashCode() + " " + p2.GetHashCode());
    Console.WriteLine("\n");

    People p3 = new People("Jimmy");
    People p4 = p3;
    Console.WriteLine(p3 == p4);
    Console.WriteLine(p3.Equals(p4));

    }
    }
    }

    运行结果:
    运行结果

hexo文档

命令

  • hexo:查看帮助
  • hexo server :本地启动命令,可以在本地浏览器浏览
    • Ctrl+C 停止Server
  • hexo new “My New Post” : 新建文档
  • hexo clean :清除旧文档
  • hexo generate :生成
  • hexo deploy :部署

部署配置

生成 SSH KEY

1
2
3
git config --global user.name " GitHub 用户名 "
git config --global user.email " GitHub 邮箱 "
ssh-keygen -t rsa -C " 邮箱地址 "

1,SSH KEY 生成之后会默认保存在 C:/Users/电脑名用户名/.ssh 目录中,打开这个目录,打开 id_rsa.pub 文件,复制全部内容,即复制密钥

2,打开 GitHub ,依次点击 头像–>Settings–>SSH and GPG keys–>Add SSH key,将复制的密钥粘贴到 key 输入框,最后点击 Add Key ,SSH KEY 配置成功

添加图片

  • 使用本地路径:在hexo/source目录下新建一个img文件夹,将图片放入该文件夹下,插入图片时链接即为/img/图片名称
    • 例如:![配置](/img/mysql-workbench.png)

站内文章链接

官方有标签插件实现站内文章链接,如下:

post_link 官方文档

1
{% post_link 'hexo blog' %}

其它

首页隐藏文章详细内容:

1
<!--more-->

段落缩进两个字符:

1
&emsp;&emsp;

ILGenerator

ILGenerator:生成IL代码

获取ILGenerator类的实例方法:

ConstructorBuilder.GetILGenerator方法
DynamicMethod.GetILGenerator 方法
MethodBuilder.GetILGenerator 方法

上面涉及到了在Emit中能够动态生成方法的三种途径,

ConstructorBuilder类用来配置的构造函数,构造函数内部的IL要使用它的

GetILGenerator方法返回的ILGenerator类发出。

DynamicMethod类,是在当前运行上下文环境中动态生成方法的类,使用该类不必

事先创建程序集、模块和类型,同样发出其内部的IL使用DynamicMethod.GetILGenerator

方法返回的ILGenerator类实例.

最终实现的调用效果:

1
2
3
4
5
6
7
8
Mock<IAssessmentAopAdviceProvider> mocker = new Mock<IAssessmentAopAdviceProvider>();

mocker.Setup(t => t.Before(3)).Returns("Hello World!");

Console.WriteLine(mocker.Obj.Before(2));

Console.Read();

接收一个接口,初始化一个Mock类的实例,然后通过Setup和Returns扩展方法设定实现

该接口的实例在指定方法上的返回值。这里我们先不考虑对不同参数的处理逻辑。

Mock类定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Mock<T> where T : IAssessmentAopAdviceProvider
{
public T Obj
{
get; set;
}

public SetupContext Contex { get; set; }

public Mock()
{
}
}

Mock类的Obj属性是特定接口的实例。Contex属性是上下文信息

Contex类定义如下:

1
2
3
4
public class SetupContext
{
public MethodInfo MethodInfo { get; set; }
}

只包含一个MethodInfo属性

扩展方法:

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
public static class MockExtention
{
public static Mock<T> Setup<T>(this Mock<T> mocker, Expression<Action<T>> expression) where T : IAssessmentAopAdviceProvider
{
mocker.Contex = new SetupContext();

mocker.Contex.MethodInfo = expression.ToMethodInfo();

return mocker;
}

public static void Returns<T>(this Mock<T> mocker, object returnValue) where T : IAssessmentAopAdviceProvider
{
if (mocker.Contex != null && mocker.Contex.MethodInfo != null)
{
//这里为简单起见,只考虑IAssessmentAopAdviceProvider接口
mocker.Obj = (T)AdviceProviderFactory.GetProvider(mocker.Contex.MethodInfo.Name, (string)returnValue);
}
}

public static MethodInfo ToMethodInfo(this LambdaExpression expression)
{
var memberExpression = expression.Body as System.Linq.Expressions.MethodCallExpression;

if (memberExpression != null)

{
return memberExpression.Method;
}

return null;
}

}

Setup是Mock类的扩展方法,配置要Mock的方法信息;

Returns扩展方法则调去对应的工厂获取接口的实例。

ToMethodInfo是LambdaExpression扩展方法,该方法从Lambda表达式中获取MethodInfo.

对应的工厂方法直接返回IAssessmentAopAdviceProvider接口实例。

在构造方法中初始化assemblyBuilder和moduleBuilder
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static readonly AssemblyName assemblyName = new AssemblyName("EmitTest.MvcAdviceProvider");

private static AssemblyBuilder assemblyBuilder;

private static ModuleBuilder moduleBuilder;

static AdviceProviderFactory()
{
assemblyName.Version = new Version("1.0.0.0");

assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

moduleBuilder = assemblyBuilder.DefineDynamicModule("MvcAdviceProviderModule", "test.dll", true);
}

CreateInstance方法负责创建类型和方法的实现:

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
private static IAssessmentAopAdviceProvider CreateInstance(string instanceName, string methodName, string returnValue)
{
TypeBuilder typeBuilder = moduleBuilder.DefineType("MvcAdviceProvider.MvcAdviceProviderType", TypeAttributes.Public, typeof(object), new Type[] { typeof(IAssessmentAopAdviceProvider) });

// typeBuilder.AddInterfaceImplementation(typeof(IAssessmentAopAdviceProvider));

MethodBuilder beforeMethodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), new Type[] { typeof(int) });

beforeMethodBuilder.DefineParameter(1, ParameterAttributes.None, "value");

ILGenerator generator1 = beforeMethodBuilder.GetILGenerator();

LocalBuilder local1 = generator1.DeclareLocal(typeof(string));

local1.SetLocalSymInfo("param1");

generator1.Emit(OpCodes.Nop);

generator1.Emit(OpCodes.Ldstr, returnValue);

generator1.Emit(OpCodes.Stloc_0);

generator1.Emit(OpCodes.Ldloc_0);

generator1.Emit(OpCodes.Ret);

Type providerType = typeBuilder.CreateType();

assemblyBuilder.Save("test.dll");

IAssessmentAopAdviceProvider provider = Activator.CreateInstance(providerType) as IAssessmentAopAdviceProvider;

return provider;
}

在CreateInstance方法中,首先定义类型:

1
TypeBuilder typeBuilder = moduleBuilder.DefineType("MvcAdviceProvider.MvcAdviceProviderType", TypeAttributes.Public, typeof(object), new Type[] { typeof(IAssessmentAopAdviceProvider) });

第三个和第四个参数,分别是该类型大的基类型和实现的接口列表。

1
MethodBuilder beforeMethodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), new Type[] { typeof(int) });

DefineMethod方法中,传人的第一个参数是方法的名称,第二个参数是访问类型,第三个参数是修饰符,第四个参数是方法的参数类型列表。这里需要注意第二个参数,也就是方法的修饰符,因为接口中的方法定义都是virtual的,所以在实现接口的时候,方法也必须声明为MethodAttributes.Virtual。

定义方法的参数,使用MethodBuilder.DefineParameter方法。

1
beforeMethodBuilder.DefineParameter(1, ParameterAttributes.None, "value");

DefineParameter方法的第一参数指定当前定义的参数在方法参数列表中的顺序,从1开始,如果设置为0则代表方法的返回参数。第二个参数是设置参数的特性,如输入参数,输出参数等等。第三个参数是指定该参数的名称。

方法定义完毕,接下来就是发出Opcode,返回一个指定的字符串。先获取ILGenerator实例,如下:

1
ILGenerator generator1 = beforeMethodBuilder.GetILGenerator();

我们若想返回一个字符串,必须先为该字符串声明一个局部变量,可以使用LocalBuilder.DeclareLocal方法,如下:

1
2
3
LocalBuilder local1 = generator1.DeclareLocal(typeof(string));

local1.SetLocalSymInfo("param1");

ocal1.SetLocalSymInfo(“param1”)指定局部变量的名称。

需要注意,如果模块定义时不允许发出符号信息,是无法使用SetLocalSymInfo方法的,AdviceProviderFactory的构造函数中,我们定义模块的代码

1
moduleBuilder = assemblyBuilder.DefineDynamicModule("MvcAdviceProviderModule", "test.dll",true);

最后一个参数是指定是否允许发出符号信息的。

发出的Opcode:

1
2
3
4
5
6
7
8
9
generator1.Emit(OpCodes.Nop);

generator1.Emit(OpCodes.Ldstr, returnValue);

generator1.Emit(OpCodes.Stloc_0);

generator1.Emit(OpCodes.Ldloc_0);

generator1.Emit(OpCodes.Ret);

第一条指令不执行任何操作。

第二条指令加载一个字符串到计算堆栈中。

第三条指令赋值计算堆栈顶部的数据到局部变量列表中的第一个变量。

第四条指令加载局部变量列表中的第一个变量的数据引用到计算堆栈。

第五条指令方法返回。

整个Emit的过程结束了,接下来要创建实例:

1
2
3
4
5
Type providerType = typeBuilder.CreateType();

assemblyBuilder.Save("test.dll");

IAssessmentAopAdviceProvider provider = Activator.CreateInstance(providerType) as IAssessmentAopAdviceProvider;

控制台调用:

1
2
3
4
5
6
7
Mock<IAssessmentAopAdviceProvider> mocker = new Mock<IAssessmentAopAdviceProvider>();

mocker.Setup(t => t.Before(3)).Returns("Hello World!");

Console.WriteLine(mocker.Obj.Before(2));

Console.Read();

代码

参考:

http://www.cnblogs.com/xuanhun/archive/2012/06/22/2558698.html

动态创建完整的程序集

创建程序集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitTest
{
internal class Program
{
private static void Main(string[] args)
{
AssemblyName assemblyName = new AssemblyName("EmitTest.MvcAdviceProvider");

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
}
}
}

AppDomain.CurrentDomain.DefineDynamicAssembly方法返回一个AssemblyBuilder实例。

其中,第一个参数是AssemblyName实例,是程序集的唯一标识;第二个参数AssemblyBuilderAccess.Run表明该程序集只能用来执行代码,

不能被持久保存。AssemblyBuilderAccess还有如下选项:

AssemblyBuilderAccess.ReflectionOnly:程序集只能在反射上下文中执行。

AssemblyBuilderAccess.RunAndCollect:程序集可以运行和垃圾回收。

AssemblyBuilderAccess.RunAndSave:程序集可以执行代码而且被持久保存。

AssemblyBuilderAccess.Save:程序集是持久化的,保存之前不可以执行代码。

创建了程序集之后,我们继续向程序集中添加模块。

向程序集添加模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitTest
{
internal class Program
{
private static void Main(string[] args)
{
AssemblyName assemblyName = new AssemblyName("EmitTest.MvcAdviceProvider");

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MvcAdviceProvider");
}
}
}

AssemblyBuilder.DefineDynamicModule方法来创建模块,该方法共有三个重载,如下表所示:

DefineDynamicModule(String)定义指定名称的模块。

DefineDynamicModule(String, Boolean)定义指定名称的模块,并指定是否发出符号信息。

DefineDynamicModule(String, String)定义持久模块。用给定名称定义将保存到指定文件路径的模块。不发出符号信息。

DefineDynamicModule(String, String, Boolean)定义持久模块,并指定模块名称、用于保存模块的文件名,同时指定是否使用默认符号编写器发出符号信息。

定义类型

我们要定义的类型必须继承并实现IAssessmentAopAdviceProvider接口

1
2
TypeBuilder typeBuilder = moduleBuilder.DefineType("EmitTest.MvcAdviceProvider", TypeAttributes.Public,
typeof(object), new Type[] { typeof(IAssessmentAopAdviceProvider) });

上述代码中mb.DefineType方法返回一个TypeBuilder实例,该方法有6个重载方法,这里采用的方法有四个参数,

第一个参数是类型名称,第二个参数的TypeAttributes枚举是类型的访问级别和类型类别等其他信息,第三个参数

是类型继承的基类,第四个参数是类型实现的接口。其他重载函数的说明如下(引自MSDN):

DefineType(String)在此模块中用指定的名称为私有类型构造 TypeBuilder。

DefineType(String, TypeAttributes)在给定类型名称和类型特性的情况下,构造 TypeBuilder。

DefineType(String, TypeAttributes, Type)在给定类型名称、类型特性和已定义类型扩展的类型的情况下,构造 TypeBuilder。

DefineType(String, TypeAttributes, Type, Int32)在给定类型名称、特性、已定义类型扩展的类型和类型的总大小的情况下,构造 TypeBuilder。

DefineType(String, TypeAttributes, Type, PackingSize)在给定类型名称、特性、已定义类型扩展的类型和类型的封装大小的情况下,构造 TypeBuilder。

DefineType(String, TypeAttributes, Type, Type[])在给定类型名称、特性、已定义类型扩展的类型和已定义类型实现的接口的情况下,构造 TypeBuilder。

DefineType(String, TypeAttributes, Type, PackingSize, Int32)在给定类型名称、特性、已定义类型扩展的类型,已定义类型的封装

通过TypeBuilder,可以使用TypeBuilder.DefineField来定义字段,使用TypeBuilder.DefineConstructor来定义构造函数,

使用TypeBuilder.DefineMethod来定义方法,并使用TypeBuilder.DefineEvent来定义事件等,总之可以定义类型里的任何成员。

这里我们只需要定义方法

1
2
3
MethodBuilder beforeMethodBuilder = typeBuilder.DefineMethod("Before", MethodAttributes.Public, typeof(object), new Type[] { typeof(object) });

MethodBuilder afterMethodBuilder = typeBuilder.DefineMethod("After", MethodAttributes.Public, typeof(object), new Type[] { typeof(object), typeof(object) });

在上面的代码中,使用TypeBuilder.DefineMethod 方法来创建MethodBuilder对象。该方法有5个重载,如下表(引自MSDN):

DefineMethod(String, MethodAttributes)使用指定的名称和方法特性向类型中添加新方法。

DefineMethod(String, MethodAttributes, CallingConventions)使用指定名称、方法特性和调用约定向类型中添加新方法。

DefineMethod(String, MethodAttributes, Type, Type[])使用指定的名称、方法特性和调用约定向类型中添加新方法。

DefineMethod(String, MethodAttributes, CallingConventions, Type, Type[])使用指定的名称、方法特性、调用约定和方法签名向类型中添加新方法。

DefineMethod(String, MethodAttributes, CallingConventions, Type, Type[], Type[], Type[], Type[][], Type[][])使用指定的名称、方法特性、调用约定、方法签名和自定义修饰符向类型中添加新方法。

完整代码:

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
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitTest
{
internal class Program
{
private static void Main(string[] args)
{
AssemblyName assemblyName = new AssemblyName("EmitTest.MvcAdviceProvider");

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MvcAdviceProvider");

TypeBuilder typeBuilder = moduleBuilder.DefineType("EmitTest.MvcAdviceProvider", TypeAttributes.Public,

typeof(object), new Type[] { typeof(IAssessmentAopAdviceProvider) });

MethodBuilder beforeMethodBuilder = typeBuilder.DefineMethod("Before", MethodAttributes.Public, typeof(object), new Type[] { typeof(object) });

MethodBuilder afterMethodBuilder = typeBuilder.DefineMethod("After", MethodAttributes.Public, typeof(object), new Type[] { typeof(object), typeof(object) });

TestType(typeBuilder);
}

private static void TestType(TypeBuilder typeBuilder)
{
Console.WriteLine(typeBuilder.Assembly.FullName);

Console.WriteLine(typeBuilder.Module.Name);

Console.WriteLine(typeBuilder.Namespace);

Console.WriteLine(typeBuilder.Name);

Console.Read();
}
}
}

参考:

http://www.cnblogs.com/xuanhun/archive/2012/06/03/2532922.html

Host ‘xx.xx.xx.xx’ is not allowed to connect to this MySQL server

注:需要在服务器登录mysql终端

改表法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> update user set host = '%' where user = 'root';//需要远程连接的用户
mysql> select host,user from user;
+-----------+-----------+
| host | user |
+-----------+-----------+
| % | root |
| localhost | mysql |
| localhost | mysql.sys |
+-----------+-----------+
3 rows in set (0.00 sec)

授权法

1
2
3
4
5
mysql> GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION; //mysql 密码强度有验证;mypassword:密码
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> FLUSH PRIVILEGES; // 刷新
Query OK, 0 rows affected (0.01 sec)

如果你想允许用户myuser从ip为192.168.1.6的主机连接到mysql服务器,并使用mypassword作为密码

1
2
GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'192.168.1.3' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
FLUSH PRIVILEGES;

如果你想允许用户myuser从ip为192.168.1.6的主机连接到mysql服务器的dk数据库,并使用mypassword作为密码

1
2
GRANT ALL PRIVILEGES ON dk.* TO 'myuser'@'192.168.1.3' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
FLUSH PRIVILEGES;

卸载mysql

命令:

1
2
3
[root@localhost usr]# yum remove mysql mysql-server mysql-libs compat-mysql51
[root@localhost usr]# rm -rf /var/lib/mysql
[root@localhost usr]# rm /etc/my.cnf

查看安装的rpm包:

1
2
3
4
5
6
7
8
9
[root@localhost mysql]# rpm -aq | grep -i mysql
MySQL-server-5.6.27-1.el6.x86_64
MySQL-client-5.6.27-1.el6.x86_64
MySQL-devel-5.6.27-1.el6.x86_64
[root@localhost mysql]# rpm -e MySQL-server-5.6.27-1.el6.x86_64
[root@localhost mysql]# rpm -e MySQL-client-5.6.27-1.el6.x86_64
[root@localhost mysql]# rpm -e MySQL-devel-5.6.27-1.el6.x86_64
[root@localhost rc.d]# cd /var/lib/
[root@localhost lib]# rm -rf mysql/
1
2
3
4
5
[root@localhost usr]# whereis mysql
mysql: /usr/lib64/mysql
[root@localhost usr]# rm -rf /usr/lib64/mysql

find / -name mysql

卸载自启服务:

1
2
[root@localhost usr]# chkconfig --list | grep -i mysql
[root@localhost usr]# chkconfig --del mysqld

参考:

http://blog.csdn.net/typa01_kk/article/details/49057073

在centos7单机安装mysql.

官网:https://www.mysql.com/cn/downloads/

检查MySql是否安装

方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost toor]# yum list installed mysql* 
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.tuna.tsinghua.edu.cn
* updates: mirrors.tuna.tsinghua.edu.cn
Installed Packages
mysql-community-client.x86_64 5.7.17-1.el7 @mysql57-community
mysql-community-common.x86_64 5.7.17-1.el7 @mysql57-community
mysql-community-libs.x86_64 5.7.17-1.el7 @mysql57-community
mysql-community-libs-compat.x86_64 5.7.17-1.el7 @mysql57-community
mysql-community-server.x86_64 5.7.17-1.el7 @mysql57-community
mysql57-community-release.noarch el7-9 installed

方式2

1
2
3
4
5
6
7
8
[root@localhost toor]# rpm -qa|grep -i mysql
mysql-community-libs-compat-5.7.17-1.el7.x86_64
mysql-community-libs-5.7.17-1.el7.x86_64
mysql57-community-release-el7-9.noarch
mysql-community-client-5.7.17-1.el7.x86_64
mysql-community-server-5.7.17-1.el7.x86_64
mysql-community-common-5.7.17-1.el7.x86_64

安装

注:选择root用户操作

下载rpm包

选择下载目录后,打开终端,输入命令,如下:

1
# wget http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm

安装mysql57-community-release-el7-7.noarch.下载rpm包

1
#rpm -ivh mysql57-community-release-el7-7.noarch.rpm

安装mysql

1
# yum install mysql-community-server

启动mysql服务

1
# service mysqld start

检查mysql状态

1
# service mysqld status

查看mysql版本

1
# mysql --version

验证mysql实例

输入命令,显示临时生成的密码:

1
# grep 'temporary password' /var/log/mysqld.log

设置root帐号(和系统root帐号不同)密码:

1
# mysql_secure_installation

连接到mysql server

1
# mysql -u root -p

使用yum更新mysql

1
# yum update mysql-server

开启远程访问端口

开启端口:

firewall-cmd --zone=public --add-port=3306/tcp --permanent

命令含义:

–zone #作用域

–add-port=3306/tcp #添加端口,格式为:端口/通讯协议

–permanent #永久生效,没有此参数重启后失效

重启防火墙:

firewall-cmd --reload

开机自动启动/取消

1
2
3
4
5
6
7
8
9
10
systemctl is-enabled iptables.service
systemctl is-enabled servicename.service #查询服务是否开机启动
systemctl enable mysqld.service #开机运行服务
systemctl disable mysqld.service #取消开机运行
systemctl start *.service #启动服务
systemctl stop *.service #停止服务
systemctl restart *.service #重启服务
systemctl reload *.service #重新加载服务配置文件
systemctl status *.service #查询服务运行状态
systemctl --failed #显示启动失败的服务

GUI管理工具

  • workbench(工作台)

下载地址:https://dev.mysql.com/downloads/workbench/

配置

参考:

[http://blog.csdn.net/typa01_kk/article/details/49057073][removeMysql]

http://www.tecmint.com/install-latest-mysql-on-rhel-centos-and-fedora/

http://tecadmin.net/install-mysql-5-7-centos-rhel/

http://blog.csdn.net/typa01_kk/article/details/49057073