Django/多任务/网络通信/WEB搭建

多任务

多任务的概念:

至少有3个任务在同时运行,还有很多任务在后台悄悄的运行

多任务的实现有3种方式:

  • 多进程模式;

  • 多线程模式;

  • 多进程+多线程模式

并发:

指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

并行:

指的是任务数小于等于cpu核数,即任务真的是一起执行的。

多线程全局变量是共享的

在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据。缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)

多线程会出现的问题:

  • 如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确

互斥锁

互斥锁为资源引入一个状态:锁定/非锁定

某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

# 创建锁
mutex = threading.Lock()
# 锁定
mutex.acquire()
# 释放
mutex.release()
  • 如果这个锁之前是没有上锁的,那么acquire不会堵塞

  • 如果在调用acquire对这个锁上锁之前 它已经被 其他线程上了锁,那么此时acquire会堵塞,直到这个锁被解锁为止。

  • 和文件操作一样,Lock也可以使用with语句快速的实现打开和关闭操作

import threading
import time
​
ticket = 20
lock = threading.Lock()
​
​
def sell_ticket():
    global ticket
    while True:
        lock.acquire()
        if ticket > 0:
            time.sleep(0.5)
            ticket -= 1
            lock.release()
            print('{}卖了一张票,还剩{}'.format(threading.current_thread().name, ticket))
        else:
            print('{}票卖完了'.format(threading.current_thread().name))
            lock.release()
            break
​
​
for i in range(5):
    t = threading.Thread(target=sell_ticket, name='thread-{}'.format(i + 1))
    t.start()

上锁过程:

当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。

每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“阻塞”,直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。

线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

总结

锁的好处:

  • 确保了某段关键代码只能由一个线程从头到尾完整地执行

锁的坏处:

  • 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。

  • 由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁。

多线程通信

Queue的原理

Queue是一个先进先出(First In First Out)的队列,主进程中创建一个Queue对象,并作为参数传入子进程,两者之间通过put( )放入数据,通过get( )取出数据,执行了get( )函数之后队列中的数据会被同时删除,可以使用multiprocessing模块的Queue实现多进程之间的数据传递。

threading.current_thread() 获取当前正在执行的这段程序的名称

import threading
import time
from queue import Queue

进程

程序:例如xxx.py这是程序,是一个静态的。

进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元。

不仅可以通过线程完成多任务,进程也是可以的。

进程的状态

工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态

新建----就绪----等待----运行-----死亡。

  • 就绪态:运行的条件都已经满足,正在等在cpu执行。

  • 执行态:cpu正在执行其功能。

  • 等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态。

创建进程

multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。

方法说明

Process( target [, name [, args [, kwargs]]])

  • target:如果传递了函数的引用,可以任务这个子进程就执行这里的代码

  • args:给target指定的函数传递的参数,以元组的方式传递

  • kwargs:给target指定的函数传递命名参数

  • name:给进程设定一个名字,可以不设定

Process创建的实例对象的常用方法:

  • start():启动子进程实例(创建子进程)

  • is_alive():判断进程子进程是否还在活着

  • join([timeout]):是否等待子进程执行结束,或等待多少秒

  • terminate():不管任务是否完成,立即终止子进程

Process创建的实例对象的常用属性:

  • name:当前进程的别名,默认为Process-N,N为从1开始递增的整数

  • pid:当前进程的pid(进程号)

def task(n):
    print('{}----->start'.format(n))
    time.sleep(1)
    print('{}------>end'.format(n))
​
​
if __name__ == '__main__':
    p = Pool(8)  # 创建进程池,并指定线程池的个数,默认是CPU的核数
    for i in range(1, 11):
        # p.apply(task, args=(i,)) # 同步执行任务,一个一个的执行任务,没有并发效果
        p.apply_async(task, args=(i,)) # 异步执行任务,可以达到并发效果
    p.close()
    p.join()

功能

  • 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ。

  • 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口。

定义的不同

  • 进程是系统进行资源分配和调度的一个独立单位.

  • 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

区别

  • 一个程序至少有一个进程,一个进程至少有一个线程.

  • 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。

  • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率

  • 线线程不能够独立执行,必须依存在进程中

  • 可以将进程理解为工厂中的一条流水线,而其中的线程就是这个流水线上的工人

优缺点

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。

Queue的使用

  • Queue.qsize():返回当前队列包含的消息数量;

  • Queue.empty():如果队列为空,返回True,反之False ;

  • Queue.full():如果队列满了,返回True,反之False;

  • Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;

进程池

from multiprocessing import Pool
po = Pool(3)  # 定义一个进程池,最大进程数3
for i in range(0,10):
    # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
    # 每次循环将会用空闲出来的子进程去调用目标
    po.apply_async(worker,(i,))

multiprocessing.Pool常用函数解析:

  • apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;

  • close():关闭Pool,使其不再接受新的任务;

  • terminate():不管任务是否完成,立即终止;

  • join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

简单总结

  1. 进程是资源分配的单位

  2. 线程是操作系统调度的单位

  3. 进程切换需要的资源很最大,效率很低

  4. 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)

  5. 协程切换任务资源很小,效率高

  6. 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

网络通讯

ip地址

ip地址的作用:在互联网通信中,我们使用IP地址来查询到各个主机。

用来标记网络上的一台电脑 。同一个局域中不允许重复

dos 命令 ipconfig (查看IP地址)

什么是socket?

  • socket是来完成网络通信必备的东西。

  • socket(简称 套接字) 是进程间通信的一种方式。

  • 它与其他进程间通信的一个主要不同是

  • 它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的。

  • 例如我们每天浏览网页、QQ 聊天、收发 email 等等

UDP协议

UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议。

在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中,"写信"。

UDP的特点 :

类似于一个写信的模型,数据有可能会丢失。

相对于TCP创建要简单的多。

TCP协议

TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)

是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。(比较稳定的信息传输)

TCP通信需要经过创建连接、数据传送、终止连接三个步骤。

TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话"

TCP特点

面向连接:

  • 通信双方必须先建立连接才能进行数据的传输。

  • 数据传输前医药建立连接

  • 双方都必须为该连接分配必要的系统内核资源,管理连

    接的状态和连接上的传输。(稳定传输

可靠传输: 超时重传,错误效验, 流量控制和阻塞管理

TCP与UDP的区别

信息传输:

  • TCP 面向连接(确认有创建三方交握,连接已创建才作传输。)

    传输数据中 传递方成功收到数据后会给传递方回应收到数据了。

    没有收到数据会 :信息重传 、重发丢失的数据包 、舍弃重复的数据包

    、无差错的数据传输、阻塞/流量控制。保证了信息传递的可靠性。

  • UDP 可以直接发送数据 ,数据容易丢失 ,传输数据中 是否成功传递消息 是不会回应对方的。

  • 最终保证了 TCP 比 UTP稳定 直到现在 TCP也是长应用的。UTP一般不常用。

TCP 服务端创建流程:

  • socket 创建套接字

  • 建立一个地址 ip+端口

  • bind绑定 ip +port

  • listen 始套接字变为被动

  • sccpept 阻塞 等待客户连接

  • recv 、send 接受 发送

  • 关闭套接字

TCP 文件下载案例

TCP服务器端:

from socket import *
def get_dile_context(file_name):
    """ 打开文件功能"""
    try:
        # 追加打开文件,二进制只读模式 
        f = open(file_name, 'rb')
        countent = f.read(1024)    # 读取文件
        while countent:
            # 定义生成器 循环读取
            yield countent
            # 读取文件 直达读取结束
            countent = f.read(1024)
    except:
        # 异常处理
        print(f'数据{file_name}不存在')
        return None
​
def run_server():
    ''' tcp 发送文件 '''
    # 1.创建套接字
    server = socket(AF_INET,SOCK_STREAM)
    # 2.绑定端口 必须是元组类型
    server.bind(('', 6789))
    # 3.监听
    server.listen(128)
    """
    4.阻塞程序 将程序停留在这个一行等待客户端激活
      accept() 有返值是一个元组 (创新的调套接字,客户端的地址和端口)
      client== 客户端的连接相当于新的个管道 == 拨打10086 提供的客服 (又多打电话 就有对少客服)
        新产生的套接字 用来为客户服务
    当收到客户端发来的消息就会被唤醒
    """
    #adder 客户端的地址和端口
    client, addr = server.accept()
    print('访问客户端的地址为:', addr)
​
    # 接受用户端传递的消息 , 获取用户端的信息转码
    file_name =client.recv(1024).decode('utf-8')
    # 调用功能函数 打开文件
    gr = get_dile_context(file_name)
    # 循环发送
    for data in gr:
        client.send(data)
        print('服务端:',len(data))
    # 关闭
    client.close()
    server.close()
if __name__ == '__main__':
    # 调用
    run_server()

TCP客户端:

# 导入模块
from socket import *
​
# 创建套接字        ip v4    tcp
client = socket(AF_INET, SOCK_STREAM)
​
# 连接信息 ip地址 +端口
addr = ('localhost',6789)
​
# tcp 通信三次握手机会
client.connect(addr) # 元组
​
# 下载文件
file_name = input("请输入要下载的文件名:")
# 转码 发送
client.send(file_name.encode("utf-8"))
​
# 接受文件
date = client.recv(1024)
​
# 循环接受
while date:
    # 新建文件    字符串拼接      二进制写入追加
    with open('[新]'+file_name,'ab') as f:
        f.write(date)
    # 再次执行打开 直到循环结束
    date = client.recv(1024)
    # 打印了一个传输状态
    print('客户端:',len(date))
​
# 提示结束了
print('结束了')

Day 8 HTTP 协议

Linux系统

命令:

查看文件下所有目录:dir

Day 1 操作系统

hello_2106A: 专业二的代码

计算机由硬件软件两大部分组成,软件部分里又被分为系统软件和应用软件,而在系统软件里,又有一个操作系统。

没有安装操作系统的计算机,通常被称为 裸机

如果想在 裸机 上运行自己所编写的程序,就必须用机器语言书写程序

## 什么是操作系统

> 是现代计算机系统中 最基本和最重要 的系统软件 > > 是 配置在计算机硬件上的第一层软件,是对硬件系统的首次扩展 > > 主要作用是管理好硬件设备,并为用户和应用程序提供一个简单的接口,以便于使用 > > 而其他的诸如编译程序、数据库管理系统,以及大量的应用软件,都直接依赖于操作系统的支持

### 操作系统分类

> 桌面操作系统 > > ​ 服务器操作系统 > > ​ 嵌入式操作系统 > > ​ 移动设备操作系统

### 桌面操作系统

- Windows 系列 - 用户群体大 - macOS - Linux - 应用软件少

### 服务器操作系统

- Linux

- 安全、稳定、免费 - 占有率高

- Windows Server

- 付费

- 占有率低

### 嵌入式操作系统

- Linux

### 移动设备操作系统

- Android、iOS、Symbian、WindowsMobile、BlackBerry

## Linux系统介绍

Linux是一套免费使用和自由传播的类Unix操作系统,基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统,继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

主要特征 :基本思想、 完全免费 、完全兼容POSIX1.0标准、多用户,多任务 、良好的界面 、支持多种平台

## Linux启动流程(了解)

启动加载BIOS:BIOS是系统启动时加载的第一个软件。

开机自检

对外部设备进行初始化,读取BIOS参数

查找MBR(Master Boot Record,主引导分区)。如果未找到,会提示找不到硬盘。

读取主引导分区(MBR)

启动引导代码(bootloader

加载内核,进入操作系统 :运行第一个程序 : /sbin/ini。

sbin/init 会读取相关的配置文件,来确定系统的运行级别。

根据对应的运行级别,查找对应的脚本文件。

## 远程连接Linuxpw

在实际开发中,Linux服务器都是被放在服务器机房里的,不能直接进入到服务器机房去操作这台Linux服务器,而是通过一些远程链接工具,对Linux服务器进行管理。

## SSH协议

SSH 为 Secure Shell的缩写,由 IETF 的网络小组(Network Working Group)所制定;

SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。

Ubuntu默认没有安装ssh服务,需要我们使用代码手动的在Ubuntu服务器上安装ssh服务。

## 软件安装相关指令

在Linux中,很多功能需要使用命令行来实现,我们甚至可以不使用桌面,只使用终端命令在Linux里实现绝大多数功能。

令的基本格式:

```python 命令: [选项] [参数] 例如: ls -a # 表示列出根目录下所有的文件及文件夹 (先进入根目录) ```

Linux系统可以分为Debian和RedHat两大分支。基于Debian平台比较流行的操作系统是Ubuntu,基于RedHat平台比较流行的操作系统是fedora.两种不同的分支,它们所使用的软件管理命令也是不一样的。

基于Debian平台的操作系统,使用dpkg和apt指令管理软件,基于RedHat平台的操作系统,使用rpm和yum指令来管理软件。它们的命名方式不同,但是命令的执行效果大致相同,基于Fedora平台CentOS系统下的rpmyum指令。

## 软件管理相关指令

简单来说,Linux系统可以分为Debian和RedHat两大分支。基于Debian平台比较流行的操作系统是Ubuntu,基于RedHat平台比较流行的操作系统是fedora.两种不同的分支,它们所使用的软件管理命令也是不一样的。

基于Debian平台的操作系统,使用dpkg和apt指令管理软件,基于RedHat平台的操作系统,使用rpm和yum指令来管理软件。它们的命名方式不同,但是命令的执行效果大致相同,我们主要学习基于Fedora平台CentOS系统下的rpmyum指令。

### rpm(了解)

rpm是“Red-Hat Package Manager”的简写,为 Red Hat专门开发的套件管理系统,方便软件的安装、更新及移除。所有源自Red Hat的“Linux ”发行版都可以使用 rpm.

命令行作用示例
rpm -ivh <.rpm file name>安装.rpm后缀名的软件,并显示安装详情rpm -ivh google-chrome-stable_current_x86_64.rpm
rpm -e <packagename>删除指定的软件rpm -r google-chrome-stable
rpm -qa列出电脑上安装的所有包rpm -qa

### yum

yum(全称为 Yellow dog Updater, Modified)

是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。

基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装。

可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次 下载、安装。

命令行作用示例
yum search <packagename>搜索软件包yum search python
yum list installed列出已经安装的软件包yum list installed
yum install <packagename>用来安装指定的软件包yum install vim
yum remove用来移除软件包yum remove vim
yum update <packagename>更新软件包yum updat tar
yum check-update检查更新yum check-update
yum info <packagename>列出指定软件包详情yum info python

### 区别

yum是基于rpm的,它的功能更加强大。

场景rpmyum
离线的.rpm安装包能够安装,但是不能自动下载安装依赖能够安装,并且能够自动安装下载安装依赖
在线安装不支持,只能把安装包下载到本地安装支持在线下载安装

## 文件系统

### Linux里的文件系统

管理和存储文件信息的软件机构称为文件管理系统,简称文件系统

系统就是负责为用户建立读取修改转储文件控制文件的存取,当用户不 再使用时撤销文件等。

常见的文件系统介绍:

FAT16 :每个磁盘的分区最大只能达到2G,并且会浪费很多空间。

缺点:无法存放大于4GB的单个文件,而且容易产生磁盘碎片,性能不佳。

FAT32:Windows95以后的系统都支持。

在一个不超过8GB 的分区中FAT32分区格式的每个簇容量都固定为4KB,减少磁盘的浪费。

FAT不支持长文件名,只能支持8个字符,且后缀名最多只支持3个字符。

且后缀名最多只支持3个字符。

NTFS:WindowsNT系列设计,用来取代FAT系统。簇的空间更小,磁盘的利用率更 高,并且可以共享资源、文件夹以及对文件设置访问许可权限。

RAW:RAW文件系统是一种磁盘未经处理或者未格式化产生的文件系统

没有格式化、格式化中途取消、硬盘出现坏道、硬盘出现不可预知的错误

EXT:EXT是扩展文件系统,目前最新的版本是5.0.

HFS(+):苹果电脑上的文件系统。

## Linux里的文件系统

Linux里只有一个盘符,是从 " / " 开始的,只有它是没有上级目录的。

目录系统像树形结构," / " 相当于树形结构的根,将 " / " 称之为根目录

/ -- 系统的根目录(最顶级目录)

/bin -- 二进制文件,可执行文件。我们在命令行里执行的指令,如 ls,rm,cp,mv。

/boot -- 系统启动相关时所需的文件。(勿动)

/dev -- 设备文件,将新的网络摄像头连接到机器中,自动弹出一个新的设备条目。

/etc -- 用来存放所有的系统管理所需要的配置文件和子目录。

/home-- 用户的主目录,用户都有自己的目录,所有的用户都存放在home目录下。

(不是超级管理员 家都是在home里)

/lib(64) -- 用来存放系统最基本的动态连接共享库,几乎所有的应用程序。

/lost+found -- 目录一般情是空的,系统非法关机,会存放些没来得及保存的文件。

/mnt -- 该目录是为了让用户临时挂载别的文件系统的,可以将光盘挂载在/mnt/上

/opt -- 给额外安装软件摆放的目录。比如安装ORACLE数据库可以放到这个目录下

/proc -- 虚拟目录,它是系统内存的映射,可以通过直接访问这个目录取系统信息。

/root -- 超级用户目录。

/sbin -- 超级用户使用的命令存放目录。

/srv -- 存放一些服务启动之后需要提取的数据。

/sys -- 映射内核设备。

/tmp -- 存放临时文件。

/usr -- 非常重要的目录,用来存放用户安装的应用程序和用户文件。

/var -- 经常修改的数据,比如程序运行的日志文件

以 " . " 开头的文件是隐藏文件。

" ./ " 表示的是当前目录; “ ../ ” 表示的上级目录

“ ~ ” 表示的当前用户的家目录

## 目录操作的常见指令

pwd:查看当前工作目录

cd:切换工作目录

符~号
.当前目录
..上一级目录
~当前用户的家目录
-表示上次切换之前的目录
/表示根目录

> 1.使用cd时,不指定目标地址,会切换到家目录 > > 2.凡是以/开头的目录都是绝对目录 > > 3.凡是以.或..开头的目录都是相当目录

### ll:查指定目录内容,不指定目录时查看当前工作目录

选项说明
ll -a显示所有文件,包括隐藏文件 ,ll 空格 -a
ll -l列表显示,详细信息
ll -h人性化的显示大小,如:K/M/G

-l选项显示的结果:类型及权限 | 连接数 | 用户 | 用户组 | 大小 | 月 | 日| 年/时间 | 名称

文件类型:(-l显示结果中的第一部分的第一列)

连接数:如果是文件,表示这个文件有多少个名字(硬链接);如果是目录,表示这个目录里有多少个子目录。

符号类型
-普通文件。包括纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件等。
d目录文件。
l链接文件。类似于Windows里的快捷方式。
c字符设备文件。即串行端口的接口设备,例如键盘、鼠标等等。
b块设备文件。就是存储数据以供系统存取的接口设备,简单而言就是硬盘
s套接字文件。这类文件通常用在网络数据连接,最常在 /var/run目录中看到这种文件类型。
p管道文件。它主要的目的是,解决多个程序同时存取一个文件所造成的错误。

- alias:给命令起别名。

```shell alias md=mkdir Copy ```

相当于给mkdir命令起了一个别名,以后使用md即可创建一个文件夹。

```shell alias # 不添加任何参数,表示列出所有的别名 ```

## 常用文件命令

cd ~ -- 自己家(root用户)

ssh - 公网ip -- 进入(60.205.218.255)(Yjz1314520!)

exit -- 退出

pwd --当前所在目录的位置

ll -- 当前用户下得所有文件

ls -- 简介显示有文件

cd / -- 跳转到顶级目录

./ -- 同一级别

../ -- 上一级别

ctrl + l -- 快捷键清楚屏幕

ls -a / # 表示列出根目录下所有的文件及文件夹(隐藏显示)

python3 -- 打开python

python - v -- 查看是否安装python

su 用户名-- 切换用户 (root 转用户)

whereis -- 查看文件路径 (whereis python --python在哪里 )

act -- 查看有什么

su - 用户名 -- 切换用户

ctrl -c -- 查看时直接退出

## 文件和目录的创建删除

命令说明
touch新建文件,可以是多个 # touch i.py b,py
rm删除文件或目录(删除目录时要传递'-r'选项)
cp拷贝文件或目录(拷贝目录是要传递'-r'选项)
mv相关命令移动文件或目录
mkdir命令创建目录,可以是多个
rmdir删除空目录

创建多个 或 删除多个用空格隔开 。

复制 移动 要在末尾添加路径。

选项说明

- -r:删除或拷贝目录时需要添加,表示递归操作。

- -f:表示强制操作,没有提示信息。

- *:表示模糊匹配,如:rm* .py,表示删除所有的py文件。

- -p:创建目录时若需要创建中间目录,可以添加此选项。

```python mkdir -p a/b/c # a文件夹中由b b文件夹中由c (递增去创建) 命令 -rf 文件名 -- 之间删除文件夹(没有任何询问) ```

## 查看文件

命令说明
cat从上到下,显示文件全部内容
tac从下到上,显示文件全部内容
head查看开头指定行数的内容,不指定时默认10行,如:head - 20 filename
tail查看文件末尾指定行数的内容,不指定时默认10行,如:tail - 5 filename
nl功能与cat相同,但是多显示了行号
wc统计显示,内容:行数 单词数 字符数 文件名
more一点一点查看内容
less一点一点查看内容

- more/less使用说明 - 显示一屏就停止 - q退出查看 - enter下翻一行 - 空格下翻一屏 - more查看完毕会自动退出,less不会 - less可以使用上下按钮上下翻看,more不可以 - 经常结合管道使用:ls /etc | more - ctrl -c -- 直接退出

## 用户管理相关命令

### 用户管理

命令说明
whoami查看当前登录的用户名
useradd新建用户,-d指定家目录,-m创建家目录,-s指定shell
userdel删除用户,-r会删除用户家目录
passwd设置指定用户的密码,没有指定用户,是修改当前用户的密码
su -切换用户,一定要加上'-',否则只会切换家目录,但是环境没有切换,不指定用户时默认切换到root用户(记得先给root用户设置密码) (切换直接退出 exit())
sudo以指定用户(root)身份执行命令。
visudo专门用于编辑/etc/sudoers文件的命令,需要将指定用户添加进去才可以使用sudo命令,如:test ALL=(ALL:ALL) ALL;使用sudo update-alternatives --config editor可以修改系统默认编辑器(nano)
groupadd新建用户组
groupdel删除用户组
gpasswd向指定组添加/删除指定的用户,如:gpasswd -a/-d user group
groups查看指定用户的组信息
chsh修改指定用户的shell解析器,如:sudo chsh test -s /usr/sbin/nologin (禁止登陆)
chown修改文件所属用户[及用户组],如: sudo chown test[:test] 1.py,递归操作需要加'-R'选项 用户名:组名 文件路径(可以是就对路径也可以是相对路径) 1.chown -R xiaomi:xiaomi /temp/temp1 (文件夹递修改) 2.sudo chown liuxin:liuxin 理想人生.txt
chgrp修改文件所属用户组,如:sudo chgrp test 1.py

删除用还后 可以用 su - 查看 (用户是否存在) 在把相对应的用户文件夹删除

## vim编辑器

### vim的使用

Vim是类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性(编写,修改文件的作用)

### 安装

``` sudo yum install vim ```

### 使用

vim 有三种工作模式:命令模式,输入模式,编辑模式。

!v : 打开最后使用vim打开的文件

vim filename : 打开/新建一个文件

vim 文件名称.格式(i编辑模式直接填写)

进入以后不做编辑填写退出以后 ,就不会显示在目录当中。

命令模式:按Esc键切换到命令模式

命令/操作说明
ZZ(shift + zz)保存退出
光标定位
vim filename +n打开文件,将光标定位到第n行
vim filename +打开文件,将光标定位到最后一行
gg定位到首行
G定位到尾行
ngg定位到第n行
^/0定位到行首
$定位到行尾
k
j
h
l
ctrl + f下翻一页
ctrl + b上翻一页
ctrl + d下翻半页
ctrl + u上翻半页
内容处理
x向右删除一个字符
nx向右删除n个字符,n表示个数
X向左删除一个字符
nX向左删除n个字符,n表示个数
dd删除光标所在行
ndd删除光标开始的n行
p粘贴剪切板中的内容
yy复制光标所在行
nyy复制光标开始的n行
u撤销
ctrl + r反撤销

编辑模式:在命令模式下,按 : 键进入到编辑模式。

命令说明
:w保存
:q退出
:wq保存退出
:x保存退出
:w!强制保存
:q!强制退出,不保存修改
:e!放弃修改,恢复到修改之前的状态
:w newfile文件另存为
:set nu[mber]显示行号
:set nonu[mber]隐藏行号
:set tabstop=4设置一个tab缩进4个字符
:set mouse=a启用鼠标的点击功能
[:]/内容查找指定内容,n下翻,N上翻
[:]?内容查找指定内容,N下翻,n上翻
:%s/原内容/新内容/[g]所有行内容替换,g表示全局(默认只能替换一行中第一处)
:m,ns/原内容/新内容/[g]m到n行内容替换,g用法同上
光标定位
:n将光标定位到第n行,n表示行号

输入模式:

命令说明
i在光标位置插入
I在第一个非空字符插入
a在光标的下一个字符输入
A在行尾插入
o在光标所在的行下面插入空行
O在光标所在的行上面插入空行
s删除光标所在字符,并进入输入模式
S删除光标所在行,并进入输入模式

## 权限管理

说明:在linux下,所有的文件都涉及权限,分为三组:所有者、所属组、其他

权限:所有文件的权限可以分为:可读(r)、可写(w)、可执行(x),'-'表示没有改权限

原理:ls -l的结果,三位一组,分为三组,刚好对应:所有者、所属组、其他

修改权限:chmod,格式:chmod [身份] [操作] [权限] 文件

选项说明
身份
u所有者(user)
g所属组(group)
o其他(other)
a所有(all)
操作
+添加
-去掉
=设置
权限
r可读
w可写
x可执行

> sudo chmod o+w 1.py,给其他用户添加可写的权限(可以随意更改)

- 本质:使用一组(3位)八进制的数据来表示权限,如:0755,展开如下:

``` 转换为二进制:0755 => 111 101 101 对应三组身份: 所有者 所属组 其他 每一组的权限:都包括 可读、可写、可执行 示例解析:所有者可读可写可执行,所属组可读可执行,其他可读可执行 Copy ```

- 简化操作:sudo chmod 0755 1.py

> 若要进行递归操作,则需要添加'-R'操作

- umask

``` 作用:用来限定新建文件的默认权限,权限与该值相反。 命令:umask [value],查看或设置掩码 分析: 掩码:0002 => 000 000 010 新建目录: 111 111 101 新建文件: 110 110 100 ```

## 压缩解压命令

tar,打包解包工具,后缀名是tar.

```bash # 解压方法与 压缩方法 都是相对应的 () 选项: -c:创建新的打包文件 -x: 解包。 -t: 不解包查看文件。 注意:以上三个选项不能同时使用,因为功能冲突。 -v: 显示详细信息。 -f: 指定操作文件。 -z: 调用gzip/gunzip进行压缩解压操作,后缀名是.tar.gz -j: 调用bzip2/bunzip2进行压缩解压操作,后缀名是.tar.bz2 示例: tar -cvf test.tar test # 将test文件夹打包成test.jar文件,并显示打包信息 tar -cvf 123.tar 1.txt 2.txt 3.txt # 将1.txt,2.txt和3.txt文件打包到123.tar文件 tar -tf 123.tar # 不解包查看123.tar文件里的内容 tar -xvf 123.tar # 解包123.tar文件,并显示详细信息

tar -zcvf 12.tar.gz 1.txt 2.txt # 将1.txt和2.txt压缩并打包成12.tar.gz文件 tar -jcvf 12.tar.bz2 1.txt 2.txt # 将1.txt和2.txt压缩并打包成12.tar.bz2文件

tar -zxvf 12.tar.gz # 解压并解包12.tar.gz文件 tar -jxvf 12.tar.bz2 # 解压并解包12.tar.bz2文件。 ```

注意:tar 只是用来打包和解包的工具,它本身是没有压缩和解压缩的功能。但是,通过添加参数,可以调用gzip或者bzip2进行压缩解压操作。

- tar -z: 使用 gzip方式打包并压缩文件,后缀名为 .tar.gz,可以简写为 .tgz

- tar -j: 使用 bzip2 方式打包并压缩文件,后缀名为 .tar.bzip2,可以简写为 .tbz2 或 .tbz

解压 -z xvf (没有顺序) -c e/ -c 表示复制

## Nginx的安装和配置

Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器。

Nginx可以作为反向代理进行负载均衡的实现。 (分化压力)

\1. 使用wget命令下载Nginx源码,下载地址: http://nginx.org/download/nginx-1.16.0.tar.gz \2. 解压软件压缩包: tar -zxvf nginx-1.16.0.tar.gz \3. 编译前执行配置文件: ./configure - —prefix:用来配置Nginx服务器的安装目录 - 配置出错多数是因为缺少相关的依赖库或者编译器 - 需要安装相关的依赖。sudo yum install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel - 运行 make && make install 命令来编译并安装软件 \4. Nginx介绍 - 进入到/usr/local/nginx/sbin 安装目录,使用 ./nginx 命令启动nginx - html:默认站点目录 - 测试:在浏览器中输入localhost,看到welcome to nginx即表示成功

正向代理 : 客户端的改变

反向代理:为服务端做的 客户端无感 (nginx (的过程为:负载均衡))

## 管理虚拟环境

Python对包和模块的下载、存储以及管理有其自己的一套方法。Python的包一般存在几个地方,使用sys.path可以查看python包和模块的存放路径。

### 安装virtualenv

virtualenv 是一个创建隔绝的Python环境的工具。virtualenv创建一个包含所有必要的可执行文件的文件夹,用来使用Python工程所需的包。

```shell udo pip install virtualenv Copy ```

安装完成以后,可以使用命令快速的创建、激活虚拟环境。

```shell cd my_project # 进入到工程的工作目录 virtualenv test # 创建虚拟环境,并命名为test.此时会在my_project下多出一个test的文件夹 source test/bin/activate # 激活虚拟环境。此时,如果使用pip install安装的插件,都会被安装到当前虚拟环境 pip install flask # 测试安装flask. flask会被安装到当前虚拟环境,而不是全局环境 ```

管理虚拟环境

```shell mkvirtualenv test # 创建并切换到test虚拟环境 deactivate # 离开test虚拟环境 rmvirtualenv test # 删除test虚拟环境 workon demo # 切换到demo虚拟环境 ```

## 服务监听

- 参数:

```shell -a 显示所有socket,包括正在监听的。 -n 以网络IP地址代替名称,显示出网络连接情形。 -o 显示与与网络计时器相关的信息 -t 显示TCP协议的连接情况 -u 显示UDP协议的连接情况 -p 显示建立相关连接的程序名和PID。 Copy ```

- ps

- 作用:查看进程信息 - 使用: - ps -ef - ps aux - 说明:经常在查询进程号的时候结合grep进行过滤

- pstree

- 作用:使用树形结构查看进程信息。

- kill

- 作用:杀死进程

- 示例:kill -9 PID

- 说明:强制杀死指定进程

ps -ef | grep 80 -- 结合使用进行过滤

## 管道

管道的操作符是 " | ",它只能处理经由前面一个指令传出的正确输出信息。

然后传递给下一个命令,作为下一个命令的标准输入。

例如ps -ef|more (后面必须是可视化) (一点一点读取)cd 直接跳出

注意:

- 管道命令只能处理前一个命令的正确输出,不能处理错误输出。 - 管道命令的右边命令,必须要能够接收标准的输入流才行。

有些命令无法接受输入流,需要通过xargs来将输入流转换成为命令行参数。

如:find -name 2.txt | xargs rm -rf

## 重定向

标准输入(stdin)、标准输出(stdout)、标准错误(stderr)

- 在linux中,创建任意进程,系统会自动创建上面三个数据流,其实就是三个文件

- 三个文件的描述符分别是:0、1、2.其中,0默认指向键盘,1和2默认指向终端窗口。

- 重定向就是改变原来默认的表现位置。

- 演示:

``` 输出重定向: ls > 1.txt # 会新建文件,若文件已存在,会清空 ls >> 1.txt # 追加到文件末尾,若文件不存在则创建 错误重定向: ls /xxx 2> 1.txt # 将标准错误重定向到1.txt 同时重定向输出和错误: ls /xxx /home &> 1.txt # 将标准输出和错误同时重定向到1.txt文件 ```

WEB搭建服务器

简单的:

import socket
​
​
def handle_client(client_scoket):
    # '为客户端进行服务'
    # '接受客户端的请求内容消息后进行转码'
    recv_data = client_scoket.recv(1024).decode('utf-8')
    print(recv_data)
    # 通过换行符进行切割:
    request_header_lines = recv_data.splitlines()
    # 打印出来
    for line in request_header_lines:
        print(line)
    # 响应头信息
    response_headers = 'HTTP/1.1 200 OK\r\n'
    # 响应头 编码类型
    response_headers += 'content-type:text/html; charset=utf-8\r\n'
    # 用一个空行 和响应体 分隔开
    response_headers += '\r\n'
    # 相应体 内容
    response_body = 'hello,你好世界'
    response = response_headers + response_body
    client_scoket.send(response.encode('utf-8'))
    client_scoket.close()
​
​
def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('', 7788))
    server_socket.listen(128)
    while True:
        client_socket, client_addr = server_socket.accept()
        handle_client(client_socket)
​
​
if __name__ == '__main__':
    main()

搭建需要的静态页面

import socket
import re
​
​
def handle_client(client_scoket):
    # '为客户端进行服务'
    # '接受客户端的请求内容消息后进行转码'
    recv_data = client_scoket.recv(1024).decode('utf-8', errors='ignore')
    print(recv_data)
    # 通过换行符进行切割:
    request_header_lines = recv_data.splitlines()
    # 打印出来
    for line in request_header_lines:
        print(line)
    # 获取请求行  也就是列表中下表为0的元素
    http_request_line = request_header_lines[0]
    # 提取请求行中的路径
    get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
    print("file name is ===>%s" % get_file_name)
    # 如果没有指定访问哪个页面。例如index.html
    if get_file_name == '/':
        get_file_name = DOCUMENTS_ROOT + "/index.html"
    else:
        get_file_name = DOCUMENTS_ROOT + get_file_name
​
    print("file name is ===2>%s" % get_file_name)  # for test
​
    try:
        f = open(get_file_name, "rb")
    except IOError:
        # 404表示没有这个页面
        response_headers = "HTTP/1.1 404 not found\r\n"
        response_headers += "\r\n"
        response_body = "====sorry ,file not found====".encode('utf-8')
    else:
        # 响应头信息
        response_headers = 'HTTP/1.1 200 OK\r\n'
        # 用一个空行 和响应体 分隔开
        response_headers += '\r\n'
        # 相应体 内容
        response_body = f.read()
        f.close()
    finally:
        # 因为头信息在组织的时候,是按照字符串组织的,不能与以二进制打开文件读取的数据合并,因此分开发送
        # 先发送response的头信息
        client_scoket.send(response_headers.encode('utf-8'))
        # 在发生响应体
        client_scoket.send(response_body)
        client_scoket.close()
​
​
def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当服务器先close 即服务器端4次挥手之后资源能够立即释放,这样就保证了,下次运行程序时 可以立即绑定7788端口
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('', 7788))
    server_socket.listen(128)
    while True:
        client_socket, client_addr = server_socket.accept()
        handle_client(client_socket)
​
​
#  静态资源的目录
DOCUMENTS_ROOT = './blog_ye'
if __name__ == '__main__':
    main()

多进程WEB服务器

import socket
import re
import multiprocessing
​
class WSGIServer(object):
    def __init__(self,server_address):
        # 创建一个tcp套接字
        self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 允许立即使用上次绑定的port
        self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 绑定
        self.listen_socket.bind(server_address)
        # 变为被动,并制定队列的长度
        self.listen_socket.listen(128)
​
    def serve_forever(self):
        "循环运行web服务器,等待客户端的链接并为客户端服务"
        while True:
            # 等待新客户端到来
            client_socket, client_address = self.listen_socket.accept()
            print(client_address)  # for test
            new_process = multiprocessing.Process(target=self.handleRequest, args=(client_socket,))
            new_process.start()
​
            # 因为子进程已经复制了父进程的套接字等资源,所以父进程调用close不会将他们对应的这个链接关闭的
            client_socket.close()
​
    def handleRequest(self, client_socket):
        "用一个新的进程,为一个客户端进行服务"
        recv_data = client_socket.recv(1024).decode('utf-8')
        print(recv_data)
        requestHeaderLines = recv_data.splitlines()
        for line in requestHeaderLines:
            print(line)
​
        request_line = requestHeaderLines[0]
        get_file_name = re.match("[^/]+(/[^ ]*)", request_line).group(1)
        print("file name is ===>%s" % get_file_name)
​
        if get_file_name == "/":
            get_file_name = DOCUMENTS_ROOT + "/index.html"
        else:
            get_file_name = DOCUMENTS_ROOT + get_file_name
​
        print('打开的是{}'.format(get_file_name).encode('utf-8'))
​
        try:
            f = open(get_file_name, "rb")
        except IOError:
            response_header = "HTTP/1.1 404 not found\r\n"
            response_header += "\r\n"
            response_body = "====sorry ,file not found===="
        else:
            response_header = "HTTP/1.1 200 OK\r\n"
            response_header += "\r\n"
            response_body = f.read()
            f.close()
        finally:
            client_socket.send(response_header.encode('utf-8'))
            client_socket.send(response_body)
            client_socket.close()
​
def main():
    httpd=WSGIServer(('',7788))
    print('端口号:{}'.format(7788))
    httpd.serve_forever()
if __name__ == '__main__':
    main()

分割服务器和逻辑功能代码用WSGI

WSGI允许开发者将选择web框架和web服务器分开。可以混合匹配web服务器和web框架,选择一个适合的配对

web服务器必须具备WSGI接口,所有的现代Python Web框架都已具备WSGI接口,它让你不对代码作修改就能使服务器和特点的web框架协同工作

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有HTTP请求信息的dict对象;

  • start_response:一个发送HTTP响应的函数

浏览器请求页面过程:

浏览器和web之间遵守的是HTTP协议

web和框架之间遵守wsgi协议

WEB服务器接收请求返回响应

1.浏览器向web服务器发送请求

2.web服务器接收到请求后设置一个响应头(response_headers)给web框架

3.web框架通过调用response_headers得到响应头信息返回给web服务器

4.web服务器保存信息后在返回给框架

5.框架查询数据库得到响应体body返回给web服务器

6.web服务器得到响应体后在发送给浏览器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值