日期: 2021 年 5 月 10 日

如何快速掌握云计算技术 Linux入门知识有哪些

何快速掌握云计算技术?Linux入门知识包括什么?Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。在实际应用中,Linux多与云计算挂扣,很多企业在招聘云计算人才时也会考察其对Linux的掌握程度。接下就给大家分享一下Linux入门知识。

%title插图%num

1、*对路径、当前目录、上层目录、主目录分别用什么表示? 如何切换目录用什么命令?

*对路径:如/etc/init.d

当前目录和上层目录:./ ../

主目录:~/

切换目录:cd

2、清屏、出当前命令、执行睡眠、查看当前用户 id用什么命令?

清屏:clear

退出当前命令:ctrl+c 彻底退出

执行睡眠 :ctrl+z 挂起当前进程fg 恢复后台

查看当前用户 id:”id“:查看显示目前登陆账户的 uid 和 gid 及所属分组及用户名

3、Ls命令执行什么功能?可以带哪些参数,有什么区别?

Ls执行的功能:列出指定目录中的目录以及文件

哪些参数以及区别:a 所有文件;l 详细信息,包括大小字节数,可读可写可执行的权限等

4、目录创建用什么命令?创建文件用什么命令?复制文件用什么命令?

创建目录:mkdir

创建文件:典型的如 touch,vi 也可以创建文件,其实只要向一个不存在的文件输出,都会创建文件

复制文件:cp

5、文件权限修改用什么命令?格式是怎么样的?

文件权限修改:chmod

格式如下:

$ chmod u+x file 给 file 的属主增加执行权限

$ chmod 751 file 给 file 的属主分配读、写、执行(7)的权限,给 file 的所在组分配读、执行(5)的权限,给其他用户分配执行(1)的权限

$ chmod u=rwx,g=rx,o=x file 上例的另一种形式

$ chmod =r file 为所有用户分配读权限

$ chmod 444 file 同上例

$ chmod a-wx,a+r file同上例

$ chmod -R u+r directory 递归地给 directory 目录下所有文件和子目录的属主分配读的权限

6、查看文件内容有哪些命令可以使用?

vi 文件名 #编辑方式查看,可修改

cat 文件名 #显示全部文件内容

more 文件名 #分页显示文件内容

less 文件名 #与 more 相似,更好的是可以往前翻页

tail 文件名 #仅查看尾部,还可以指定行数

head 文件名 #仅查看头部,还可以指定行数

7、Linux下命令有哪几种可使用的通配符?

“?”可替代单个字符

“*”可替代任意多个字符

方括号“[charset]”可替代 charset 集中的任何单个字符,如[a-z],[abABC]

8、Linux中进程有哪几种状态?

1)不可中断状态:进程处于睡眠状态,但是此刻进程是不可中断的。不可中断, 指进程不响应异步信号。

2)暂停状态/跟踪状态:向进程发送一个SIGSTOP信号,它就会因响应该信号 而进入TASK_STOPPED状态;当进程正在被跟踪时,它处于TASK_TRACED这个特殊的状态。

“正在被跟踪”指的是进程暂停下来,等待跟踪它的进程对它进行操作。

3)就绪状态:在run_queue队列里的状态

4)运行状态:在run_queue队列里的状态

5)可中断睡眠状态:处于这个状态的进程因为等待某事件的发生而被挂起

6)zombie状态(僵尸):父亲没有通过wait系列的系统调用会顺便将子进程的尸体(task_struct)也释放掉

7)退出状态

当然,除了以上内容,Linux相关的知识点还有很多,在此就不一一列举了。如果你想成为一个优秀的云计算人才,除了要掌握Linux知识外,还要了解数据库知识、Docker容器、Shell脚本运维、Python语言等,如果你想快速掌握这一系列的技术,可以选择专业的学习,快速掌握企业所需的高薪技术!

没有基础怎么学云计算 多云有哪些优势和挑战

没有基础怎么学云计算?多云有哪些优势和挑战?据IDC调研报告显示,在过去五年里,采用云(包括公有云和私有云)的用户呈指数级增长趋势。多云的出现是为了弥补公有云和私有云各自存在的不足,但这并不意味着多云就毫无缺点。接下来就给大家分析一下多云的优势以及存在的挑战。

%title插图%num

多云的优势

1、解决”单一云”的诸多挑战。多云将多个云的优势相结合,使组织能够使用合适的平台来满足合规性和安全性,而不影响其他工作负载的敏捷性,也不会限制对提供新计划或试点项目的新兴服务的获取。

2、更高的安全性。多云平台通过为组织提供根据合规性要求在适当平台中部署工作负载的灵活性,具备更高的安全性。

3、更高的敏捷性和速度。多云满足了不同企业的工作负载需求,根据企业的情况来选择不同的云,挑战将会更少,这对于企业部署业务的速度将大大提升。

4、为企业提供更广泛的云优势。多云可以为每个企业选择*适合其需求的服务,并提供灵活性,而不必受整个业务中的某个框架的约束。

多云面临的挑战

1、成本相对较高。虽然从一开始就通过利用多个云计算提供商来实现成本效率似乎是合理的,但从长远来看,缺乏工具和标准,以及低效率来跟踪云平台的使用和成本,可能代价更加高昂。

2、在数据迁移方面,客户使用多云面临的主要挑战是,云之间的数据迁移、各个平台缺乏统一的安全监督、所有平台之间缺乏一致的管理结构,以及无法快速部署应用程序。

3、缺乏一致的基础架构、缺乏统一的监视工具,以及各种云之间缺乏共享的专用网络,也被指出是企业正在努力解决的问题。

综合来看,多云是企业未来的趋势,但企业在选择多云的时候还需要尽量考虑周全,尽量选择一些知名度较高的企业来合作部署多云。对于想要加入云计算行业的开发人员来说,现在*对是入行的好时机。如果你不知道如何学习,不妨选择专业的学习,让自己理论与实战兼备,毕业后快速入职拿高薪!

云计算为什么要学Docker容器 该怎样快速入门

云计算为什么要学Docker容器?该怎样快速入门?“云计算”作为未来网络甚至未来计算机行业的发展趋势,得到了广泛重视。越来越多的人想通过学习云计算收获高薪,很多人会发现学习云计算的过程中会接触到Docker容器,这究竟是为什么?如何快速高效的学好Docker容器、进而学好云计算呢?下面且看小编的分析。

%title插图%num

Docker是基于Linux 容器技术的开源项目,它使用Luinux的内核功能(如命名空间和控制组)在操作系统上创建容器。Docker容器具有四大优势:

1)使用简单:Docker 的口头禅是:“一次构建,处处运行”。它使得任何人(开发人员,运维,架构师和其他人)都可以更轻松的利用容器的优势来快速构建和测试可移植的应用程序。

2)速度:Docker容器非常轻量级和快速,因为容器只是运行在内核上的沙盒环境,因此它们占用的资源更少。与可能需要更多时间来创建的虚拟机相比,你可以在几秒钟内创建一个Docker容器。

3)Docker Hub:Docker Hub拥有数万个由社区构建的公共镜像,这些镜像都是随时可用的。Docker用户可以从日益丰富的Docker Hub生态中受益,可以把Docker Hub看作是“Docker 镜像的应用商店”。

4)模块化和可扩展性:Docker可以让你轻松地把应用程序按功能拆分为单个独立的容器。使用Docker,将这个容器链接在一起以创建你的应用程序将会变得更简单,同时在将来可以很轻松地扩展和更新单独的组件。

想要快速入门Docker容器技术,你需要了解Docker容器的安装与启动、镜像操作、应用部署、备份与迁移等知识。同时,Docker容器技术多是与云计算相结合,想要学好Docker找到好工作,参加专业的云计算培训班是明智的。

如果你想成为一个优秀的云计算人才,要掌握Linux知识,了解数据库知识、Docker容器、Shell脚本运维、Python语言等,如果你想快速掌握这一系列的技术,专业的学习让你高效、快速掌握企业所需的高薪技术!

DL-常用函数及其作用

DL-常用函数及其作用

1、optimizer.zero_grad(),loss.backward()和optimizer.step()三个函数
在用pytorch训练模型时,通常会在遍历epochs的过程中依次用到optimizer.zero_grad(),loss.backward()和optimizer.step()三个函数,如下所示:

model = MyModel()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)

for epoch in range(1, epochs):
for i, (inputs, labels) in enumerate(train_loader):
output= model(inputs)
loss = criterion(output, labels)

# compute gradient and do SGD step
optimizer.zero_grad()
loss.backward()
optimizer.step()
总得来说,这三个函数的作用是先将梯度归零(optimizer.zero_grad()),然后反向传播计算得到每个参数的梯度值(loss.backward()),*后通过梯度下降执行一步参数更新(optimizer.step())

optimizer.zero_grad():

def zero_grad(self):
r”””Clears the gradients of all optimized :class:`torch.Tensor` s.”””
for group in self.param_groups:
for p in group[‘params’]:
if p.grad is not None:
p.grad.detach_()
p.grad.zero_()
optimizer.zero_grad()函数会遍历模型的所有参数,通过p.grad.detach_()方法截断反向传播的梯度流,再通过p.grad.zero_()函数将每个参数的梯度值设为0,即上一次的梯度记录被清空。

清零原因:训练的过程通常使用mini-batch方法,如果不将梯度清零的话,梯度会与上一个batch的数据相关,因此该函数要写在反向传播和梯度下降之前。
loss.backward():
PyTorch的反向传播(即tensor.backward())是通过autograd包来实现的,autograd包会根据tensor进行过的数学运算来自动计算其对应的梯度。

具体来说,torch.tensor是autograd包的基础类,

如果设置tensor的requires_grads为True,就会开始跟踪这个tensor上面的所有运算,

如果做完运算后使用tensor.backward(),所有的梯度就会自动运算,tensor的梯度将会累加到它的.grad属性里面去。

更具体地说,损失函数loss是由模型的所有权重w经过一系列运算得到的,

若某个w的requires_grads为True,则w的所有上层参数(后面层的权重w)的.grad_fn属性中就保存了对应的运算,

然后在使用loss.backward()后,会一层层的反向传播计算每个w的梯度值,并保存到该w的.grad属性中。

如果没有进行tensor.backward()的话,梯度值将会是None,因此loss.backward()要写在optimizer.step()之前。
optimizer.step():

以SGD为例,torch.optim.SGD().step()源码如下:

def step(self, closure=None):
“””Performs a single optimization step.
Arguments:
closure (callable, optional): A closure that reevaluates the model
and returns the loss.
“””
loss = None
if closure is not None:
loss = closure()

for group in self.param_groups:
weight_decay = group[‘weight_decay’]
momentum = group[‘momentum’]
dampening = group[‘dampening’]
nesterov = group[‘nesterov’]

for p in group[‘params’]:
if p.grad is None:
continue
d_p = p.grad.data
if weight_decay != 0:
d_p.add_(weight_decay, p.data)
if momentum != 0:
param_state = self.state[p]
if ‘momentum_buffer’ not in param_state:
buf = param_state[‘momentum_buffer’] = torch.clone(d_p).detach()
else:
buf = param_state[‘momentum_buffer’]
buf.mul_(momentum).add_(1 – dampening, d_p)
if nesterov:
d_p = d_p.add(momentum, buf)
else:
d_p = buf

p.data.add_(-group[‘lr’], d_p)

return loss
step()函数的作用是执行一次优化步骤,通过梯度下降法来更新参数的值。因为梯度下降是基于梯度的,所以在执行optimizer.step()函数前应先执行loss.backward()函数来计算梯度。

注意:optimizer只负责通过梯度下降进行优化,而不负责产生梯度,梯度是tensor.backward()方法产生的。

参考https://blog.csdn.net/PanYHHH/article/details/107361827
2、assert(断言)

用于判断一个表达式,在表达式条件为 false 的时候触发异常。

断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况,例如我们的代码只能在 Linux 系统下运行,可以先判断当前系统是否符合条件。

使用实例

>>> assert True # 条件为 true 正常执行
>>> assert False # 条件为 false 触发异常
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
AssertionError
>>> assert 1==1 # 条件为 true 正常执行
>>> assert 1==2 # 条件为 false 触发异常
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
AssertionError

>>> assert 1==2, ‘1 不等于 2’
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
AssertionError: 1 不等于 2
>>>
3、torch.cat()

函数目的: 在给定维度上对输入的张量序列seq 进行连接操作。

outputs = torch.cat(inputs, dim=0) → Tensor
参数

inputs : 待连接的张量序列,可以是任意相同Tensor类型的python 序列
dim : 选择的扩维, 必须在0到len(inputs[0])之间,沿着此维连接张量序列。
C = torch.cat( (A,B),0 ) #按维数0拼接(竖着拼)

C = torch.cat( (A,B),1 ) #按维数1拼接(横着拼)
示例

>>> import torch
>>> A=torch.ones(2,3) #2×3的张量(矩阵)
>>> A
tensor([[ 1., 1., 1.],
[ 1., 1., 1.]])
>>> B=2*torch.ones(4,3) #4×3的张量(矩阵)
>>> B
tensor([[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.]])
>>> C=torch.cat((A,B),0) #按维数0(行)拼接
>>> C
tensor([[ 1., 1., 1.],
[ 1., 1., 1.],
[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.]])
>>> C.size()
torch.Size([6, 3])
>>> D=2*torch.ones(2,4) #2×4的张量(矩阵)
>>> C=torch.cat((A,D),1)#按维数1(列)拼接
>>> C
tensor([[ 1., 1., 1., 2., 2., 2., 2.],
[ 1., 1., 1., 2., 2., 2., 2.]])
>>> C.size()
torch.Size([2, 7])
4、slice()

slice() 函数返回 slice 对象(切片)。

slice 对象用于指定如何对序列进行裁切。您可以指定在哪里开始裁切以及在哪里结束裁切。您还可以指定步进,例如只切每隔一个项目。

语法:

slice(start, end, step)
参数值

start 可选。整数,指定在哪个位置开始裁切。默认为 0。
end 可选。整数,指定在哪个位置结束裁切。
step 可选。整数,指定裁切的步进值。默认为 1。
示例:

a = (“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”)

x = slice(2)

print(a[x])
运行结果:
(‘a’, ‘b’)
——————————————–

a = (“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”)

x = slice(3, 5)

print(a[x])
运行结果:
(‘d’, ‘e’)
———————————————-

a = (“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”)

x = slice(0, 8, 3)

print(a[x])
运行结果:
(‘a’, ‘d’, ‘g’)
5、 *args:表示接受任意长度的参数,然后存放入一个元组中;如def fun(*args) print(args),‘fruit’,’animal’,’human’作为参数传进去,输出(‘fruit’,’animal’,’human’)

6、**kwargs:表示接受任意长的参数,然后存放入一个字典中;如

def fun(**kwargs):
for key, value in kwargs.items():
print(“%s:%s” % (key,value)
输出:
fun(a=1,b=2,c=3)会输出 a=1 b=2 c=3
7、semilogy()绘图

semilogy 将使用 y 轴的对数刻度绘制数据。

d2l.semilogy(range(1, num_epochs + 1), train_ls, ‘epochs’, ‘rmse’,

range(1, num_epochs + 1), valid_ls,

[‘train’, ‘valid’])
8、plot()绘图

a、plot(y)

当y为向量时,是以y的分量为纵坐标,以元素序号为横坐标,用直线依次连接数据点,绘制曲线。若y为实矩阵,则按列绘制每列对应的曲线。

b、plot(x,y)

若y和x为同维向量,则以x为横坐标,y为纵坐标绘制连线图。若x是向量,y是行数或列数与x长度相等的矩阵,则绘制多条不同色彩的连线图,x被作为这些曲线的共同横坐标。若x和y为同型矩阵,则以x,y对应元素分别绘制曲线,曲线条数等于矩阵列数。

c、plot(x1,y1,x2,y2,……)

在此格式中,每对x,y必须符合plot(x,y)中的要求,不同对之间没有影响,命令将对每一对x,y绘制曲线。

以上三种格式中的x,y都可以是表达式。plot是绘制一维曲线的基本函数,但在使用此函数之前,须先定义曲线上每一点的x以及y坐标。

9、pytorch detach() item() cpu() numpy()

item()返回的是tensor中的值,且只能返回单个值(标量),不能返回向量,使用返回loss等。

detach阻断反向传播,返回值仍为tensor

cpu()将变量放在cpu上,仍为tensor:

numpy()将tensor转换为numpy:
注意cuda上面的变量类型只能是tensor,不能是其他

loss.item() # 获得loss的值

——————————–

gpu_info.detach() #返回tensor,仍在gpu上

tensor([[ 0.9621, -1.0931, -0.8481],
[-0.1668, -1.3945, 0.6562],
[ 0.6152, 0.4177, -0.3538]], device=’cuda:0′)
——————————————-
gpu_info.cpu()

tensor([[ 0.9621, -1.0931, -0.8481],
[-0.1668, -1.3945, 0.6562],
[ 0.6152, 0.4177, -0.3538]])
———————————–
gpu_info.cpu().numpy()

array([[ 0.9621306 , -1.0930926 , -0.8481391 ],
[-0.1667992 , -1.3945109 , 0.656157 ],
[ 0.6151904 , 0.41773367, -0.35378388]], dtype=float32)

10、concat方法相当于数据库中的全连接(UNION ALL),可以指定按某个轴进行连接,也可以指定连接的方式join(outer,inner 只有这两种)。

与数据库不同的是concat不会去重,要达到去重的效果可以使用drop_duplicates方法

concat(objs, axis=0, join=’outer’, join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False, copy=True):
运行结果:

from pandas import Series,DataFrame,concat

df1 = DataFrame({‘city’: [‘Chicago’, ‘San Francisco’, ‘New York City’], ‘rank’: range(1, 4)})
df2 = DataFrame({‘city’: [‘Chicago’, ‘Boston’, ‘Los Angeles’], ‘rank’: [1, 4, 5]})
print ‘按轴进行内连接\r\n’,concat([df1,df2],join=”inner”,axis=1)
print ‘进行外连接并指定keys(行索引)\r\n’,concat([df1,df2],keys=[‘a’,’b’]) #这里有重复的数据
print ‘去重后\r\n’,concat([df1,df2],ignore_index=True).drop_duplicates()
————————————————————————-
运行结果:
按轴进行内连接
city rank city rank
0 Chicago 1 Chicago 1
1 San Francisco 2 Boston 4
2 New York City 3 Los Angeles 5

进行外连接并指定keys(行索引)
city rank
a 0 Chicago 1
1 San Francisco 2
2 New York City 3
b 0 Chicago 1
1 Boston 4
2 Los Angeles 5

去重后
city rank
0 Chicago 1
1 San Francisco 2
2 New York City 3
4 Boston 4
5 Los Angeles 5

 

内容审核:用python实现内容鉴黄

内容审核:用python实现内容鉴黄

随着网络监管越来越严格,UGC网站都需要针对用户生产的内容,进行审核。

目前大家一般是机器和人工审核的双重过滤。针对大型的UGC网站,如果全部人工审核是不现实的,需要花费大量的人工成本,所以机器审核尤其重要。

废话不多说,给大家介绍下怎么利用python进行鉴黄。

思路
下面给大家说明下图片审核的思路。

视频审核与图片审核是通用的。视频内容实则由音频内容、视频画面内容两个对象组成,视频画面内容的机器审核,业界目前常采用截取画面帧上传识别,*终复用的是图片识别通道对场景、人物、物品进行判断是否违规。

遍历图片每一个像素,进行颜色分区、并记录是否为肤色;

皮肤区域小于 3 个,不是色情;

如果皮肤区域与整个图像的比值小于 15%,那么不是色情图片;

如果*大皮肤区域小于总皮肤面积的 45%,不是色情图片;

皮肤区域数量超过 60个,不是色情图片;

其它情况为色情图片。

关键代码
# 分析区域
def _analyse_regions(self):
# 如果皮肤区域小于 3 个,不是色情
if len(self.skin_regions) < 3:
self.message = “Less than 3 skin regions ({_skin_regions_size})”.format(
_skin_regions_size=len(self.skin_regions))
self.result = False
return self.result

# 为皮肤区域排序
self.skin_regions = sorted(self.skin_regions, key=lambda s: len(s),
reverse=True)

# 计算皮肤总像素数
total_skin = float(sum([len(skin_region) for skin_region in self.skin_regions]))

# 如果皮肤区域与整个图像的比值小于 15%,那么不是色情图片
if total_skin / self.total_pixels * 100 < 15:
self.message = “Total skin percentage lower than 15 ({:.2f})”.format(total_skin / self.total_pixels * 100)
self.result = False
return self.result

# 如果*大皮肤区域小于总皮肤面积的 45%,不是色情图片
if len(self.skin_regions[0]) / total_skin * 100 < 45:
self.message = “The biggest region contains less than 45 ({:.2f})”.format(len(self.skin_regions[0]) / total_skin * 100)
self.result = False
return self.result

# 皮肤区域数量超过 60个,不是色情图片
if len(self.skin_regions) > 60:
self.message = “More than 60 skin regions ({})”.format(len(self.skin_regions))
self.result = False
return self.result

# 其它情况为色情图片
self.message = “色情图片”
self.result = True
return self.result
运行效果

%title插图%num

luffy数据库的创建

luffy数据库的创建

05.luffy数据库的创建
文章目录
05.luffy数据库的创建
一、创建数据库
二、创建用户,授予权限
三、在Django项目中配置
1.在 setting.py (dev.py)中配置
2.通过服务器环境变量来存放/获取密码
一、创建数据库
新建一个luffy数据库

可以使用图形化工具Navicat创建,鼠标点点即可

可以使用命令行创建

# 1.管理员连接数据库
mysql -uroot -p密码

# 2.创建数据库
create database luffy default charset=utf8;

进入到该数据库查看数据库用户

%title插图%num

# 使用luffy数据库
use luffy

# 查看用户
select user,host,password from mysql.user;

# 5.7之上的的版本查看命令 (提示: 5.7之后password字段变成了authentication_string字段)
select user,host,authentication_string from mysql.user;

二、创建用户,授予权限
注意:基于root用户进行的操作

创建luffy用户,授予luffy库所有权限

# 设置权限账号密码
# 授权账号命令:grant 权限(create, update) on 库.表 to ‘账号’@’host’ identified by ‘密码’

# 1.配置任意ip都可以连入数据库的账户 (提示:%表示任意的地址都可以远程链接)
grant all privileges on luffyapi.* to ‘luffyapi’@’%’ identified by ‘Luffy123?’;

# 2.由于数据库版本的问题,可能本地还连接不上,就给本地用户单独配置
grant all privileges on luffyapi.* to ‘luffyapi’@’localhost’ identified by ‘Luffy123?’;

# 3.刷新一下权限。 (提示: 如果不刷新,只会在下次登录时生效。)
flush privileges;

# 只能操作luffy数据库的账户
账号:luffyapi
密码:Luffy123?

三、在Django项目中配置
1.在 setting.py (dev.py)中配置
# 1.安装配置数据库mysql
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.mysql’,
‘NAME’: ‘luffy’,
‘USER’: ‘luffy’,
‘PASSWORD’: ‘Luffy123?’,
‘HOST’: ‘localhost’,
‘PORT’: 3306,
‘CHARSET’: ‘utf8’,
}
}

# 2.安装pymysql,或者是mysqlclient
-运气好:一把装好就用mysqlclient
-pip3 install mysqlclient
-或者使用pymysql(django版本超过2.0.7,需要改源码)
-使用pymysql不要忘了在配置文件中加入
import pymysql
pymysql.install_as_MySQLdb()

问题:如果项目上线后代码泄露,数据库密码很容易泄露,安全性不高,所以,一般我们PASSWORD密码不因该存放到pro.py或者dev.py配置文件中。 因此存放到服务器中, 通过环境变量的获取存放。

2.通过服务器环境变量来存放/获取密码

%title插图%num
password = os.getenv(‘mysql_password’,’Luffy12333′) # 或者下面语句
# password = os.environ.get(‘MYSQL_PASSWORD’,’Luffy12333′))

DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.mysql’,
‘NAME’: ‘luffy’,
‘USER’: ‘luffy’,
‘PASSWORD’: password,
‘HOST’: ‘localhost’,
‘PORT’: 3306
}
}

import pymysql
pymysql.install_as_MySQLdb()

Windows配置完环境变量需要重启电脑,否则启动项目报错

Linux重新加载配置文件即可

# 方式一:
source /etc/profile
# 方式二:
. /etc/profile

使用pymysql 版本问题出现的报错信息 :

使用pymysql时, Django版本超过 2.0.7 的时候就会出现这种错误

%title插图%num

%title插图%num

# 修改前
query = query.decode(errors=’replace’)

# 修改后
query = query.encode(errors=’replace’)

修改后启动成功

PS: 如果不想使用pymysql,可以直接安装mysqlclient

pip install mysqlclient

# mysqlclient 比较难装, 运气好一次可以装好, 是在不行不要强求

数据结构之数组结构

数据结构之数组结构

数组结构
线性表
数组
矩阵
矩阵相加

矩阵相乘

矩阵转置

稀疏矩阵

上三角矩阵

以行为主
k = n ∗ ( i − 1 ) − i ( i − 1 ) / 2 + j k = n * (i-1) – i(i-1)/2 + j
k=n∗(i−1)−i(i−1)/2+j

以列为主

k = j ( j − 1 ) / 2 + i k=j(j-1)/2 + i
k=j(j−1)/2+i

右上三角矩阵
左上三角矩阵
下三角矩阵

以行为主
k = i ( i − 1 ) / 2 + j k = i(i-1)/2 + j
k=i(i−1)/2+j

以列为主
k = n ∗ ( j − 1 ) + i − j ( j − 1 ) / 2 k = n * (j-1) + i – j(j -1) /2
k=n∗(j−1)+i−j(j−1)/2

右下三角矩阵

左下三角矩阵

带状矩阵

数组与多项式
设计一个python程序,进行多项式的计算:A(x) = 3x^4 + 7x^3 + 6x +2和B(x) = x^4 +5x^3 + 2x^2 + 9的加法运算
1
一个多项式如果使用数组结构存储在计算机中,有一下两种方法表示:

使用一个n+2长度的一组数组来存放,数组的*个位置存储*大指数n项的系数,其他位置按照指数n递减,按序存储对应项的系数:P=(n,an,an-1,…,a1,a0),存储在A(1:n+2)中,例如:

P(x) = 2x^5 + 3x^4 + 5x^2 + 4x + 1可以转换为A数组来表示,例如A=[5,2,3,0,5,4,1]。

只存储多项式中的非零项。如果有m项非零项,就使用2m+1的数组来存储每一个非零项的指数和系数,数组的*个元素为此多项式非零项的个数。

P(x) = 2x^5 + 3x^4 + 5x^2 + 4x + 1可以表示为A(1:2m+1)数组,例如:

A=[5,2,5,3,4,5,2,4,1,1,0]

采用*种多项式的方法进行上述题目的运算

“””
A(x) = 3x^4 + 7x^3 + 6x + 2 和 B(x) = x^4 + 5x^3 + 2x^2 + 9的加法运算
“””

ITEMS = 6
“””
poly:表示多项式的数组
items:数组的长度
“””
def PrintPoly(Poly,items):
#*高指数
MaxExp = Poly[0]
for i in range(1,Poly[0] + 2):
MaxExp =MaxExp – 1
if Poly[i] != 0:
if(MaxExp + 1) != 0:
print(‘ %dx^%d ‘ %(Poly[i],MaxExp + 1),end=”)
else:
print(‘ %d’ %Poly[i],end=”)
if MaxExp >= 0:
print(‘+’,end=”)
print()

“””
Poly1:多项式1
Poly2:多项式2
“””
def PolySum(Poly1,Poly2):
result = [None] * ITEMS
result[0] = Poly1[0]
for i in range(1,Poly1[0] + 2):
result[i] = Poly1[i] + Poly2[i]
PrintPoly(result,ITEMS)

PolyA = [4,3,7,0,6,2]
PolyB = [4,1,5,2,0,9]
print(“多项式A=>”,end=”)
PrintPoly(PolyA,ITEMS)
print(“多项式B=>”,end=”)
PrintPoly(PolyB,ITEMS)
print(“A+B=>”,end=”)
PolySum(PolyA,PolyB)
%title插图%num

爬虫入门 requests库

爬虫入门 requests库

异常处理代码框架

%title插图%num

import requests
def getHtmlText(url):
try:
r=requests.get(url,timeout=30)
r.raise_for_status()/不是200 引发httperror
r.encoding=r.apparent_encoding
return r.text
except:
return “产生异常”
if __name__ ==”__main__”:
url=”http://www.ba23idu1.com”
print(getHtmlText(url))
r在这是response类型的对象

Http 协议:

**HTTP**,Hypertext Transfer Protocol,超文本传输协议

HTTP是一个基于“请求与响应”模式的、无状态的应用层协议

HTTP协议采用URL作为定位网络资源的标识,URL格式如下:

http://host[:port][path]

host: 合法的Internet主机域名或IP地址

port: 端口号,缺省端口为80

path: 请求资源的路径

%title插图%num

requests库的七个主要方法:

用法:

head:
import requests
r=requests.head(“http://www.baidu.com”)
print(r.headers)
print(r.text)
/*
{‘Cache-Control’: ‘private, no-cache, no-store, proxy-revalidate, no-transform’, ‘Connection’: ‘keep-alive’, ‘Content-Encoding’: ‘gzip’, ‘Content-Type’: ‘text/html’, ‘Date’: ‘Fri, 07 May 2021 01:25:26 GMT’, ‘Last-Modified’: ‘Mon, 13 Jun 2016 02:50:08 GMT’, ‘Pragma’: ‘no-cache’, ‘Server’: ‘bfe/1.0.8.18’}
*/

post
payload ={‘key1′:’value1′,’key2′:’value2′}
r=requests.post(url,data=payload)
或者
r=requests.post(url,data=’abc’)
// 向url post一个字符串 自动编码为data

put
payload = {‘key1’: ‘value1’, ‘key2’: ‘value2’}
r = requests.put(url, data = payload)
1
2
requests.request(method, url, **kwargs)

method 请求方式,对应get/put/post等7种

url 拟获取页面的url链接

**kwargs 控制访问的参数,共13个

method: get head post put patch delete options

**kwargs:
params : 字典或字节序列,作为参数增加到url中
kv = {‘key1’: ‘value1’, ‘key2’: ‘value2’}
r = requests.request(‘GET’, ‘http://python123.io/ws’, params=kv)
data : 字典、字节序列或文件对象,作为Request的内容
kv = {‘key1’: ‘value1’, ‘key2’: ‘value2’}
r = requests.request(‘POST’, ‘http://python123.io/ws’, data=kv)
json : JSON格式的数据,作为Request的内容
kv = {‘key1’: ‘value1’}
r = requests.request(‘POST’, ‘http://python123.io/ws’, json=kv)
headers : 字典,HTTP定制头
hd = {‘user‐agent’: ‘Chrome/10’}
r = requests.request(‘POST’, ‘http://python123.io/ws’, headers=hd)
cookies : 字典或CookieJar,Request中的cookie
auth : 元组,支持HTTP认证功能
files : 字典类型,传输文件
fs = {‘file’: open(‘data.xls’, ‘rb’)}
r = requests.request(‘POST’, ‘http://python123.io/ws’, files=fs)
timeout : 设定超时时间,秒为单位
r= requests.request(‘GET’, ‘http://www.baidu.com’, timeout=10)
proxies : 字典类型,设定访问代理服务器,可以增加登录认证
pxs = { ‘http’: ‘http://user:pass@10.10.10.1:1234’
‘https’: ‘https://10.10.10.1:4321’ }
r = requests.request(‘GET’, ‘http://www.baidu.com’, proxies=pxs)
allow_redirects : True/False,默认为True,重定向开关
stream : True/False,默认为True,获取内容立即下载开关
verify : True/False,默认为True,认证SSL证书开关
cert : 本地SSL证书路径

requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)
requests.get(url, params=None, **kwargs)

模拟浏览器

import** requests

kv={‘user-agent’:’Mozilla/5.0′}

r=requests.get(“https://www.amazon.com/”,headers=kv)

print(r.status_code)

200

百度接口:
http://www.baidu.com/s?wd=keyword
360:
http://www.so.com/s?q=keyword

import requests
kv={‘wd’:’王泽坤’}
r=requests.get(“http://www.baidu.com/s”,params=kv)
print(r.text)

ip查询接口:

http://m.ip138.com/ip.asp?ip=ipaddress

 

ryu实例—网络聚合(LACP)

ryu实例—网络聚合(LACP)

这一篇重点介绍ryu来实现网络聚合的功能,建议先阅读关于LACP的知识,可以参考上一篇博文:https://blog.csdn.net/weixin_40042248/article/details/116395325?spm=1001.2014.3001.5501

一、拓扑构建

在介绍程序之前,先介绍一下实验拓扑的构建。拓扑如下图所示,其中h1和交换机连接的两条链路绑定在一个逻辑平面之中,接下来的实验就是针对这两个链路进行。%title插图%num

这个拓扑的构建,本实验选择namespace进行,新建h1-h4四个ns空间,然后新建s1作为ovs,具体的构建和配置命令如下,各位可以新建.sh文件,将以下命令全部复制进去,然后执行就行。

ip netns add h1
ip netns add h2
ip netns add h3
ip netns add h4

ovs-vsctl add-br s1

ip link add h1-eth0 type veth peer name s1-eth1
ip link add h1-eth1 type veth peer name s1-eth2
ip link add h2-eth0 type veth peer name s1-eth3
ip link add h3-eth0 type veth peer name s1-eth4
ip link add h4-eth0 type veth peer name s1-eth5

ip link set h1-eth0 netns h1
ip link set h1-eth1 netns h1
ip link set h2-eth0 netns h2
ip link set h3-eth0 netns h3
ip link set h4-eth0 netns h4

ovs-vsctl add-port s1 s1-eth1
ovs-vsctl add-port s1 s1-eth2
ovs-vsctl add-port s1 s1-eth3
ovs-vsctl add-port s1 s1-eth4
ovs-vsctl add-port s1 s1-eth5

ip link set s1-eth1 up
ip link set s1-eth2 up
ip link set s1-eth3 up
ip link set s1-eth4 up
ip link set s1-eth5 up

ip netns exec h2 ip link set lo up
ip netns exec h2 ip link set h2-eth0 up
ip netns exec h2 ip addr add 10.0.0.2/24 dev h2-eth0

ip netns exec h3 ip link set lo up
ip netns exec h3 ip link set h3-eth0 up
ip netns exec h3 ip addr add 10.0.0.3/24 dev h3-eth0

ip netns exec h4 ip link set lo up
ip netns exec h4 ip link set h4-eth0 up
ip netns exec h4 ip addr add 10.0.0.4/24 dev h4-eth0
然后输入命令ip netns exec h1 bash 进入h1的空间之中,首先新建文件/etc/modprobe.d/bonding.conf,并写入命令:

alias bond0 bonding
options bonding mode=4
然后执行命令

modprobe bonding
接下来,在h1中执行如下命令,下列命令是将h1的两个网卡绑定在一个逻辑平面之中,并统一设置一个ip地址。

ip link add bond0 type bond
ip link set bond0 address 02:01:02:03:04:08
ip link set h1-eth0 down
ip link set h1-eth1 down
ip link set h1-eth0 address 00:00:00:00:00:11
ip link set h1-eth0 address 00:00:00:00:00:22
ip link set h1-eth0 master bond0
ip link set h1-eth1 master bond0
ip addr add 10.0.0.1/24 dev bond0
ip link set bond0 up
*后,设置s1的远程控制器,命令:ovs-vsctl set-controller s1 tcp:127.0.0.1:6633

至此,本次实验的拓扑设置完成。

(说明:控制器运行simple_switch_13.py,拓扑使用上述拓扑,也可以正常的进行通信,但是倘若,将h1的其中一个端口移除逻辑平面,由于控制器无法得知端口状态的改变,所以流表项并不会更新,接下来的通信就可能会中断,也就达不到LACP可以利用冗余防止单点失效的效果,所以在SDN网络架构下,通过利用ryu程序实现LACP的功能,就需要控制器可以获知端口的状态情况,进而动态的改变流表项)

二、程序

在ryu的ryu/ryu/lib/lacplib.py中是ryu关于lacp的函数库,里面已经实现了各种lacp的连接和操作,我们只需要针对库进行调用,然后加入流表的添加和删除动作即可。

关于lacplib.py 的介绍,各位看官可以参考ryubook第四章的相关内容,可在链接(https://github.com/Yang-Jianlin/ryu/tree/master/spec_book)中下载。

本博文主要讲解一下,如何编写ryu应用程序在控制器中运行,实现LACP的功能。

新建一个类NetLacp,内容如下:

这里版本选择了openflow1.3,_CONTEXTS的含义主要是为该应用程序的运行添加依赖库,例如一个simple_switch.py的应用,如果没有OFPHandler应用作为数据收发和解析的基础的话,是无法运行的;

初始化中,add()方法在lacplib之中,作用就是将id为0000000000000001的交换机的1、2端口整合为一个逻辑平面,也就是和拓扑的h1的h1-eth0、h1-eth1对应,若要组成多个逻辑平面,只需要重复的调用add()方法即可。

class NetLacp(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
# 添加该应用程序运行所需要的依赖程序
_CONTEXTS = {‘lacplib’: lacplib.LacpLib}

def __init__(self, *args, **kwargs):
super(NetLacp, self).__init__(*args, **kwargs)
self._lacp = kwargs[‘lacplib’]
# 将交换机01的1、2端口绑定为一个逻辑平面
# 若网络中存在着多个逻辑平面,多个LACP,就需要调用多次add()
self._lacp.add(dpid=str_to_dpid(‘0000000000000001’), ports=[1, 2])
self.mac_table = {}
由于是在控制器实现LACP功能,所以在控制器和交换机完成握手动作后,就需要向交换机下发table-miss流表项(默认流表项),代码如下,add_flow()是添加流表项的方法,关于这一段代码的详细解析,参见:https://blog.csdn.net/weixin_40042248/article/details/115749340

def add_flow(self, datapath, priority, match, actions):
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser
command = ofp.OFPFC_ADD
inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)]
req = ofp_parser.OFPFlowMod(datapath=datapath, command=command,
priority=priority, match=match, instructions=inst)
datapath.send_msg(req)

# 当控制器和交换机开始的握手动作完成后,进行table-miss(默认流表)的添加
# 关于这一段代码的详细解析,参见:https://blog.csdn.net/weixin_40042248/article/details/115749340
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

# add table-miss
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER)]
self.add_flow(datapath=datapath, priority=0, match=match, actions=actions)
接下来,需要自定义packet_in的处理方法,用于packet_in消息的处理,控制器根据收到的交换机的消息进行转发表的学习和流表的下发等操作,虽然在lacplib中已经包含packet_in_handler方法了,但是lacp库中的函数不包含对消息的处理,仅仅是对LACP data unit的处理。

所以,构建packet_in_handler()函数,代码如下:

# 需要对流表和流表项做一系列的操作,这里和自学习交换机的packet_in一个道理
@set_ev_cls(lacplib.EventPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
global src, dst
msg = ev.msg
datapath = msg.datapath
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser
dpid = datapath.id
# msg实际上是json格式的数据,通过解析,找出in_port
# 可用print(msg)查看详细数据
in_port = msg.match[‘in_port’]
# 接下来,主要是解析出源mac地址和目的mac地址
pkt = packet.Packet(msg.data)
for p in pkt.protocols:
if p.protocol_name == ‘ethernet’:
src = p.src
dst = p.dst
print(‘src:{0} dst:{1}’.format(src, dst))

# 字典的样式如下
# {‘dpid’:{‘src’:in_port, ‘dst’:out_port}}
self.mac_table.setdefault(dpid, {})
# 转发表的每一项就是mac地址和端口,所以在这里不需要额外的加上dst,port的对应关系,其实返回的时候目的就是源
self.mac_table[dpid][src] = in_port

# 若转发表存在对应关系,就按照转发表进行;没有就需要广播得到目的ip对应的mac地址
if dst in self.mac_table[dpid]:
out_port = self.mac_table[dpid][dst]
else:
out_port = ofp.OFPP_FLOOD
actions = [ofp_parser.OFPActionOutput(out_port)]

# 如果执行的动作不是flood,那么此时应该依据流表项进行转发操作,所以需要添加流表到交换机
if out_port != ofp.OFPP_FLOOD:
match = ofp_parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src)
self.add_flow(datapath=datapath, priority=1,
match=match, actions=actions)

data = None
if msg.buffer_id == ofp.OFP_NO_BUFFER:
data = msg.data
# 控制器指导执行的命令
out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)
*后,程序需要对端口的状态改变做出反应,也就是说,在本例中,h1-eth0和h1-eth1的状态改变,即从逻辑平面bond0中移除后,控制器需要对移除做出反应,改变相应的流表项,这里对流表项的处理相对简单,只需要移除对应的流表项,然后重新进行自学习即可。代码如下:

# 删除流表的方法,本应用中,在物理平面的状态改变(所属的逻辑平面变化)之后,
# 需要将对于的流表项清除,否则达不到LACP的效果
def del_flow(self, datapath, match):
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

req = ofp_parser.OFPFlowMod(datapath=datapath,
command=ofp.OFPFC_DELETE,
out_port=ofp.OFPP_ANY,
out_group=ofp.OFPG_ANY,
match=match)
datapath.send_msg(req)

# 当交换机的状态出现变化时,就需要对流表做一些操作
@set_ev_cls(lacplib.EventSlaveStateChanged, MAIN_DISPATCHER)
def slave_state_changed_handler(self, ev):
# 对于这四行解析之所以这样,不同于之前的ev.msg,
# 可以打开lacplib.EventSlaveStateChanged中看一下初始化函数就明白了
datapath = ev.datapath
dpid = datapath.id
port = ev.port
enabled = ev.enabled
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

if dpid in self.mac_table:
for mac in self.mac_table[dpid]:
match = ofp_parser.OFPMatch(eth_dst=mac)
self.del_flow(datapath=datapath, match=match)
del self.mac_table[dpid]
self.mac_table.setdefault(dpid, {})
至此,实验的所有准备条件已经编写完成,关于实验的步骤各位在阅读https://blog.csdn.net/weixin_40042248/article/details/116395325?spm=1001.2014.3001.5501之后,可以自行进行实验,也可以参考ryubook相关内容的讲解,这里不再赘述,如有问题,读者留言或者私聊。

全部代码附录:

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.lib.dpid import str_to_dpid
from ryu.lib.packet import packet
from ryu.ofproto import ofproto_v1_3
from ryu.lib import lacplib
from ryu.controller.handler import set_ev_cls
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import CONFIG_DISPATCHER

”’
应用程序主要实现网络聚合(LACP)的功能,
”’

class NetLacp(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
# 添加该应用程序运行所需要的依赖程序
_CONTEXTS = {‘lacplib’: lacplib.LacpLib}

def __init__(self, *args, **kwargs):
super(NetLacp, self).__init__(*args, **kwargs)
self._lacp = kwargs[‘lacplib’]
# 将交换机01的1、2端口绑定为一个逻辑平面
# 若网络中存在着多个逻辑平面,多个LACP,就需要调用多次add()
self._lacp.add(dpid=str_to_dpid(‘0000000000000001’), ports=[1, 2])
self.mac_table = {}

def add_flow(self, datapath, priority, match, actions):
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser
command = ofp.OFPFC_ADD
inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)]
req = ofp_parser.OFPFlowMod(datapath=datapath, command=command,
priority=priority, match=match, instructions=inst)
datapath.send_msg(req)

# 删除流表的方法,本应用中,在物理平面的状态改变(所属的逻辑平面变化)之后,
# 需要将对于的流表项清除,否则达不到LACP的效果
def del_flow(self, datapath, match):
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

req = ofp_parser.OFPFlowMod(datapath=datapath,
command=ofp.OFPFC_DELETE,
out_port=ofp.OFPP_ANY,
out_group=ofp.OFPG_ANY,
match=match)
datapath.send_msg(req)

# 当控制器和交换机开始的握手动作完成后,进行table-miss(默认流表)的添加
# 关于这一段代码的详细解析,参见:https://blog.csdn.net/weixin_40042248/article/details/115749340
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

# add table-miss
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER)]
self.add_flow(datapath=datapath, priority=0, match=match, actions=actions)

# 需要对流表和流表项做一系列的操作,这里和自学习交换机的packet_in一个道理
@set_ev_cls(lacplib.EventPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
global src, dst
msg = ev.msg
datapath = msg.datapath
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser
dpid = datapath.id
# msg实际上是json格式的数据,通过解析,找出in_port
# 可用print(msg)查看详细数据
in_port = msg.match[‘in_port’]
# 接下来,主要是解析出源mac地址和目的mac地址
pkt = packet.Packet(msg.data)
for p in pkt.protocols:
if p.protocol_name == ‘ethernet’:
src = p.src
dst = p.dst
print(‘src:{0} dst:{1}’.format(src, dst))

# 字典的样式如下
# {‘dpid’:{‘src’:in_port, ‘dst’:out_port}}
self.mac_table.setdefault(dpid, {})
# 转发表的每一项就是mac地址和端口,所以在这里不需要额外的加上dst,port的对应关系,其实返回的时候目的就是源
self.mac_table[dpid][src] = in_port

# 若转发表存在对应关系,就按照转发表进行;没有就需要广播得到目的ip对应的mac地址
if dst in self.mac_table[dpid]:
out_port = self.mac_table[dpid][dst]
else:
out_port = ofp.OFPP_FLOOD
actions = [ofp_parser.OFPActionOutput(out_port)]

# 如果执行的动作不是flood,那么此时应该依据流表项进行转发操作,所以需要添加流表到交换机
if out_port != ofp.OFPP_FLOOD:
match = ofp_parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src)
self.add_flow(datapath=datapath, priority=1,
match=match, actions=actions)

data = None
if msg.buffer_id == ofp.OFP_NO_BUFFER:
data = msg.data
# 控制器指导执行的命令
out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)

# 当交换机的状态出现变化时,就需要对流表做一些操作
@set_ev_cls(lacplib.EventSlaveStateChanged, MAIN_DISPATCHER)
def slave_state_changed_handler(self, ev):
# 对于这四行解析之所以这样,不同于之前的ev.msg,
# 可以打开lacplib.EventSlaveStateChanged中看一下初始化函数就明白了
datapath = ev.datapath
dpid = datapath.id
port = ev.port
enabled = ev.enabled
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser

if dpid in self.mac_table:
for mac in self.mac_table[dpid]:
match = ofp_parser.OFPMatch(eth_dst=mac)
self.del_flow(datapath=datapath, match=match)
del self.mac_table[dpid]
self.mac_table.setdefault(dpid, {})
github地址:https://github.com/Yang-Jianlin/ryu/blob/master/ryu/app/lacp_yj

Linux台式机搭建FTP服务器

Linux台式机搭建FTP服务器

目录

Linux搭建FTP服务器

设置开机自动联网

内网端口映射

本文采用gedit编辑文件,方便复制,推荐学习vim

Linux搭建FTP服务器
首先换源:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

sudo gedit /etc/apt/sources.list
deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse

deb http://cn.archive.ubuntu.com/ubuntu bionic main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic-updates main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic-security main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic main multiverse restricted universe
更新源

sudo apt-get update
安装vsftpd

sudo apt-get install vsftpd
修改文件

sudo gedit /etc/vsftpd.conf
修改内容为,直接复制,覆盖原有代码

# 禁止匿名用户登录
anonymous_enable=NO
# 允许系统用户登录
local_enable=YES
# 启用可以修改文件的 FTP 命令
write_enable=YES
# 本地用户创建文件的 umask 值
local_umask=022
# 允许为目录配置显示信息,显示每个目录下面的message_file文件的内容
dirmessage_enable=YES
# 开启日记功能
xferlog_enable=YES
# 使用标准的20端口来连接ftp
connect_from_port_20=YES
# 使用标准日志格式
xferlog_std_format=YES
# 如果启动这项功能,则所有列在chroot_list_file之中的使用者不能更改根目录
chroot_list_enable=YES
# 指定限制的用户文件
chroot_list_file=/etc/vsftpd/chroot_list
# ftp服务器将处于独立启动模式
listen=YES
# 设置一个本地用户登录后进入到的目录
local_root=/home/ftp
# 设置PAM认证服务的配置文件名称,该文件保存在“/etc/pam.d/”目录下
pam_service_name=vsftpd
# ftp将检查userlist_file设置文件中指定的用户是否可以访问vsftpd服务器
userlist_enable=YES
# 只允许user_list文件中记录的ftp用户能登录vsftp服务,其他的ftp用户都不可以登录。
userlist_deny=NO
# 定义限制/允许用户登录的文件
userlist_file=/etc/vsftpd/allowed_users
# ftp服务器将使用tcp_wrappers作为主机访问控制模式
tcp_wrappers=YES
# 连接ftp服务费使用的端口
listen_port=21
创建文件夹和文件

sudo mkdir /etc/vsftpd

cd /etc/vsftpd

sudo touch chroot_list

sudo touch allowed_users
创建FTP根目录,并添加目录权限

sudo mkdir /home/ftp

sudo chmod -R 777 /home/ftp
添加用户,密码

sudo useradd -d /home/ftp -s /sbin/nologin chuangxin

sudo passwd chuangxin
在/etc/shells文件末尾添加

sudo gedit /etc/shells
添加到末尾

/sbin/nologin
添加用户到/etc/vsftpd/allowed_users

sudo gedit /etc/vsftpd/allowed_users

chuangxin
重启vsftpd服务

service vsftpd restart
查看vsftpd服务状态,绿灯表示正常连接

service vsftpd status
查看本机局域网ip

ifconfig
测试ftp连接

ftp 19.168.x.x
连接成功返回:

230 Login successful

设置开机自动联网
sudo apt-get install python3-pip

sudo apt-get install python3-bs4

pip3 install selenium

pip3 install requests
使用Ubuntu自带火狐浏览器实施模拟点击,

火狐webdriver下载地址

下载完成后,把geckodriver放到/usr/bin/目录下,并执行

chmod 777 /usr/bin/geckodriver
创建/home/chuangxin/auto_connect/auto_connect.py文件,注:下面py代码非原创,本文对登录部分稍加修改,忘记哪篇文章的作者写的了……

#coding:utf-8

from selenium import webdriver
from bs4 import BeautifulSoup
import time
import requests

username_str = “xxxxxxx” # 用户名
password_str = “xxxxxxx” # 密码

class Login:
def login(self):
try:
#time.sleep(60)
driver = webdriver.Firefox()
driver.get(“http://xxxxxxx.edu.cn/”) # 校园网登录的网址
time.sleep(3)
username_input = driver.find_element_by_xpath(‘//*[@placeholder=”账号”]’)
password_input = driver.find_element_by_xpath(‘//*[@placeholder=”密码”]’)
login_button = driver.find_element_by_xpath(‘//*[@value=”登录”]’)

username_input.send_keys(username_str)
password_input.send_keys(password_str)
login_button.click()
#time.sleep(5)
except:
print(username_input[2].text)
print(self.getCurrentTime(), u”登陆函数异常”)
finally:
driver.close()

#获取当前时间
def getCurrentTime(self):
return time.strftime(‘[%Y-%m-%d %H:%M:%S]’,time.localtime(time.time()))

#判断当前是否可以连网
def canConnect(self):
try:
baidu_request=requests.get(“http://www.baidu.com”)
if(baidu_request.status_code==200):
baidu_request.encoding = ‘utf-8’
baidu_request_bsObj = BeautifulSoup(baidu_request.text, ‘html.parser’)
baidu_input = baidu_request_bsObj.find(value=”百度一下”)
if baidu_input==None:
return False
return True
else:
return False
except:
print (‘error’)

#主函数
def main(self):
print (self.getCurrentTime(), u”Hi,SEU自动登陆脚本正在运行”)
while True:
while True:
can_connect = self.canConnect()
if not can_connect:
print (self.getCurrentTime(),u”断网了…”)
try:
self.login()
except:
print(self.getCurrentTime(), u”浏览器出了bug”)
finally:
time.sleep(2)
if self.canConnect():
print(self.getCurrentTime(), u”重新登陆成功”)
else:
print(self.getCurrentTime(), u”登陆失败,再来一次”)
else:
print (self.getCurrentTime(), u”一切正常…”)
time.sleep(5)
time.sleep(1)
time.sleep(self.every)

login = Login()
login.main()
创建脚本文件/home/chuangxin/auto_connect/auto_start.sh

#!/bin/bash

python3 /home/chuangxin/auto_connect/auto_connect.py &

exit 0
在ubuntu的搜索框中查找Startup Applications

点击add添加Name和Command

Name:随便写
Command:/usr/bin/gnome-terminal -x bash -c “/home/chuangxin/auto_connect/auto_start.sh;exec bash”
内网端口映射
可参考Windows端口映射,原理一样都是

网址输入192.168.1.1打开路由器管理,进入虚拟服务器,添加端口21和ip(192.168.x.x)

*后可以通过FileZilla或xftp软件连接实现上传和下载功能

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速