Linux命令

  • 安装
  • 安装ubuntu20.04
1
2
3
4
1.下载:http://mirrors.163.com/ubuntu-releases/20.04/
2.简易安装即可
主机名:ubuntu
用户名/密码: xxxx/xxxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# ========== 查看目录 ===========
ls :查看当前目录信息
    -l    以列表方式显示(简写 : ll)
    -h    件大小单位显示,默认是字节
    -a    显示隐藏文件和隐藏目录
tree : 以树状方式显示目录信息

# ========== 查看当前目录路径 ==========
pwd : 查看当前目录路径

# ========== 清除终端内容 ==========
clear : 清除终端内容

# ========== 切换目录命令 ==========
cd 目录 : 切换到指定目录
cd ~ / cd : 切换到当前用户的主目录
cd .. : 切换到上一级目录
cd . : 切换到当前目录
cd - : 切换到上一次目录

# ========== 绝对路径(从根目录/算起) ==========
# ========== 相对路径(从当前目录./算起的路径) ==========

# ========== 创建、删除文件及目录命令的使用 ==========
touch 文件名 : 创建指定文件
mkdir 目录名 : 创建目录(文件夹) 
    -p    创建所依赖的文件夹
rm 文件名或者目录名 : 删除指定文件或者目录 
    -i    交互式提示
    -r    递归删除目录及其内容
    -f    强制删除,忽略不存在的文件,无需提示
    -d    删除空目录

rmdir 目录名 : 删除空目录

# ========== 复制、移动文件及目录命令的使用 ==========
cp : 拷贝文件、拷贝目录
    -i    交互式提示
    -r    递归拷贝目录及其内容
    -v    显示拷贝后的路径描述
    -a    保留文件的原有权限
mv : 移动文件、移动目录、重命名

# ========== 查看命令帮助方式 ==========
--help 使用说明: 命令 --help
man 使用说明: man 命令
    空格 显示下一屏信息
    回车 显示下一行信息
    b    显示上一屏信息
    f    显示下一屏信息
    q    退出

# ========== 重定向命令(将终端显示内容重定向到文件) ==========
>  : 如果文件存在会覆盖原有文件内容,相当于文件操作中的‘w’模式
>> : 如果文件存在会追加写入文件末尾,相当于文件操作中的‘a’ 模式

# ========== 查看文件内容命令 ==========
cat : 查看小型文件
more : 分屏查看大型文件
    cat命令结合重定向可以完成多个文件的合并
    gedit 文件编辑命令,可以查看和编辑文件
管道(|): 容器,存放在终端显示的内容。(只要可以再终端显示的都可以使用管道)
    管道(|)一般结合 more 命令使用,主要是分配查看终端显示内容。
    ls -ih | more

# ========== 链接命令 ==========
ln -s : 创建软链接(天空蓝,相当于windows下的快捷方式。无效/失效的为红色)
    ln -s 要创建的文件/目录的绝对路径 软链接的名字
    可以rm删除链接
ln : 创建硬链接(类似于源文件的一个别名,也就是说这两个名字指向的是同一个文件数据。类似与内存地址的概念)  
* 创建硬链接使用相对路径和绝对路径都可以
* 删除源文件,硬链接还可以访问到数据。
* 创建硬链接,硬链接数会加1,删除源文件或者硬链接,硬链接数会减1。(硬链接数就是文件数据被文件名使用的次数, 好比引用计数)
* 创建软链接,硬链接数不会加1
* 不能给目录创建硬链接

# ========== 文本搜索命令 ==========
grep : 文本搜索
    -i    忽略大小写
    -n    显示匹配行号
    -v    显示不包含匹配文本的所有行
grep 'abc' test.txt (grep可以省略搜索内容的引号)
    ^    以指定字符串开头
    $    以指定字符串结尾
    .    匹配一个非换行符的字符
grep可以结合管道使用

# ========== 查找文件命令 ==========
find : 在指定目录下查找文件(包括目录)
    -name : 根据文件名(包括目录名)字查找
    模糊搜索
    *    代表0个或多个任意字符
    ?    代表任意一个字符
通配符不仅能结合 find 命令使用,还可以结合其它命令使用, 比如: ls、mv、cp 等,
这里需要注意只有 find 命令使用通配符需要加上引号。
find ./ -name index.html

# ========== 压缩和解压缩命令(节省磁盘空间) ==========
.gz和.bz2的压缩包需要使用tar命令来压缩和解压缩
.zip的压缩包需要使用zip命令来压缩,使用unzip命令来解压缩
tar : 压缩和解压缩命令
    -c    创建打包文件
    -v    显示打包或者解包的详细信息
    -f    指定文件名称, 必须放到所有选项后面
    -z    压缩或解压缩(.gz)
    -j    压缩或解压缩(.bz2)
    -x    解包
    -C    解压缩到指定目录
    压缩文件:tar -zcvf test.tar.gz *.txt
    解压文件: tar -zxvf test.tar.gz -C .
zip : 压缩成.zip格式文件
unzip : 解压缩.zip格式文件
    -d    解压缩到指定目录
* 压缩文件尽量使用.gz格式,因为占用空间较少
* 使用zip命令压缩的文件占用空间比较多, 当时比较通用,操作更加简单。

# ========== 文件权限命令 ==========
chmod : 修改文件权限
    u    user, 表示该文件的所有者
    g    group, 表示用户组
    o    other, 表示其他用户
    a    all, 表示所有用户

    +    增加权限
    -    撤销权限
    =    设置权限

    r    可读 权限值是4
    w    可写 权限值是2
    x    可执行 权限值是1
    -    无任何权限 权限值是0
    添加权限 :chmod 776 ./test.txt

# ========== 获取管理员权限的相关命令 ==========
切换到管理员root用户: sudo -s  + 输入密码
临时获取管理员root权限:sudo + 具体的命令  (输入一次密码,可以保留2分钟)
    如果只是某次操作需要使用管理员权限建议使用 sudo , 也就是说临时使用管理器权限。
    如果大量操作都需要使用管理员权限 sudo –s, 但是操作需谨慎。
exit :退出root用户
查看当前用户:whoami
who : 查看所有的登录用户
passwd : 修改用户密码,不指定用户默认修改当前登录用户密码
which : 查看命令位置
    查看python安装路径 :which python3
    #!/usr/bin/python3  => 可以直接./python_dmeo.py,否则就要 python3 python_dmeo.py执行了
    #号的含义:
        # 注释
        #!/python解释器的路径 表示系统直接执行文件选择的解释器
        #_*_coding:utf-8_*_表示指定文件比那吗格式
shutdown –h now : 立刻关机
reboot : 重启

# ========== 用户相关操作 ==========
useradd : 创建(添加)用户
    -m    自动创建用户主目录,主目录的名字就是用户名
    -g    指定用户所属的用户组,默认不指定会自动创建一个同名的用户组
* useradd 命令的使用需要使用管理员权限,前面需要加上 sudo
* 创建用户如果不指定用户组,默认会自动创建一个同名的用户组
* 查看用户是否创建成功,可以查看/etc/passwd这个文件
    passwd文件中的每项信息说明,以root:x:0:0:root:/root:/bin/bash为例:
        * 第一个:用户名
        * 第二个:密码占位符
        * 第三个:uid, 用户id
        * 第四个:gid, 用户所在组id
        * 第五个:用户描述, 可选,
        * 第六个:用户的主目录所在位置
        * 第七个:用户所用 shell 的类型,一般由bash或者sh,默认不设置是sh类型
* 查看用户组是否创建成功,可以查看/etc/group这个文件
    group文件中的每项信息说明, 以laowang:x:1001:为例:
        * 第一个:用户组名
        * 第二个:用户组密码占位符,一般Linux系统的用户组都没有密码的
        * 第三个:组id
id : 查看用户信息
    uid=1001(laowang) gid=1001(laowang) 组=1001(laowang)
        * 第一个: uid 表示用户id
        * 第二个: gid 表示用户组id
        * 第三个: 组 表示用户所在的用户组
给其它用户设置密码,需要使用: sudo passwd 用户名
su : 切换用户
    新添加的用户,默认没有sudo权限。给laowang用户设置一个sudo附加组, 需要使用usermod修改用户信息
usermod :修改用户信息
    -G    设置一个附加组
    -g    修改用户组
    设置附加组 :sudo usermod -G sudo laowang
gpasswd : 添加和删除附加组信息
    -a 用户名 给用户添加附加组
    -d 用户名 给用户删除附加组
    sudo gpasswd -d laowang sudo
userdel : 删除用户 (删除用户,默认同名的用户组也会被删除)
    -r 用户名 :删除用户主目录,必须要设置,否则用户主目录不会删除

# ========== 用户组相关操作 ==========
groupadd : 创建(添加)用户组
groupdel : 删除用户组 (组下有用户需要先删除用户)
* 创建用户组使用: sudo groupadd 用户组名
* 创建用户并指定用户组使用: sudo useradd -m -g 用户组 用户名
* 修改用户组使用: sudo usermod -g 用户组 用户名
* 删除用户组使用: sudo groupdel 用户组名

# ========== 远程登录、远程拷贝命令 ==========
ssh :远程登录
    1. 假如Ubuntu作为服务端,需要安装ssh服务端软件. 执行命令: sudo apt-get install openssh-server
        查找是否安装ssh: apt list | grep openssh-server
    2. 客户端电脑如果是 macOS 系统则不需要安装 ssh 客户端软件,默认已经安装过了,直接可以使用 ssh 命令
    3. 客户端电脑如果是Windows系统则需要安装OpenSSH for Windows这个软件
        * 在一台电脑上可以安装安装ssh客户端和ssh服务端软件
        * 在Ubuntu安装ssh客户端命令: sudo apt-get install openssh-client
    ssh 用户名@ip地址
scp :远程拷贝 (基于ssh进行远程拷贝,可以把我们写代码远程拷贝到服务器)
* 远程拷贝文件
    * scp 本地文件 远程服务器用户名@远程服务器ip地址:指定拷贝到远程服务器的路径
    * scp 远程服务器用户名@远程服务器ip地址:远程服务器文件 指定拷贝到本地电脑的路径
* 远程拷贝目标(文件夹)
    * scp -r 本地目录 远程服务器用户名@远程服务器ip地址:指定拷贝到远程服务器的路径
    * scp -r 远程服务器用户名@远程服务器ip地址:远程服务器目录 指定拷贝到本地电脑的路径
    * -r 表示递归拷贝整个目录
如果更多文件上传下载还是要用工具,xshell,xftp,mobaxterm等

# ========== 编辑器 vim ==========
:w 保存
:wq 保存退出
:x 保存退出
:q! 强制退出

yy    复制光标所在行
p    粘贴
dd    删除/剪切当前行
V    按行选中
u    撤销
ctr+r    反撤销
>>    往右缩进
<<    往左缩进
:/搜索的内容    搜索指定内容
:%s/要替换的内容/替换后的内容/g    全局替换
:开始行数,结束行数s/要替换的内容/替换后的内容    局部替换
.    重复上一次命令操作
G    回到最后一行
gg    回到第一行
数字+G    回到指定行
shift+6    回到当前行的行首
shift+4    回到当前行的行末
ctr+f    下一屏
ctr+b    上一屏

V+G 全选

# ========== 软件安装 ==========
* 离线安装(deb文件格式安装)
* 在线安装(apt-get方式安装)
dpkg : 安装和卸载deb安装包
    -i    离线安装deb安装包
sudo apt–get install 安装包 , 表示在线安装deb安装包
更换源
    1. 可视化方式更改镜像源(软件和更新中设置)
    2. 手动方式更改镜像源
        sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
        sudo gedit /etc/apt/sources.list
        百度镜像源 输入 mirrors.tuna.tsinghua.edu.cn/help/ubuntu/ 页面选择的deb *** 镜像命令
        1. 手动修改镜像源,配置完成以后需要执行 sudo apt-get update 这个命令,更新镜像源保证可以下载最新的软件。
        2. 使用apt-get方式安装软件一定要联网

# ========== 软件卸载 ==========
* 离线安装包的卸载(deb 文件格式卸载)
* 在线安装包的卸载(apt-get 方式卸载)
sudo dpkg –r 安装包名
    -r 选项表示安装的卸载
sudo apt-get remove 安装包名

# ========== 其他命令 ==========
查看IP:ip addr show

多任务编程

12_多任务

多任务

为什么用多任务

1
2
3
4
利用现学知识能够让两个函数或者方法同时执行吗?

不能,因为之前所写的程序都是单任务的,也就是说一个函数或者方法执行完成另外一个函数或者方法才能执行,要想实现这种操作就需要使用多任务。
多任务的最大好处是充分利用CPU资源,提高程序的执行效率。

多任务是什么

1
2
3
4
5
多任务是指在同一时间内执行多个任务,例如: 现在电脑安装的操作系统都是多任务操作系统,可以同时运行着多个软件。
多任务执行方式:
- 并发:在一段时间内交替去执行任务。
    对于单核cpu处理多任务,操作系统轮流让各个软件交替执行,假如:软件1执行0.01秒,切换到软件2,软件2执行0.01秒,再切换到软件3,执行0.01秒……这样反复执行下去。表面上看,每个软件都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像这些软件都在同时执行一样,这里需要注意单核cpu是并发的执行多任务的。
- 并行:对于多核cpu处理多任务,操作系统会给cpu的每个内核安排一个执行的软件,多个内核是真正的一起执行软件。这里需要注意多核cpu是并行的执行多任务,始终有多个软件一起执行。

进程

为什么用进程

1
在Python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式。

进程是什么

1
2
3
4
5
6
    一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行

注意:
    一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。

进程之间执行是无序的(具体哪个进程执行是有操作系统调度决定的)

多进程怎么用

1
2
3
4
5
6
7
8
9
1. 导入进程包
    * import multiprocessing
2. 创建子进程并指定执行的任务
    * sub_process = multiprocessing.Process (target=任务名)
3. 启动进程执行任务
    * sub_process.start()

# 当前进程(主进程)等待添加数据的子进程执行完成以后程序再继续往下执行,比如:读取数据
    add_data_process.join()
  • Process进程类的说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Process([group [, target [, name [, args [, kwargs]]]]])
- group:指定进程组,目前只能使用None
- target:执行的目标任务名(指的是一个函数/方法)
- name:进程名字(一般不设置,默认Process-N)
- args:以元组方式给执行任务传参(元组方式传参(args): 元组方式传参一定要和参数的顺序保持一致。)
- kwargs:以字典方式给执行任务传参(字典方式传参(kwargs): 字典方式传参字典中的key一定要和参数名保持一致。)

Process创建的实例对象的常用方法:
- start():启动子进程实例(创建子进程)
- join():等待子进程执行结束
- terminate():不管任务是否完成,立即终止子进程
Process创建的实例对象的常用属性:
- name:当前进程的别名,默认为Process-N,N为从1开始递增的整数

# 获取当前进程的编号
    print("dance:", os.getpid())
# 获取当前进程
    print("dance:", multiprocessing.current_process())
# 获取父进程的编号
    print("dance的父进程编号:", os.getppid())
# 扩展:根据进程编号杀死指定进程
    os.kill(os.getpid(), 9)
  • 多任务的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import multiprocessing
import time

# 跳舞任务def dance():
    for i in range(5):
        print("跳舞中...")
        time.sleep(0.2)

# 唱歌任务def sing():
    for i in range(5):
        print("唱歌中...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 创建跳舞的子进程
    # group: 表示进程组,目前只能使用None
    # target: 表示执行的目标任务名(函数名、方法名)
    # name: 进程名称, 默认是Process-1, .....
    dance_process = multiprocessing.Process(target=dance, name="myprocess1")
    sing_process = multiprocessing.Process(target=sing)

    # 启动子进程执行对应的任务
    dance_process.start()
    sing_process.start()

image-20230927182211584

进程注意点

1
2
3
注意点:
1. 进程之间不共享全局变量
2. 主进程会等待所有的子进程执行结束再结束

image-20230927182217190

image-20230927182222417

1
2
3
4
5
6
7
8
9
10
11
    创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,好比是一对双胞胎,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。(好比QQ里面的全局变量A和陌陌里的全局变量A是不同的这种概念)

主进程会等待所有的子进程执行结束再结束
    假如我们现在创建一个子进程,这个子进程执行完大概需要2秒钟,现在让主进程执行0.5秒钟就退出程序,但是主进程并不会结束,而是等子进程执行玩再退出。(这样如果子进程是个死循环,那你主进程就一直无法退出了)
    如果想要主进程介绍,子进程也结束:
        - 我们可以设置守护主进程(主进程退出子进程销毁不再执行)
            # 设置子进程为守护主进程,主进程退出子进程直接销毁,子进程的生命周期依赖与主进程
            sub_process.daemon = True 
        - 或者 在主进程退出之前 让子进程销毁(子进程执行结束)
            # 让子进程销毁
            sub_process.terminate()

线程

为什么用线程

1
在Python中,想要实现多任务除了使用进程,还可以使用线程来完成,线程是实现多任务的另外一种方式。

线程是什么

1
2
    线程是进程中执行代码的一个分支,每个执行分支(线程)要想工作执行代码需要cpu进行调度 ,也就是说线程是cpu调度的基本单位,每个进程至少都有一个线程,而这个线程就是我们通常说的主线程。
    多个线程可以在一个进程里,一个进程里的全局变量可以共享

怎么用线程

线程类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Thread([group [, target [, name [, args [, kwargs]]]]])
- group: 线程组,目前只能使用None
- target: 执行的目标任务名
- args: 以元组的方式给执行任务传参
- kwargs: 以字典方式给执行任务传参
- name: 线程名,一般不用设置

注意点:
1. 线程之间执行是无序的(具体哪个线程执行是有CPU调度决定的)
2. 主线程会等待所有的子线程执行结束再结束
3. 线程之间共享全局变量(因为多线程在同一个进程内)(好处)
4. 线程之间共享全局变量数据出现错误问题(坏处)

# 主线程等待写入线程执行完成以后代码在继续往下执行
  write_thread.join() (否则你要计算上一个线程大概执行多久,然后将下个线程睡眠多久后执行。这样有点傻)

image-20230927182230090

守护线程

1
2
3
4
和进程一样,如果想要主线程停止,子线程也停止。可以设置守护主线程。
有两种方式:
1. 创建子线程的时候:threading.Thread(target=show_info, daemon=True)
2. 子线程对象.setDaemon(True)

线程共享变量

1
2
3
4
5
6
多线程操作同一个全局变量时会出现问题
    两个线程first_thread和second_thread都要对全局变量g_num(默认是0)进行加1运算,但是由于是多线程同时操作,有可能出现下面情况:
1. 在g_num=0时,first_thread取得g_num=0。此时系统把first_thread调度为”sleeping”状态,把second_thread转换为”running”状态,t2也获得g_num=0
2. 然后second_thread对得到的值进行加1并赋给g_num,使得g_num=1
3. 然后系统又把second_thread调度为”sleeping”,把first_thread转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
4. 这样导致虽然first_thread和first_thread都对g_num加1,但结果仍然是g_num=1

image-20230927182235746

  • 解决全局数据变量错误方法
1
2
3
4
线程同步: 保证同一时刻只能有一个线程去操作全局变量 同步: 就是协同步调,按预定的先后次序进行运行。如:你说完,我再说, 好比现实生活中的对讲机
线程同步的方式:
1. 线程等待(join)(等一个线程执行完再执行下个线程(单任务),有顺序,效率低)
2. 互斥锁:多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其它等待的线程再去抢这个锁。

互斥锁使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建锁
mutex = threading.Lock()
# 上锁
mutex.acquire()
...这里编写代码能保证同一时刻只能有一个线程去操作, 对共享数据进行锁定...
# 释放锁
mutex.release()

注意点:
* acquire和release方法之间的代码同一时刻只能有一个线程去操作
* 如果在调用acquire方法的时候 其他线程已经使用了这个互斥锁,那么此时acquire方法会堵塞,直到这个互斥锁释放后才能再次上锁。
   
# 提示:加上互斥锁,那个线程抢到这个锁我们决定不了,那线程抢到锁那个线程先执行,没有抢到的线程需要等待
# 加上互斥锁多任务瞬间变成单任务,性能会下降,也就是说同一时刻只能有一个线程去执行

如果不想数据出现问题,而且是多个线程操作同一个变量。这时候可以用互斥锁。

互斥锁如果用不好可能会出现死锁问题!!!

死锁

1
2
会造成应用程序的停止响应,不能再处理其它任务了。
为了避免出现死锁,要在合适的地方释放互斥锁。

image-20230927182243325

总结下进程和线程

image-20230927182248084

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1. 进程之间不共享全局变量
2. 线程之间共享全局变量,但是要注意资源竞争的问题,解决办法: 互斥锁或者线程同步
3. 创建进程的资源开销要比创建线程的资源开销要大
4. 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
5. 线程不能够独立执行,必须依存在进程中
6. 多进程开发比单进程多线程开发稳定性要强
* 进程优缺点:
    * 优点:可以用多核 (和计算密集型相关操作可以用多进程)
    * 缺点:资源开销大
* 线程优缺点:
    * 优点:资源开销小 (文件写入/下载,io操作可以用多线程)
    * 缺点:不能使用多核
* 进程和线程都是完成多任务的一种方式
* 多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
* 多进程可以使用cpu的多核运行,多线程可以共享全局变量。
* 线程不能单独执行必须依附在进程里面