AcWing-Linux基础课

命令帮助

终端输入下面其中一个命令,可以查看该命令的使用帮助

  • 命令 --help
  • man 命令

文件系统

文件系统结构

  • /(根目录)
    • bin(存储常用的可执行文件、命令)
    • etc(一般用于存储配置文件)
    • var(一般用于存储日志文件)
    • lib(一般用于存储安装包、静态链接库)
    • home(一般用于存储用户的家目录,一个Linux系统可以有多个用户,不同用户对应不同的家目录)
    • proc(一般用于存储Linux系统的一些配置文件,可以看到Linux系统的信息)

路径

  • 绝对路径:开头是 /

  • 相对路径:开头不是 /

  • .:当前目录

  • …:上级目录

  • ~/:家目录

acs@80826ae841a9:~/temp$ pwd
/home/acs/temp
acs@80826ae841a9:~/temp$ cd .. # 回到上级目录
acs@80826ae841a9:~$ pwd
/home/acs
acs@80826ae841a9:~$ cd . # 回到当前目录
acs@80826ae841a9:~$ pwd
/home/acs
acs@80826ae841a9:~$
acs@80826ae841a9:/$ pwd
/
acs@80826ae841a9:/$ cd ~/ # 回到家目录
acs@80826ae841a9:~$ pwd
/home/acs
acs@80826ae841a9:~$ 

常用文件管理命令

  • 键盘按下CTRL + c:结束正在运行的程序,取消正在输入的本行命令,并且换行

  • 键盘按下CTRL + u:清空正在输入的本行且在光标之前的命令

  • 键盘按下TAB:可以补全命令或文件名,如果补全不了可以快速按两下TAB键,则可以显示备选选项

  • 键盘按下方向键 ↑ :可以自动输入上一次执行的命令

  • history:显示使用过的历史指令

  • ls:列出当前目录下所有文件,蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件(在ACWing的终端中)

    • ls -l:展示详细信息
    • ls -hl:以人性化展示详细信息
    • ls -a:能够展示所有文件,包括隐藏文件(所有隐藏文件的文件名以.开头)
  • pwd:显示当前路径

  • cd:切换目录

  • cd -:返回上一次所在的目录

  • cp:复制粘贴文件、复制粘贴目录

    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    a  b
    acs@80826ae841a9:~$ cp a/tmp.txt b # 把a目录下的tmp.txt文件复制粘贴到b目录下
    acs@80826ae841a9:~$ 
    
    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    a  b
    acs@80826ae841a9:~$ cp a/tmp.txt b/tmp2.txt # 把a目录下的tmp.txt文件复制粘贴到b目录下并且重命名为tmp2.txt
    acs@80826ae841a9:~$ 
    
    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    a  b
    acs@80826ae841a9:~$ cp a b -r # 把整个a目录复制粘贴到b目录下
    acs@80826ae841a9:~$ ls
    a  b
    acs@80826ae841a9:~$ cd b
    acs@80826ae841a9:~/b$ ls
    a  tmp2.txt
    acs@80826ae841a9:~/b$ 
    
    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
     a   b  'te p'  'y c'
    acs@80826ae841a9:~$ cp a c -r # 把整个a目录复制粘贴到当前目录下,并且重命名为c
    acs@80826ae841a9:~$ ls
     a   b   c  'te p'  'y c'
    acs@80826ae841a9:~$ 
    
  • touch:创建文件

    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
     a   b  'y c'
    acs@80826ae841a9:~$ touch te\ p # 创建文件,文件名有空格的使用转义字符\
    acs@80826ae841a9:~$ ls
     a   b  'te p'  'y c'
    acs@80826ae841a9:~$  
    
  • mkdir:创建目录

    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    a  b
    acs@80826ae841a9:~$ mkdir y\ c # 创建目录,目录名有空格的使用转义字符\
    acs@80826ae841a9:~$ ls
     a   b  'y c'
    acs@80826ae841a9:~$ 
    
    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    acs@80826ae841a9:~$ mkdir a/b/c -p # 在当前目录下创建a目录,在a目录下创建b目录,在b目录下创建c目录
    acs@80826ae841a9:~$ ls
    a
    acs@80826ae841a9:~$ ls a/
    b
    acs@80826ae841a9:~$ ls a/b/
    c
    acs@80826ae841a9:~$ 
    
  • rm:删除文件、删除目录

    acs@80826ae841a9:~/a/b$ pwd
    /home/acs/a/b
    acs@80826ae841a9:~/a/b$ ls
    c  tmp.txt  tmp2.txt
    acs@80826ae841a9:~/a/b$ rm tmp.txt tmp2.txt # 删除tmp.txt和tmp2.txt文件
    acs@80826ae841a9:~/a/b$ ls
    c
    acs@80826ae841a9:~/a/b$ rm c -r # 删除一整个c目录
    acs@80826ae841a9:~/a/b$ ls
    
    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls 
    a
    acs@80826ae841a9:~$ find a
    a
    a/t1.txt
    a/t2.txt
    a/b
    acs@80826ae841a9:~$ rm a/* -r # 删除a目录下的所有东西
    acs@80826ae841a9:~$ cd a 
    acs@80826ae841a9:~/a$ ls
    acs@80826ae841a9:~/a$ 
    
  • mv:剪切粘贴文件、剪切粘贴目录。用法和cp一模一样,只不过mv是剪切粘贴,cp是复制粘贴

    acs@80826ae841a9:~/a$ pwd
    /home/acs/a
    acs@80826ae841a9:~/a$ ls
    t1.txt
    acs@80826ae841a9:~/a$ mv t1.txt t2.txt # 可以实现重命名
    acs@80826ae841a9:~/a$ ls
    t2.txt
    acs@80826ae841a9:~/a$ 
    
  • cat:展示文件中的内容

  • 键盘按下CTRL + INSERT:复制文本

  • 键盘按下SHIFT + INSERT:粘贴文本

在终端上复制超过窗口大小展示的内容的方法

  • 先用cat命令把文件中的内容展示到终端上
  • 然后用鼠标左键选中内容的开头
  • 然后用鼠标滚轮往下翻,找到内容的结尾
  • 然后键盘按住SHIFT键,接着用鼠标左键选中内容的结尾
  • 然后键盘按下CTRL + INSERT进行文本的复制即可!!!

知识点补充

  • ag命令,可以进行全文搜索

    acs@80826ae841a9:~/homework/lesson_3/homework_4$ pwd
    /home/acs/homework/lesson_3/homework_4
    acs@80826ae841a9:~/homework/lesson_3/homework_4$ ls
    main.sh
    acs@80826ae841a9:~/homework/lesson_3/homework_4$ ag sum main.sh # 全文搜索sum出现的位置
    5:sum=0
    9:    sum=$(expr ${sum} + $(expr ${i} \* ${i}))
    12:echo ${sum} > ${2}
    acs@80826ae841a9:~/homework/lesson_3/homework_4$ 
    
  • tree命令,可以展示当前路径下的目录文件结构

    acs@80826ae841a9:~/homework/lesson_3$ pwd
    /home/acs/homework/lesson_3
    acs@80826ae841a9:~/homework/lesson_3$ ls
    homework_0  homework_1  homework_2  homework_3  homework_4
    acs@80826ae841a9:~/homework/lesson_3$ tree . # 展示当前路径下的目录文件结构
    .
    |-- homework_0
    |   `-- helper.sh
    |-- homework_1
    |   `-- check_file.sh
    |-- homework_2
    |   `-- main.sh
    |-- homework_3
    |   `-- main.sh
    `-- homework_4
        `-- main.sh
    
    5 directories, 5 files
    acs@80826ae841a9:~/homework/lesson_3$ 
    

tmux

tmux的两个重要作用

  • 可以分屏操作,每个屏幕都是一个Terminal(终端),操作同一个服务器
  • 允许断开Terminal(终端)连接后,继续运行进程(可以保证在突然断电的情况下,进程继续运行或正在写的文档内容不消失)

tmux的结构(一个tmux可以包含多个session,一个session可以包含多个window,一个window可以包含多个pane):

  • session
    • window
      • pane

常用操作:

  • tmux:新建一个session,其中包含一个window,window中包含一个pane,pane里打开了一个shell对话框

  • 键盘按下CTRL + a后,手指松开,然后按%:将当前pane左右平分成两个pane

  • 键盘按下CTRL + a后,手指松开,然后按":将当前pane上下平分成两个pane

  • 键盘按下CTRL + d:关闭当前pane;如果当前window的所有pane均已关闭,则自动关闭window;如果当前session的所有window均已关闭,则自动关闭session

  • 鼠标点击可以直接选pane

  • 键盘按下CTRL + a后手指松开,然后按方向键:选择相邻的pane

  • 鼠标拖动pane之间的分割线,可以调整分割线的位置

  • 键盘按住CTRL + a的同时按方向键,可以调整pane之间分割线的位置

  • 键盘按下CTRL + a后手指松开,然后按z:将当前pane全屏或者取消全屏

  • 键盘按下CTRL + a后手指松开,然后按d:挂起当前session(即退出tmux,但是不关闭窗口)

  • tmux a:打开之前挂起的session

  • 键盘按下CTRL + a后手指松开,然后按s,然后按方向键

    • 上:选择上一项 session/window/pane
    • 下:选择下一项 session/window/pane
    • 右:展开当前项 session/window
    • 左:闭合当前项 session/window
  • 键盘按下CTRL + a后手指松开,然后按c:在当前session中创建一个新的window**(不常用)**

  • 键盘按下CTRL + a后手指松开,然后按w,然后按方向键。操作跟上面那个类似,区别是这里会默认打开window这一级

  • 鼠标滚轮:翻阅当前pane内的内容

  • 键盘按下CTRL + a后手指松开,然后按PageUp或PageDown:翻阅当前pane内的内容

  • 在tmux中要选中文本时,需要按住shift键,然后可以进行复制粘贴

  • 在tmux中复制粘贴文本的通用方式:

    • 键盘按下CTRL + a后松开手指,然后按[
    • 用鼠标选中文本,被选中的文本会被自动复制到tmux的剪贴板
    • 键盘按下CTRL + a后松开手指,然后按],会将tmux的剪贴板中的内容粘贴到光标处

vim

vim:命令行模式下的文本编辑器

vim可以根据文件扩展名自动判别编程语言,支持代码缩进、代码高亮等功能

使用vim

  • vim (filename):
    • 如果已有该文件,则打开它
    • 如果没有该文件,则打开个一个新的文件,并命名为filename

vim的三种模式

  • 一般命令模式(默认)
    • 键盘按下不同的健,即可进行不同操作,可以复制、粘贴、删除文本等等
    • 在一般命令模式里键盘按下i或a或o这三个字符中的任意一个,则会进入编辑模式
    • 在一般命令模式里键盘按下:或/或?这三个字符中的任意一个,则会进入命令行模式
  • 编辑模式
    • 键盘按下ESC,会退出编辑模式,返回到一般命令模式
  • 命令行模式
    • 可以查找、替换、保存、退出、配置编辑器等等

vim的常用操作:

  • 键盘按下h 或 左箭头键:光标向左移动一个字符,不允许换行
  • 键盘按下j 或 向下箭头:光标向下移动一个字符
  • 键盘按下k 或 向上箭头:光标向上移动一个字符
  • 键盘按下l 或 向右箭头:光标向右移动一个字符,不允许换行
  • 键盘按下n(n为数字),然后再按下空格键:光标会向右移动n个字符,允许换行
  • 键盘按下0 或 Home:光标移动到本行开头
  • 键盘按下$ 或 End:光标移动到本行末尾
  • 键盘按下G:光标移动到最后一行
  • 键盘按下:n 或 nG(n为数字):光标移动到第n行
  • 键盘按下gg:光标移动到第一行,相当于键盘按下1G
  • 键盘按下n(n为数字),然后再按下回车:光标向下移动n行
  • 键盘按下/word:从当前光标位置开始,往下寻找第一个值为word的字符串(用于查找字符串)
  • 键盘按下?word:从当前光标位置开始,往上寻找第一个值为word的字符串(用于查找字符串)
  • 键盘按下n:重复前一个查找操作
  • 键盘按下N:反向重复前一个查找操作
  • 键盘按下:n1,n2s/word1/word2/g:n1与n2为数字,在第n1行与n2行之间(包括n1和n2)寻找word1这个字符串,并将该字符串替换为word2(用于替换字符串,注意不要漏掉s,和末位的g)
  • 键盘按下:1,$s/word1/word2/g:将全文的word1替换为word2(用于替换字符串,注意不要漏掉s,和末位的g)
  • 键盘按下:1,$s/word1/word2/gc:将全文的word1替换为word2,且在替换前要求用户确认是否替换(用于替换字符串,注意不要漏掉s,和末位的gc)
  • 键盘按下:noh:关闭查找关键词产生的高亮
  • 键盘按下v后松开,然后按下方向键:可以选中文本,再按一次v可以退出选中状态
  • 键盘按下d:剪切选中的文本,粘贴时是在光标的下一个位置粘贴
  • 键盘按下dd:剪切当前行,粘贴时是在光标的下一行位置粘贴
  • 键盘按下y:复制选中的文本,粘贴时是在光标的下一个位置粘贴
  • 键盘按下yy:复制当前行,粘贴时是在光标的下一行位置粘贴
  • 键盘按下p:将复制或剪切的数据在光标的下一行或下一个位置粘贴
  • 键盘按下u:撤销
  • 键盘按下CTRL + r:取消撤销
  • 键盘按下SHIFT + >:将选中的文本整体向右缩进一次
  • 键盘按下SHIFT + <:将选中的文本整体向左缩进一次
  • 键盘按下:w:保存
  • 键盘按下:w!:强制保存
  • 键盘按下:q:退出
  • 键盘按下:q!:强制退出
  • 键盘按下:wq:保存并退出
  • 键盘按下:wq!:强制保存并退出
  • 键盘按下:set nu:显示行号
  • 键盘按下:set nonu:隐藏行号
  • 键盘按下:set paste:设置成粘贴模式,取消代码自动缩进
  • 键盘按下:set nopaste:设置成非粘贴模式,开启代码自动缩进
  • 键盘按下CTRL + q:当vim卡死时,可以取消当前正在执行的命令

vim的常用组合键:

  • 键盘按下ggdG:删除全文
  • 键盘按下gg=G:全文代码格式化(当全文代码很长时,此方式会占用很大带宽)

vim的异常处理:

  • 每次用vim编辑文件时,会自动创建一个.filename.swp的临时文件,如果打开某个文件时,该文件的swp文件已存在,则会报错
    • 此时解决办法有两种:
      • 找到正在打开该文件的程序,并退出
      • 直接删掉该swp文件即可

shell语法

概论

  • shell是我们通过命令行与操作系统沟通的语言
  • shell脚本可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用
  • AC Terminal中的命令行可以看成是一个“shell脚本在逐行执行”
  • Linux中常见的shell脚本有很多种,常见的有
    • Bourne Shell(/usr/bin/sh或/bin/sh)
    • Bourne Again Shell(/bin/bash)(这个是最常用的)
    • C Shell(/usr/bin/csh)
    • K Shell(/usr/bin/ksh)
    • zsh
  • .sh文件开头需要写上 #! /bin/bash 这一行(注意不要加分号;),作用是指明bash为脚本的解释器

示例:新建一个test.sh文件,内容如下

#! /bin/bash

# echo会自动换行
echo "Hello World!" 
echo Hello World!!! # 也可以写成这种,不加双引号的

第一种运行方式:直接用解释器执行,该文件不需要有可执行权限也可以

acs@80826ae841a9:~/temp$ pwd
/home/acs/temp
acs@80826ae841a9:~/temp$ ls
temp.cpp  test.sh
acs@80826ae841a9:~/temp$ bash test.sh # 直接用解释器执行
Hello World!
Hello World!!!
acs@80826ae841a9:~/temp$ 

第二种运行方式:把test.sh作为可执行文件,该文件必须要有可执行权限

acs@80826ae841a9:~/temp$ pwd
/home/acs/temp
acs@80826ae841a9:~/temp$ ls
temp.cpp  test.sh
acs@80826ae841a9:~/temp$ ls -l test.sh
-rw-rw-r-- 1 acs acs 34 Aug  5 23:33 test.sh
acs@80826ae841a9:~/temp$ chmod +x test.sh # 添加可执行权限
acs@80826ae841a9:~/temp$ ls -l test.sh
-rwxrwxr-x 1 acs acs 34 Aug  5 23:33 test.sh
acs@80826ae841a9:~/temp$ ./test.sh # 在当前路径下执行
Hello World!
acs@80826ae841a9:~/temp$ test.sh # 这么写是错误的,必须要加上./
-bash: test.sh: command not found
acs@80826ae841a9:~/temp$ /home/acs/temp/test.sh # 在绝对路径下执行。也可以在相对路径下执行
Hello World!
acs@80826ae841a9:~/temp$ 

注释

单行注释

#! /bin/bash

# 这是一行注释

多行注释:其中EOF可以换成其它任意字符串

#! /bin/bash

:<<EOF
注释1
注释2
注释3
注释4
...
EOF

:<<abc
注释1
注释2
注释3
注释4
...
abc

:<<!
注释1
注释2
注释3
注释4
...
!

变量

  • 定义变量和使用变量
#! /bin/bash

# 定义变量
name1="yxc" # 注意等于号左右两边不能有空格
name2='yxc'
name3=yxc

# 使用变量
echo $name3
echo ${name3} # 一般推荐使用这种方式,存在明确边界
echo ${name3}acwing
echo "${name3}acwing"
  • 使用 readonly 或者 declare -r 可以将变量变为只读变量
#! /bin/bash

name1=yxc

readonly name1 # 将变量定义为只读变量

name2=acwing

declare -r name2 # 将变量定义为只读变量
  • 删除变量
#! /bin/bash

name=yxc

unset name # 删除变量

echo ${name} # 输出为空值
  • 变量类型
    • 自定义变量(局部变量),即子进程不能访问的变量
    • 环境变量(全局变量),即子进程可以访问的变量

自定义变量改成环境变量(当前在tmux中操作,一个pane里面的bash即可视为一个进程):

acs@80826ae841a9:~/temp$ name=yxc # 定义变量
acs@80826ae841a9:~/temp$ export name # 第一种方法,将自定义变量改成环境变量
acs@80826ae841a9:~/temp$ declare -x name # 第二种方法,将自定义变量改成环境变量
acs@80826ae841a9:~/temp$ 
acs@80826ae841a9:~/temp$ bash # 可以进入到一个新的bash中,即视为开了一个子进程,原来的进程则会进入睡眠
acs@80826ae841a9:~/temp$ echo $name # 子进程中可以访问环境变量
yxc
acs@80826ae841a9:~/temp$ exit # 退出子进程
exit
acs@80826ae841a9:~/temp$ 

环境变量改成自定义变量(当前在tmux中操作,一个pane里面的bash即可视为一个进程):

acs@80826ae841a9:~/temp$ name=yxc # 定义变量
acs@80826ae841a9:~/temp$ export name # 将自定义变量改成环境变量
acs@80826ae841a9:~/temp$ declare +x name # 将环境变量改成自定义变量
acs@80826ae841a9:~/temp$ 
acs@80826ae841a9:~/temp$ bash # 可以进入到一个新的bash中,即视为开了一个子进程,原来的进程则会进入睡眠
acs@80826ae841a9:~/temp$ echo $name # 子进程中不能访问自定义变量

acs@80826ae841a9:~/temp$ exit # 退出子进程
exit
acs@80826ae841a9:~/temp$ 
acs@80826ae841a9:~/temp$ echo name
name
acs@80826ae841a9:~/temp$ 
  • 字符串,可以用单引号,也可以用双引号,也可以不用引号
    • 单引号与双引号**(不用引号和用双引号一样)**的区别:
      • 单引号中的内容会原样输出,不会执行、不会取变量、不会转义
      • 双引号中的内容可以执行、可以取变量、可以转义
    • 获取字符串长度
    • 获取字符串的子串
#! /bin/bash

name=yxc

echo 'hello, $name \"hh\"'  # 单引号字符串,输出:hello, $name \"hh\"

echo "hello, $name \"hh\""  # 双引号字符串,输出:hello, yxc "hh"
echo hello, $name \"hh\" # 不用引号字符串,输出:hello, yxc "hh"

echo ${#name} # 能够输出字符串长度,输出:3

temp="hello,yxc"

echo ${temp:0:5} # 输出从下标为0开始,长度为5的子串,输出:hello

默认变量

  • 文件参数变量

    • 在执行shell脚本时,可以向脚本传递参数

      • 脚本内容如下

        #! /bin/bash
        
        echo "文件名:"${0}
        echo "第一个参数:"${1}
        echo "第二个参数:"${2}
        echo "第三个参数:"${3}
        echo "第四个参数:"${4}
        
        echo "传入的参数个数:"${#}
        
        echo "输出由所有参数构成的用空格隔开的字符串:"${*}
        
        echo "输出每个参数分别用双引号括起来的字符串:"${@}
        
        echo "当前脚本的进程ID:"${$}
        
        echo "输出上一条命令的退出状态(exit code),0表示正常退出,其他值表示错误:"${?}
        
        # echo "返回command这条命令的stdout(可嵌套):"$(command)
        echo "返回ls这条命令的stdout(可嵌套):"$(ls)
        
        # echo "返回command这条命令的stdout(不可嵌套):"`command`
        echo "返回pwd这条命令的stdout(不可嵌套):"`pwd`
        
      • 执行脚本

        acs@80826ae841a9:~/temp$ pwd
        /home/acs/temp
        acs@80826ae841a9:~/temp$ ls
        temp.cpp  test.sh
        acs@80826ae841a9:~/temp$ ./test.sh yxc 12 cgw 18 
        文件名:./test.sh
        第一个参数:yxc
        第二个参数:12
        第三个参数:cgw
        第四个参数:18
        传入的参数个数:4
        输出由所有参数构成的用空格隔开的字符串:yxc 12 cgw 18
        输出每个参数分别用双引号括起来的字符串:yxc 12 cgw 18
        当前脚本的进程ID:2357
        输出上一条命令的退出状态(exit code),0表示正常退出,其他值表示错误:0
        返回ls这条命令的stdout(可嵌套):temp.cpp test.sh
        返回pwd这条命令的stdout(不可嵌套):/home/acs/temp
        acs@80826ae841a9:~/temp$ 
        

数组

数组中可以存放多个不同类型的值,只支持一维数组,初始化时不需要指明数组大小,数组下标从0开始,数组下标灵活

  • 定义

    #! /bin/bash
    
    # 第一种定义方式,数组用小括号表示,元素之间用空格隔开
    array1=(1 abc "def" 'yxc')
    
    # 第二种定义方式,直接定义数组中某个元素的值
    array2[0]=1
    array2[1]=abc
    array2[2]="def"
    array2[3]='yxc'
    
    # 第三种定义方式,可以直接定义空数组
    array3=
    
  • 读取数组中某个元素的值

    • 脚本内容如下

      #! /bin/bash
      
      # 第一种定义方式,数组用小括号表示,元素之间用空格隔开
      array1=(1 abc "def" 'yxc')
      
      # 第二种定义方式,直接定义数组中某个元素的值
      array2[0]=1
      array2[1]=abc
      array2[2]="def"
      array2[1000]='yxc' # 数组下标灵活,array2数组的长度是4,不是1000
      
      # 读取数组中某个元素的值
      echo ${array1[0]}
      echo ${array1[1]}
      echo ${array1[2]}
      echo ${array1[3]}
      echo "---------------"
      echo ${array2[0]}
      echo ${array2[1]}                                                                                                                                                            
      echo ${array2[2]}
      echo ${array2[1000]}
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh
      1
      abc
      def
      yxc
      ---------------
      1
      abc
      def
      yxc
      acs@80826ae841a9:~/temp$ 
      
  • 读取整个数组

    • 脚本内容如下

      #! /bin/bash
      
      array=(1 abc "def" 'yxc')
      
      # 读取整个数组
      echo ${array[*]} # 第一种写法
      echo "---------------"
      echo ${array[@]}  # 第二种写法
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh
      1 abc def yxc
      ---------------
      1 abc def yxc
      acs@80826ae841a9:~/temp$ 
      
  • 读取数组长度

    • 脚本内容如下

      #! /bin/bash
      
      array=(1 abc "def" 'yxc')
      
      # 读取数组长度
      echo ${#array[*]} # 第一种写法
      echo "---------------"
      echo ${#array[@]}  # 第二种写法
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      4
      ---------------
      4
      acs@80826ae841a9:~/temp$ 
      

expr命令

  • expr命令:用于求表达式的值

关于表达式的说明:

  • 用空格隔开每一项
  • 用反斜杠放在shell特定的字符前面(发现表达式运行错误时,可以试试转义)
  • 对包含空格和其他特殊字符的字符串要用引号括起来
  • **expr命令执行后本身会在stdout中输出结果:**如果为逻辑关系表达式,则结果为真时输出1,结果为假时输出0
  • expr命令的exit code(退出状态):0表示真,非0表示假

三种表达式的优先级:逻辑关系表达式 < 算术表达式 < 字符串表达式

字符串表达式

  • 求字符串长度

    • 脚本内容如下

      #! /bin/bash
      
      str="Hello World!"
      
      echo $(expr length "${str}") # 如果字符串存在空格,则需要加上双引号
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh
      12
      acs@80826ae841a9:~/temp$ 
      
  • 返回给定字符集中的任意单个字符在字符串中最早出现的位置(位置从1开始数),如果没有结果则返回0

    • 脚本内容如下

      #! /bin/bash
      
      str="Hello World!"
      
      echo $(expr index "${str}" aWd)
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh
      7
      acs@80826ae841a9:~/temp$ 
      
  • 截取字符串

    • 脚本内容如下

      #! /bin/bash
      
      str="Hello World!"
      
      echo $(expr substr "${str}" 2 3) # 输出从第2个字母开始长度为3的字符串
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      ell
      acs@80826ae841a9:~/temp$ 
      

整数表达式(算术表达式)

  • 加,减运算:两端参数会转换为整数,如果转换失败则报错
  • 乘,除,取模运算:两端参数会转换为整数,如果转换失败则报错
  • 括号可以改变优先级,但需要用反斜杠转义

脚本内容如下

#! /bin/bash

a=3
b=4

# 加减
echo $(expr ${a} + ${b}) # 这种写法比较麻烦
echo `expr $a - $b`
echo "--------------------------"

# 乘除取模
echo `expr $a \* $b` # *需要转义
echo `expr $a / $b`
echo `expr $a % $b`                                                                                                                                                          
echo "--------------------------"

# 添加括号
echo `expr \( $a + 1 \) \* \( $b + 1 \)`

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh
7
-1
--------------------------
12
0
3
--------------------------
20
acs@80826ae841a9:~/temp$ 

逻辑关系表达式

  • |

    • 如果第一个参数非空且非0, 则返回第一个参数的值,否则如果第二个参数的值非空且非0,就返回第二个参数的值,否则返回0
    • 遵循短路原则
  • &

    • 如果两个参数都非空且非0,则返回第一个参数,否则返回0
    • 遵循短路原则
  • <(小于)<=(小于等于)=(等于)==(等于)!=(不等于)>(大于)>=(大于等于)

    • 比较两端的参数,如果为true,则返回1,否则返回0
    • ==和=是同义词
    • expr首先尝试将两端参数转换为整数,如果转换失败,则按字符集排序规则做字符比较
    • 括号可以改变优先级,但需要用反斜杠转义

脚本内容如下

#! /bin/bash

a=3
b=4
c=0
d=5

echo `expr $c \& $d`
echo `expr $a \& $b`
echo `expr $c \| $d`
echo `expr $a \| $b`

echo "---------------------"
echo `expr $a \> $b` # >需要转义
echo $? # 上一条命令的exit code为0                                                                                                                                                                     
echo "---------------------"
expr $a \> $b # >需要转义,expr命令执行后本身会在stdout中输出结果
echo $? # 上一条命令的exit code为1
echo "---------------------"
echo `expr $a '<' $b` # 也可以用引号引起来,不一定要用反斜杠转义
echo `expr $a '>=' $b`
echo `expr $a \<\= $b`

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh 
0
3
5
3
---------------------
0
0
---------------------
0
1
---------------------
1
0
1
acs@80826ae841a9:~/temp$ 

read命令

  • read命令:用于从标准输入中读取单行数据,当读到文件结束符时,exit code为1,否则为0
  • 文件结束符为:键盘按下CTRL + d
  • 参数说明:
    • -p:后面可以接提示信息
    • -t:后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令

脚本内容如下

#! /bin/bash

# read 变量名
read name1 # 变量名不需要加$

echo Hello,$name1!

echo "----------------------------------"

read -p "What'a is your name?" name2

echo Hello,$name2!

echo "----------------------------------"

read -p "What'a is your name?" -t 5 name3 # 读入name3的值,等待时间5秒

echo Hello,$name3!

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh 
yxc
Hello,yxc!
----------------------------------
What'a is your name?cgw
Hello,cgw!
----------------------------------
What'a is your name?Hello,!
acs@80826ae841a9:~/temp$ 

知识点补充

acs@80826ae841a9:~/temp$ read name
yxc
acs@80826ae841a9:~/temp$ echo ${?}
0
acs@80826ae841a9:~/temp$ read name # 直接读入文件结束符,键盘按下CTRL + d
acs@80826ae841a9:~/temp$ echo ${?} # 读到文件结束符时,上一条命令的退出状态(exit code)为1
1
acs@80826ae841a9:~/temp$ 

echo命令

  • echo命令:用于输出字符串
    • 显示普通字符串
    • 显示转义字符
    • 显示变量
    • 显示换行
    • 显示不换行
    • 显示结果定向至文件
    • 原样输出字符串,不进行转义或取变量(用单引号)
    • 显示命令的执行结果

脚本内容如下

#! /bin/bash

# 显示普通字符串
echo "Hello AC Terminal"
echo Hello AC Terminal

echo "-----------------------------------"

# 显示转义字符
echo "\"Hello AC Terminal\"" # 注意只能使用双引号,如果使用单引号,则不转义
echo \"Hello AC Terminal\"

echo "-----------------------------------"

# 显示变量
name=yxc
echo "My name is $name"

echo "-----------------------------------"

# 显示换行
echo -e "Hi\n" # -e表示开启转义,\n换行
echo "acwing"

echo "-----------------------------------"

# 显示不换行                                                                                                                                                                 
echo -e "Hi,\c" # -e表示开启转义,\c不换行
echo "acwing"

echo "-----------------------------------"

# 显示结果定向至文件
echo "Hello World!" > output.txt # 将内容以覆盖的方式输出到output.txt中

echo "-----------------------------------"

# 原样输出字符串,不进行转义或取变量(用单引号)
temp=cgw
echo '\"$temp\"'

echo "-----------------------------------"

# 显示命令的执行结果
echo `date`
echo $(date)

执行脚本

acs@80826ae841a9:~/temp$ ls
temp.cpp  test.sh
acs@80826ae841a9:~/temp$ ./test.sh 
Hello AC Terminal
Hello AC Terminal
-----------------------------------
"Hello AC Terminal"
"Hello AC Terminal"
-----------------------------------
My name is yxc
-----------------------------------
Hi

acwing
-----------------------------------
Hi,acwing
-----------------------------------
-----------------------------------
\"$temp\"
-----------------------------------
Sun Aug 13 15:34:41 CST 2023
Sun Aug 13 15:34:41 CST 2023
acs@80826ae841a9:~/temp$ ls
output.txt  temp.cpp  test.sh
acs@80826ae841a9:~/temp$ cat output.txt 
Hello World!
acs@80826ae841a9:~/temp$ 

printf命令

  • printf命令:用于格式化输出,类似于C/C++中的printf函数,默认不会在字符串末尾添加换行符

脚本内容如下

#! /bin/bash

printf "%10d.\n" 123 # 占10位,右对齐
printf "%-10.2f.\n" 123.125321 # 占10位,左对齐,保留2位小数(四舍五入)
printf "My name is %s\n" "yxc" # 格化输出字符串
printf "%d * %d = %d\n" 2 3 `expr 2 \* 3` # 表达式的值作为参数

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh 
       123.
123.13    .
My name is yxc
2 * 3 = 6
acs@80826ae841a9:~/temp$ 

test命令

  • 逻辑运算符&&和||

    • 二者具有短路原则,我们可以利用短路原则来实现if else语句的作用

    • 表达式的exit code(退出状态)为0表示真,为非0表示假(与C和C++中的定义相反)

  • test命令

    • test命令用于:判断数值比较的结果、判断字符串比较的结果、判断文件的类型和权限
    • test命令执行后本身不会在stdout中输出结果
    • test命令的exit code(退出状态):0表示真,非0表示假

判断数值比较的结果,有如下参数(只能用于数值的比较)

  • -eq(等于)
  • -ne(不等于)
  • -gt(大于)
  • -lt(小于)
  • -ge(大于等于)
  • -le(小于等于)

脚本内容如下

#! /bin/bash

test 2 -lt 3 # 判断2小于3是否成立
echo $? # 输出上个命令的返回值,2小于3为真,返回0,所以输出0

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh 
0
acs@80826ae841a9:~/temp$ 

判断字符串比较的结果,有如下参数

  • -z(判断字符串是否为空,如果为空,则返回true)
  • -n(判断字符串是否非空,如果非空,则返回true(-n可以省略))
  • ==(判断字符串是否相等)
  • !=(判断字符串是否不相等)
acs@80826ae841a9:~/temp$ test -z "Hello"   
acs@80826ae841a9:~/temp$ echo $?
1
acs@80826ae841a9:~/temp$ test -n "Hello"
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ test "Hello" == "hello"
acs@80826ae841a9:~/temp$ echo $?
1
acs@80826ae841a9:~/temp$ test "Hello" != "hello"
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ 

判断文件的类型,有如下参数

  • -e(判断文件是否存在)
  • -f(判断是否为文件)
  • -d(判断是否为目录)
acs@80826ae841a9:~/temp$ ls
temp.cpp  test.sh
acs@80826ae841a9:~/temp$ 
acs@80826ae841a9:~/temp$ test -e test.sh && echo "exist" || echo "Not exist"
exist
acs@80826ae841a9:~/temp$ test -e test2.sh && echo "exist" || echo "Not exist"
Not exist
acs@80826ae841a9:~/temp$ test -f test.sh && echo "yy" || echo "nn"
yy
acs@80826ae841a9:~/temp$ test -d test.sh && echo "yy" || echo "nn"
nn
acs@80826ae841a9:~/temp$ 
acs@80826ae841a9:~/temp$ test -e test.sh 
acs@80826ae841a9:~/temp$ echo $?  
0
acs@80826ae841a9:~/temp$ test -f test.sh 
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ test -d test.sh 
acs@80826ae841a9:~/temp$ echo $?
1
acs@80826ae841a9:~/temp$ 

判断文件的权限,有如下参数

  • -r(判断文件是否可读)
  • -w(判断文件是否可写)
  • -x(判断文件是否可执行)
  • -s(判断是否为非空文件)
acs@80826ae841a9:~/temp$ ls -l
total 8
-rw-rw-r-- 1 acs acs 132 Aug  4 00:12 temp.cpp
-rwxrwxr-x 1 acs acs 147 Aug 13 17:10 test.sh
acs@80826ae841a9:~/temp$ test -r temp.cpp 
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ test -w temp.cpp 
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ test -x temp.cpp 
acs@80826ae841a9:~/temp$ echo $?
1
acs@80826ae841a9:~/temp$ test -s temp.cpp 
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ 
  • 多重条件判定,有如下参数
    • -a(判断两个条件是否同时成立)
    • -o(判断两个条件是否至少一个成立)
    • !(取反)
acs@80826ae841a9:~/temp$ ls -l
total 8
-rw-rw-r-- 1 acs acs 132 Aug  4 00:12 temp.cpp
-rwxrwxr-x 1 acs acs 147 Aug 13 17:10 test.sh
acs@80826ae841a9:~/temp$ test -r temp.cpp -a -x temp.cpp # 判断temp.cpp是否可读并且可执行
acs@80826ae841a9:~/temp$ echo $?
1
acs@80826ae841a9:~/temp$ test -r temp.cpp -o -x temp.cpp # 判断temp.cpp是否可读或者可执行
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ test ! -x temp.cpp # 判断temp.cpp是否不可执行
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ 

判断符号[]

判断符号[]与test命令的用法几乎一模一样

判断符号[]更常用于if语句中

[[]]是[]的加强版,支持的特性更多

注意事项:

  • []内的每一项都要用空格隔开
  • []内的变量,最好用双引号括起来
  • []内的常数,最好用单引号或双引号括起来
acs@80826ae841a9:~/temp$ [ 2 -lt 3 ] # 为真,返回值为0
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ ls
temp.cpp  test.sh
acs@80826ae841a9:~/temp$ [ -e test.sh ] # 为真,返回值为0
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ name="acwing yxc"
acs@80826ae841a9:~/temp$ [ "$name" == "acwing yxc" ]
acs@80826ae841a9:~/temp$ echo $?
0
acs@80826ae841a9:~/temp$ 

判断语句

  • 单层if

    • 脚本内容如下

      #! /bin/bash
      
      a=3
      b=4
      
      if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
      then
          echo ${a}在范围内
      fi
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ls   
      temp.cpp  test.sh
      acs@80826ae841a9:~/temp$ ./test.sh 
      3在范围内
      acs@80826ae841a9:~/temp$ 
      
  • 单层if else

    • 脚本内容如下

      #! /bin/bash
      
      a=3
      b=4
      
      if ! [ "$a" -lt "$b" ]
      then
          echo ${a}不小于${b}
      else
          echo ${a}小于${b}
      fi
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      3小于4
      acs@80826ae841a9:~/temp$ 
      
  • 多层if elif elif else

    • 脚本内容如下

      #! /bin/bash
      
      a=4
      
      if [ "$a" -eq 1 ]
      then
          echo ${a}等于1
      elif [ "$a" -eq 2 ]
      then
          echo ${a}等于2
      elif [ "$a" -eq 3 ]
      then
          echo ${a}等于3
      else
          echo ${a}等于4
      fi
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      4等于4
      acs@80826ae841a9:~/temp$ 
      
  • case esac形式,类似于C和C++中的switch语句

    • 脚本内容如下

      #! /bin/bash
      
      a=4
      
      case "$a" in
          1)
              echo ${a}等于1 # 语句1
              # 语句2
              # 语句3
              # ......
              ;; # 类似于C和C++中的break
          2)
              echo ${a}等于2
              ;;
          3)
              echo ${a}等于3
              ;;
          *) # 类似于C和C++中的default
              echo ${a}等于其它数
              ;;                                                                                                                                                                   
      esac
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      4等于其它数
      acs@80826ae841a9:~/temp$ 
      

循环语句

  • for…in…do…done

    • 示例一:脚本内容如下

      #! /bin/bash
      
      for i in a 2 cc
      do
          echo ${i}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh
      a
      2
      cc
      acs@80826ae841a9:~/temp$ 
      
    • 示例二:脚本内容如下

      #! /bin/bash
      
      for file in `ls`
      do
          echo ${file}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ls
      temp.cpp  test.sh
      acs@80826ae841a9:~/temp$ ./test.sh 
      temp.cpp
      test.sh
      acs@80826ae841a9:~/temp$ 
      
    • 示例三:脚本内容如下

      #! /bin/bash
      
      # `seq 1 10`会返回用回车隔开的1到10
      for i in `seq 1 10`
      do
          echo ${i}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      acs@80826ae841a9:~/temp$ 
      
    • 示例四:脚本内容如下

      #! /bin/bash
      
      for i in {1..10}
      do
          echo ${i}
      done
      
      echo "----------------------"
      
      for i in {a..z}
      do
          echo ${i}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh                                                                                                                           
      1                                                                                                                                                            
      2                                                                                                                                                            
      3                                                                                                                                                            
      4                                                                                                                                                            
      5
      6
      7
      8
      9
      10
      ----------------------
      a
      b
      c
      d
      e
      f
      g
      h
      i
      j
      k
      l
      m
      n
      o
      p
      q
      r
      s
      t
      u
      v
      w
      x
      y
      z
      acs@80826ae841a9:~/temp$ 
      
  • for ((…;…;…)) do…done

    • 脚本内容如下

      #! /bin/bash
      
      for ((i=1; i<=10; i++))                                                                                                                                      
      do
          echo ${i}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      acs@80826ae841a9:~/temp$ 
      
  • while…do…done

    文件结束符为键盘按下CTRL + d,输入文件结束符后read命令的退出状态(exit code)为1

    • 脚本内容如下

      #! /bin/bash
      
      while read name
      do
          echo "上一条read命令的exit code为:${?}"
          echo "-------------------------------"
          echo "输入的字符或字符串为:${name}"
          echo "-------------------------------"
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      yxc
      上一条read命令的exit code为:0
      -------------------------------
      输入的字符或字符串为:yxc
      -------------------------------
      cgw
      上一条read命令的exit code为:0
      -------------------------------
      输入的字符或字符串为:cgw
      -------------------------------
      acs@80826ae841a9:~/temp$ 
      
  • until…do…done

    先执行do…done中的命令,再进行判断

    注意:当判断条件为真时会结束循环,判断条件为假时会继续循环!!!跟一般的循环语句的判断条件反着来的!!!

    • 脚本内容如下

      #! /bin/bash
      
      # 当用户读入yes或者YES时,判断条件为真,结束循环,否则一直等待读入
      until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
      do
          read -p "Please input yes/YES to stop this program:" word
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      Please input yes/YES to stop this program:yES
      Please input yes/YES to stop this program:yeS
      Please input yes/YES to stop this program:yes
      acs@80826ae841a9:~/temp$ ./test.sh 
      Please input yes/YES to stop this program:Yes
      Please input yes/YES to stop this program:YEs
      Please input yes/YES to stop this program:YES
      acs@80826ae841a9:~/temp$ 
      
  • break

    跳出当前这一层的循环

    注意:与C/C++不同的是,break不能跳出case语句

    • 脚本内容如下

      #! /bin/bash
      
      # 每次读入非结束符的字符串或字符时,会输出一遍1~7
      while read name
      do
          for ((i=1; i<=10; i++))
          do
              case ${i} in
                  8)
                      break;# 跳出的是for循环,而不是case语句
                      ;;
                  *)
                      echo ${i}
                      ;;
              esac
          done
      done 
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      yxc
      1
      2
      3
      4
      5
      6
      7
      cgw
      1
      2
      3
      4
      5
      6
      7
      acs@80826ae841a9:~/temp$ 
      
  • continue

    跳出当前这次循环,直接进入下一次循环

    • 脚本内容如下

      #! /bin/bash
      
      # 输出1~10中的奇数
      for ((i=1; i<=10; i++))
      do
          if [ `expr ${i} % 2` -eq 0 ]
          then
              continue
          fi
          echo ${i}
      done
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      1
      3
      5
      7
      9
      acs@80826ae841a9:~/temp$ 
      

死循环的处理方式

  • 如果可以打开该程序,则键盘按下CTRL + c即可
  • 如果无法打开该程序,则
    • 使用top命令找到进程的PID
    • 使用kill -9 PID命令即可强制关掉此进程

函数

bash中的函数类似于C/C++中的函数,但是bash中的函数return的返回值与C/C++的不同,bash中的函数return的返回值是exit code,取值为0~255,0表示正常结束

bash中的函数return的返回值可以通过${?}来获取

如果想获取bash中的函数的某些输出结果,可以把这些输出结果通过在函数中的echo输出到stdout中,然后通过 $(函数名) 或者 `函数名` 来截取获得stdout中的结果

  • 不获取return值和stdout值

    • 脚本内容如下

      #! /bin/bash
      
      function func() { # function关键字可以省略
          name=yxc
          echo "Hello ${name}"
          # 当函数中不写return时,则默认写了return 0
      }
      
      func # 调用函数
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      Hello yxc
      acs@80826ae841a9:~/temp$ 
      
  • 获取return值和stdout值

    • 脚本内容如下

      #! /bin/bash
      
      func() {
          name=yxc
          echo "Hello ${name}"
          return 123 # 注意数值范围在0~255
      }
      
      output=`func` # 截取获得函数中的echo输出到stdout中的结果,赋值给output变量
      ret=${?}
      
      echo "output = ${output}"
      echo "return = ${ret}"
      
    • 执行脚本

      # 注意!!!执行脚本的结果为这个!!!
      acs@80826ae841a9:~/temp$ ./test.sh 
      output = Hello yxc
      return = 123
      acs@80826ae841a9:~/temp$ 
      
      # 而不是我想象中的这个!!!
      # acs@80826ae841a9:~/temp$ ./test.sh
      # Hello yxc
      # output = Hello yxc
      # return = 123
      # acs@80826ae841a9:~/temp$ 
      
  • 函数的输入参数

    在函数内, 1 表示第一个输入参数, {1}表示第一个输入参数, 1表示第一个输入参数,{2}表示第二个输入参数,依此类推

    注意:函数内的${0}仍然是文件名,而不是函数名

    • 脚本内容如下

      • 简单递归的版本

        #! /bin/bash
        
        func() {
            if [ ${1} -le 0 ] # 当函数的第一个输入参数小于等于0时,则结束递归
            then
                echo 0
                return 0
            fi
        
        	# 递归计算 10 + 9 + 8 + ... + 2 + 1 + 0 的值
            sum=$(func $(expr ${1} - 1))
            echo $(expr ${1} + ${sum})
        }
        
        echo `func 10`
        
      • 可以控制递归的版本,可以有效防止递归发生死循环

        #! /bin/bash
        
        func() {
            word=""
            while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
            do
                read -p "要进入func(${1})函数吗?请输入y/n:" word
            done
        
            if [ "${word}" == 'n' ]
            then
                echo 0
                return 0 # 函数正常退出
            fi  
        
            if [ ${1} -le 0 ] # 当函数的第一个输入参数小于等于0时,则结束递归
            then
                echo 0
                return 0 # 函数正常退出
            fi  
        
        	# 递归计算 10 + 9 + 8 + ... + 2 + 1 + 0 的值
            sum=$(func $(expr ${1} - 1))
            echo `expr ${1} + ${sum}`
        }
        
        echo `func 10` # 截取获得函数中的echo输出到stdout中的结果,然后再执行这一行的echo
        
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      要进入func(10)函数吗?请输入y/n:y
      要进入func(9)函数吗?请输入y/n:y
      要进入func(8)函数吗?请输入y/n:y
      要进入func(7)函数吗?请输入y/n:y
      要进入func(6)函数吗?请输入y/n:y
      要进入func(5)函数吗?请输入y/n:y
      要进入func(4)函数吗?请输入y/n:y
      要进入func(3)函数吗?请输入y/n:y
      要进入func(2)函数吗?请输入y/n:y
      要进入func(1)函数吗?请输入y/n:y
      要进入func(0)函数吗?请输入y/n:y
      55
      acs@80826ae841a9:~/temp$ 
      acs@80826ae841a9:~/temp$ ./test.sh 
      要进入func(10)函数吗?请输入y/n:y
      要进入func(9)函数吗?请输入y/n:y
      要进入func(8)函数吗?请输入y/n:y
      要进入func(7)函数吗?请输入y/n:y
      要进入func(6)函数吗?请输入y/n:y
      要进入func(5)函数吗?请输入y/n:y
      要进入func(4)函数吗?请输入y/n:y
      要进入func(3)函数吗?请输入y/n:y
      要进入func(2)函数吗?请输入y/n:n
      52
      acs@80826ae841a9:~/temp$ 
      
  • 函数内的局部变量

    可以在函数内定义局部变量,局部变量作用范围仅在当前函数内

    可以在递归函数中定义局部变量

    • 示例一:脚本内容如下

      #! /bin/bash
      
      func() {
          local name=yxc # 局部变量,作用范围在当前函数内
          echo "Name is ${name}"
      }
      
      func
      
      echo "<<<${name}>>>"
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      Name is yxc
      <<<>>>
      acs@80826ae841a9:~/temp$ 
      
    • 示例二:脚本内容如下

      #! /bin/bash
      
      func() {
          name=yxc
          echo "Name is ${name}"
      }
      
      func
      
      echo "<<<${name}>>>"
      
    • 执行脚本

      acs@80826ae841a9:~/temp$ ./test.sh 
      Name is yxc
      <<<yxc>>>
      acs@80826ae841a9:~/temp$ 
      

exit命令

exit命令用于退出当前shell进程,并返回一个退出状态的值,使用${?}可以接收这个退出状态的值

exit命令可以接受一个整数值作为参数,表示退出状态的值,如果不指定,则退出状态的值默认为0

exit命令退出状态的值只能是0~255之间的整数,其中只有0表示成功(正常退出),其它值都表示失败(非正常退出)

脚本内容如下

#! /bin/bash

if [ ${#} -ne 1 ]
then
    echo "传入参数的个数不等于1"
    exit 1
else
    echo "传入参数的个数等于1"
    # exit 和 exit 0 的效果一样
    # exit
    exit 0
fi

执行脚本

acs@80826ae841a9:~/temp$ ./test.sh 
传入参数的个数不等于1
acs@80826ae841a9:~/temp$ echo ${?}
1
acs@80826ae841a9:~/temp$ ./test.sh acwing
传入参数的个数等于1
acs@80826ae841a9:~/temp$ echo ${?}
0
acs@80826ae841a9:~/temp$ 

文件重定向

每个进程默认都会打开3个文件

  • stdin(标准输入),从命令行读取数据,文件描述符为0
  • stdout(标准输出),向命令行输出数据,文件描述符为1
  • stderr(标准错误输出),向命令行输出数据,文件描述符为2

可以用文件重定向将这3个文件重定向到其它文件中

重定向命令

  • command < file:将stdin重定向到file中,即从file中读取内容

  • command > file:将stdout重定向到file中

  • command >> file:将stdout以追加方式重定向到file中

  • command n> file:将文件描述符n重定向到file中

  • command n>> file:将文件描述符n以追加方式重定向到file中

  • 示例一:

    acs@80826ae841a9:~/temp$ ls
    temp.cpp  test.sh
    acs@80826ae841a9:~/temp$ ls > output.txt
    acs@80826ae841a9:~/temp$ ls
    output.txt  temp.cpp  test.sh
    acs@80826ae841a9:~/temp$ cat output.txt 
    output.txt
    temp.cpp
    test.sh
    acs@80826ae841a9:~/temp$ 
    
  • 示例二:

    脚本内容如下:

    #! /bin/bash
    
    echo -e "Hello \c" > output.txt # 将stdout重定向到output.txt中
    echo "World" >> output.txt # 将stdout以追加方式重定向到output.txt中
    
    read str < output.txt # 从output.txt中读取内容
    
    echo ${str}
    

    执行脚本:

    acs@80826ae841a9:~/temp$ ls             
    output.txt  temp.cpp  test.sh
    acs@80826ae841a9:~/temp$ cat output.txt 
    output.txt
    temp.cpp
    test.sh
    acs@80826ae841a9:~/temp$ ./test.sh 
    Hello World
    acs@80826ae841a9:~/temp$ cat output.txt 
    Hello World
    acs@80826ae841a9:~/temp$ 
    
  • 示例三:

    脚本内容如下:

    #! /bin/bash
    
    read a
    read b
    
    echo `expr ${a} + ${b}`
    

    执行脚本:

    acs@80826ae841a9:~/temp$ ls
    input.txt  temp.cpp  test.sh
    acs@80826ae841a9:~/temp$ cat input.txt 
    3
    4
    acs@80826ae841a9:~/temp$ ./test.sh < input.txt > output.txt # 从input.txt中读取内容,将stdout重定向到output.txt中
    acs@80826ae841a9:~/temp$ cat output.txt 
    7
    acs@80826ae841a9:~/temp$ 
    

引入外部脚本

类似于C/C++中的include操作,bash也可以引入其它文件中的代码

脚本内容如下:

#! /bin/bash

# 第一种写法,引入temp.sh文件,引入的文件只要有可读权限即可
# source temp.sh

# 第二种写法,引入temp.sh文件,引入的文件只要有可读权限即可
. temp.sh

echo "My name is:${name}" # 可以使用temp.sh文件中的变量

执行脚本:

acs@80826ae841a9:~/temp$ ls    
temp.cpp  temp.sh  test.sh
acs@80826ae841a9:~/temp$ cat temp.sh
#! /bin/bash

name=yxc
acs@80826ae841a9:~/temp$ ./test.sh
My name is:yxc
acs@80826ae841a9:~/temp$ 

ssh

ssh登录

  • 登录远程服务器

    acs@80826ae841a9:~$ pwd 
    /home/acs
    acs@80826ae841a9:~$ ls -al
    total 148
    drwxr-xr-x 1 acs  acs   4096 Sep 19 00:19 .
    drwxr-xr-x 1 root root  4096 Jul 23  2021 ..
    -rw------- 1 acs  acs   8493 Sep 18 23:56 .bash_history
    -rw-r--r-- 1 acs  acs    220 Jul 23  2021 .bash_logout
    -rw-r--r-- 1 acs  acs   3831 May 15 16:17 .bashrc
    drwx------ 2 acs  acs   4096 Jul 24 23:17 .cache
    drwx------ 3 acs  acs   4096 Jul 27 00:09 .config
    drwxrwxr-x 1 acs  acs   4096 Jul 27 22:59 .homework
    drwxr-xr-x 1 acs  acs   4096 Jul 23  2021 .ipython
    -rw-r--r-- 1 acs  acs    807 Jul 23  2021 .profile
    -rw------- 1 acs  acs      7 Aug 17  2021 .python_history
    drwx------ 1 acs  acs   4096 Sep 19 00:19 .ssh
    -rw-r--r-- 1 acs  acs      0 Jul 23  2021 .sudo_as_admin_successful
    -rw-r--r-- 1 acs  acs   1569 May 15 16:17 .tmux.conf
    drwxr-xr-x 1 acs  acs   4096 Sep  9  2021 .vim
    -rw------- 1 acs  acs  50595 Sep 19 00:19 .viminfo
    -rw-r--r-- 1 acs  acs   6128 May 15 16:17 .vimrc
    drwxrwxr-x 6 acs  acs   4096 Sep 18 23:42 homework
    drwxrwxr-x 2 acs  acs   4096 Sep  6 00:09 temp
    acs@80826ae841a9:~$ cd .ssh
    acs@80826ae841a9:~/.ssh$ ls # 此时该目录下还没有任何的文件
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$ homework 4 getinfo # 先获取需要登录的远程服务器的信息
    User: acs_11511 # 需要登录的远程服务器的某个用户名
    HostName: 123.57.67.128 # IP地址或域名
    Password: ******** # 密码(此处密码已经手动屏蔽)
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$ ssh acs_11511@123.57.67.128 -p 22 # 默认登录的端口号为22,命令中的"-p 22"可省略,除非想登录指定的端口号
    The authenticity of host '123.57.67.128 (123.57.67.128)' can't be established.
    ECDSA key fingerprint is SHA256:El+Pj10jXvbx4RWsVgvKj1qY6N4qTBTk0AGc7a87r0k.
    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes # 第一次登录某个远程服务器时会出现的提醒信息,直接输入yes
    Warning: Permanently added '123.57.67.128' (ECDSA) to the list of known hosts.
    acs_11511@123.57.67.128's password: 	# 直接输入密码
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ # 此时已经成功登录到远程服务器,当前用户名为acs_11511
    acs_11511@acs:~$ 
    acs_11511@acs:~$ 
    acs_11511@acs:~$ 
    acs_11511@acs:~$ exit # 使用exit命令或者键盘按下CTRL + d,可以直接退出登录的远程服务器
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/.ssh$ 
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$ pwd
    /home/acs/.ssh
    acs@80826ae841a9:~/.ssh$ ls # 此时该目录下发现多了一个文件known_hosts,该文件用于记录登录的远程服务器的信息
    known_hosts
    acs@80826ae841a9:~/.ssh$ 
    
  • 通过配置文件,可以简化ssh连接远程服务器操作

    acs@80826ae841a9:~/.ssh$ homework 4 getinfo                                    
    User: acs_11511                                                                
    HostName: 123.57.67.128                                                        
    Password: ******** # 密码(此处密码已经手动屏蔽)
    acs@80826ae841a9:~/.ssh$ pwd
    /home/acs/.ssh
    acs@80826ae841a9:~/.ssh$ ls                                                    
    known_hosts                                                            
    acs@80826ae841a9:~/.ssh$ vim config # 新建一个配置文件config                                           
    acs@80826ae841a9:~/.ssh$ ls                                                    
    config  known_hosts                                                            
    acs@80826ae841a9:~/.ssh$ cat config # 配置文件config内容如下,默认登录的端口号为22,可以省略,除非想登录指定的端口号                                          
    Host myserver                                                                  
        Hostname 123.57.67.128                                                     
        User acs_11511
        Port 22
    acs@80826ae841a9:~/.ssh$ ssh myserver # 现在使用ssh连接远程服务器时,可以直接使用别名myserver
    acs_11511@123.57.67.128's password: 
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ 
    acs_11511@acs:~$
    acs_11511@acs:~$
    acs_11511@acs:~$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/.ssh$ 
    
  • 密钥登录

    第一种方式

    acs@80826ae841a9:~/.ssh$ pwd                                                                                                                                                
    /home/acs/.ssh                                                                                                                                                              
    acs@80826ae841a9:~/.ssh$ ls                                                                                                                                                 
    config  known_hosts                                                                                                                                                                                                                                                                                                                                 
    acs@80826ae841a9:~/.ssh$ ssh-keygen # 通过这个命令可以直接创建密钥,命令执行后一直按回车即可
    Generating public/private rsa key pair.                                                                                                                                     
    Enter file in which to save the key (/home/acs/.ssh/id_rsa):                                                                                                                
    Enter passphrase (empty for no passphrase):                                                                                                                                 
    Enter same passphrase again:
    Your identification has been saved in /home/acs/.ssh/id_rsa                                                                                                                 
    Your public key has been saved in /home/acs/.ssh/id_rsa.pub                                                                                                                 
    The key fingerprint is:                                                                                                                                                     
    SHA256:TvU0i26amcku513ja138Hxq8drMJVj+o7VTC1mvNmKM acs@80826ae841a9                                                                                                         
    The key's randomart image is:                                                                                                                                               
    +---[RSA 3072]----+                                                                                                                                                         
    |                 |                                                                                                                                                         
    |                 |                                                                                                                                                         
    |          . o    |                        
    |         . +.o.  |                        
    |        S . o+ = |                        
    |       o .  o =+*|                        
    |        . o oO+*=|                        
    |      ...O o*+B+=|                        
    |       =X .oE*.o=|                        
    +----[SHA256]-----+                        
    acs@80826ae841a9:~/.ssh$ ls # 此时该目录下发现多了两个文件id_rsa、id_rsa.pub。id_rsa为记录私钥信息的文件,id_rsa.pub为记录公钥信息的文件
    config  id_rsa  id_rsa.pub  known_hosts
    acs@80826ae841a9:~/.ssh$ cat id_rsa.pub # 把id_rsa.pub记录的公钥信息,复制到需要登录的远程服务器的~/.ssh/authorized_keys文件中
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1TTXGpAqNKUt3AbtH85pOEUQTVNBx9dqmXcwUxRd++JaagGY8q1OkTQ/1Aojq/dGmKzM4F1Vdlz61w5QBoGqlqe71OwTLT0Iq4GLSkRNyl5C02vw/INOefRSmAD75RUAisT2Kto++pXJCQ+xJQXejduzjVKY0jZDqT4ijsuRw1tUpx4fM4GGKwfgKyJ5ff1Ucq/9b3m0CCOFdYKQd0pBPL8zVUJhCmSc/pjWTPYqE8zuC0LkvVpnAomeN3TAacJtSwb8lUR4Sb7S1L4PSetdU0O1KX6Rri3BW6+L8CU5q8YPMGrpTAwMZPBK8Xq491mRr0T9OVbPTqcGnUJRHvBjMwbk2MMkOHZj0g/LWkWVT7N9jj7/esdTVfknfBiY9DHQMUu5+eTUOwKQlXTs3L05FXGu5/5YBdH9zdbA4nm5qeLUlyRSPmk2uvE171zGoJ4ExXyLS79wBPKkO033Kkusvicun7bLAaUJugxozBrER1sF2hHZlVFKRoK6TeIPB9O8= acs@80826ae841a9
    acs@80826ae841a9:~/.ssh$ 
    acs@80826ae841a9:~/.ssh$ 
    acs@80826ae841a9:~/.ssh$ 
    acs@80826ae841a9:~/.ssh$ ssh myserver                                                                                                                                       
    acs_11511@123.57.67.128's password:                                                                                                                                         
    Welcome to AC Server                                                                                                                                                        
     * Tutorial:        https://www.acwing.com/activity/content/57/                                                                                                             
         __    __________      __ ______  ___ _______                                                                                                                           
        /  \  / ______/ /      \ \| ||  \ | |/  _____|                                                                                                                          
       / /\ \ | |     | |  /\  | || || \ \| || /   ___                                                                                                                          
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |                                                                                                                         
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |                                                                                                                         
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/                                                                                                                         
                                                                                                                                                                                
    acs_11511@acs:~$ pwd                                                                                                                                                        
    /home/acs_11511                                                                                                                                                             
    acs_11511@acs:~$ ls -al                                                                                                                                                     
    total 288                                                                                                                                                                   
    drwxr-xr-x    3 acs_11511 acs_11511   4096 Sep 19 00:14 .                                                                                                                   
    drwxr-xr-x 9002 root      root      266240 Dec 12  2022 ..                                                                                                                  
    -rw-------    1 acs_11511 acs_11511     30 Sep 24 23:14 .bash_history                                                                                                       
    -rw-r--r--    1 acs_11511 acs_11511    220 Dec 11  2022 .bash_logout
    -rw-r--r--    1 acs_11511 acs_11511   3771 Dec 11  2022 .bashrc
    drwx------    2 acs_11511 acs_11511   4096 Sep 18 23:56 .cache
    -rw-r--r--    1 acs_11511 acs_11511    807 Dec 11  2022 .profile
    acs_11511@acs:~$ mkdir .ssh
    acs_11511@acs:~$ ls -al
    total 300
    drwxr-xr-x    4 acs_11511 acs_11511   4096 Sep 24 23:26 .
    drwxr-xr-x 9002 root      root      266240 Dec 12  2022 ..
    -rw-------    1 acs_11511 acs_11511    187 Sep 24 23:23 .bash_history
    -rw-r--r--    1 acs_11511 acs_11511    220 Dec 11  2022 .bash_logout
    -rw-r--r--    1 acs_11511 acs_11511   3771 Dec 11  2022 .bashrc
    drwx------    2 acs_11511 acs_11511   4096 Sep 18 23:56 .cache
    -rw-r--r--    1 acs_11511 acs_11511    807 Dec 11  2022 .profile
    drwxrwxr-x    2 acs_11511 acs_11511   4096 Sep 24 23:26 .ssh
    -rw-------    1 acs_11511 acs_11511   4498 Sep 24 23:26 .viminfo
    acs_11511@acs:~$ cd .ssh/
    acs_11511@acs:~/.ssh$ ls
    acs_11511@acs:~/.ssh$ vim authorized_keys 
    acs_11511@acs:~/.ssh$ ls
    authorized_keys
    acs_11511@acs:~/.ssh$ cat authorized_keys 
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1TTXGpAqNKUt3AbtH85pOEUQTVNBx9dqmXcwUxRd++JaagGY8q1OkTQ/1Aojq/dGmKzM4F1Vdlz61w5QBoGqlqe71OwTLT0Iq4GLSkRNyl5C02vw/INOefRSmAD75RUAisT2Kto++pXJCQ+xJQXejduzjVKY0jZDqT4ijsuRw1tUpx4fM4GGKwfgKyJ5ff1Ucq/9b3m0CCOFdYKQd0pBPL8zVUJhCmSc/pjWTPYqE8zuC0LkvVpnAomeN3TAacJtSwb8lUR4Sb7S1L4PSetdU0O1KX6Rri3BW6+L8CU5q8YPMGrpTAwMZPBK8Xq491mRr0T9OVbPTqcGnUJRHvBjMwbk2MMkOHZj0g/LWkWVT7N9jj7/esdTVfknfBiY9DHQMUu5+eTUOwKQlXTs3L05FXGu5/5YBdH9zdbA4nm5qeLUlyRSPmk2uvE171zGoJ4ExXyLS79wBPKkO033Kkusvicun7bLAaUJugxozBrER1sF2hHZlVFKRoK6TeIPB9O8= acs@80826ae841a9
    acs_11511@acs:~/.ssh$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$ ssh myserver # 此时即可通过密钥直接登录远程服务器,而不需要输入密码
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/.ssh$ 
    

    第二种方式

    acs@80826ae841a9:~/.ssh$ pwd                                                                                                                                                
    /home/acs/.ssh                                                                                                                                                              
    acs@80826ae841a9:~/.ssh$ ls                                                                                                                                                 
    config  known_hosts                                                                                                                                                                                                                                                                                                                                 
    acs@80826ae841a9:~/.ssh$ ssh-keygen # 通过这个命令可以直接创建密钥,命令执行后一直按回车即可
    Generating public/private rsa key pair.                                                                                                                                     
    Enter file in which to save the key (/home/acs/.ssh/id_rsa):                                                                                                                
    Enter passphrase (empty for no passphrase):                                                                                                                                 
    Enter same passphrase again:
    Your identification has been saved in /home/acs/.ssh/id_rsa                                                                                                                 
    Your public key has been saved in /home/acs/.ssh/id_rsa.pub                                                                                                                 
    The key fingerprint is:                                                                                                                                                     
    SHA256:TvU0i26amcku513ja138Hxq8drMJVj+o7VTC1mvNmKM acs@80826ae841a9                                                                                                         
    The key's randomart image is:                                                                                                                                               
    +---[RSA 3072]----+                                                                                                                                                         
    |                 |                                                                                                                                                         
    |                 |                                                                                                                                                         
    |          . o    |                        
    |         . +.o.  |                        
    |        S . o+ = |                        
    |       o .  o =+*|                        
    |        . o oO+*=|                        
    |      ...O o*+B+=|                        
    |       =X .oE*.o=|                        
    +----[SHA256]-----+                        
    acs@80826ae841a9:~/.ssh$ ls # 此时该目录下发现多了两个文件id_rsa、id_rsa.pub。id_rsa为记录私钥信息的文件,id_rsa.pub为记录公钥信息的文件
    config  id_rsa  id_rsa.pub  known_hosts
    acs@80826ae841a9:~/.ssh$ cat id_rsa.pub 
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1TTXGpAqNKUt3AbtH85pOEUQTVNBx9dqmXcwUxRd++JaagGY8q1OkTQ/1Aojq/dGmKzM4F1Vdlz61w5QBoGqlqe71OwTLT0Iq4GLSkRNyl5C02vw/INOefRSmAD75RUAisT2Kto++pXJCQ+xJQXejduzjVKY0jZDqT4ijsuRw1tUpx4fM4GGKwfgKyJ5ff1Ucq/9b3m0CCOFdYKQd0pBPL8zVUJhCmSc/pjWTPYqE8zuC0LkvVpnAomeN3TAacJtSwb8lUR4Sb7S1L4PSetdU0O1KX6Rri3BW6+L8CU5q8YPMGrpTAwMZPBK8Xq491mRr0T9OVbPTqcGnUJRHvBjMwbk2MMkOHZj0g/LWkWVT7N9jj7/esdTVfknfBiY9DHQMUu5+eTUOwKQlXTs3L05FXGu5/5YBdH9zdbA4nm5qeLUlyRSPmk2uvE171zGoJ4ExXyLS79wBPKkO033Kkusvicun7bLAaUJugxozBrER1sF2hHZlVFKRoK6TeIPB9O8= acs@80826ae841a9
    acs@80826ae841a9:~/.ssh$ ssh-copy-id myserver # 通过这个命令,可以直接实现把id_rsa.pub记录的公钥信息,复制到需要登录的远程服务器的~/.ssh/authorized_keys文件中
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/acs/.ssh/id_rsa.pub"                                                                                   
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed                                                          
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys                                                        
    acs_11511@123.57.67.128's password:                                                                                                                                         
                                                                                                                                                                                
    Number of key(s) added: 1                                                                                                                                                   
    
    Now try logging into the machine, with:   "ssh 'myserver'"                            
    and check to make sure that only the key(s) you wanted were added.                    
    
    acs@80826ae841a9:~/.ssh$ 
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$
    acs@80826ae841a9:~/.ssh$ ssh myserver # 此时即可通过密钥直接登录远程服务器,而不需要输入密码
    Welcome to AC Server                       
     * Tutorial:        https://www.acwing.com/activity/content/57/                       
         __    __________      __ ______  ___ _______                                     
        /  \  / ______/ /      \ \| ||  \ | |/  _____|                                    
       / /\ \ | |     | |  /\  | || || \ \| || /   ___                                    
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |                                   
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |                                   
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/                                   
    
    acs_11511@acs:~$ pwd                                                                                                                                                        
    /home/acs_11511
    acs_11511@acs:~$ ls -al
    total 300
    drwxr-xr-x    4 acs_11511 acs_11511   4096 Sep 24 23:49 .
    drwxr-xr-x 9002 root      root      266240 Dec 12  2022 ..
    -rw-------    1 acs_11511 acs_11511    275 Sep 24 23:48 .bash_history
    -rw-r--r--    1 acs_11511 acs_11511    220 Dec 11  2022 .bash_logout
    -rw-r--r--    1 acs_11511 acs_11511   3771 Dec 11  2022 .bashrc
    drwx------    2 acs_11511 acs_11511   4096 Sep 18 23:56 .cache
    -rw-r--r--    1 acs_11511 acs_11511    807 Dec 11  2022 .profile
    drwx------    2 acs_11511 acs_11511   4096 Sep 24 23:49 .ssh
    -rw-------    1 acs_11511 acs_11511   4498 Sep 24 23:26 .viminfo
    acs_11511@acs:~$ cd .ssh/
    acs_11511@acs:~/.ssh$ ls
    authorized_keys
    acs_11511@acs:~/.ssh$ cat authorized_keys 
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1TTXGpAqNKUt3AbtH85pOEUQTVNBx9dqmXcwUxRd++JaagGY8q1OkTQ/1Aojq/dGmKzM4F1Vdlz61w5QBoGqlqe71OwTLT0Iq4GLSkRNyl5C02vw/INOefRSmAD75RUAisT2Kto++pXJCQ+xJQXejduzjVKY0jZDqT4ijsuRw1tUpx4fM4GGKwfgKyJ5ff1Ucq/9b3m0CCOFdYKQd0pBPL8zVUJhCmSc/pjWTPYqE8zuC0LkvVpnAomeN3TAacJtSwb8lUR4Sb7S1L4PSetdU0O1KX6Rri3BW6+L8CU5q8YPMGrpTAwMZPBK8Xq491mRr0T9OVbPTqcGnUJRHvBjMwbk2MMkOHZj0g/LWkWVT7N9jj7/esdTVfknfBiY9DHQMUu5+eTUOwKQlXTs3L05FXGu5/5YBdH9zdbA4nm5qeLUlyRSPmk2uvE171zGoJ4ExXyLS79wBPKkO033Kkusvicun7bLAaUJugxozBrER1sF2hHZlVFKRoK6TeIPB9O8= acs@80826ae841a9 
    acs_11511@acs:~/.ssh$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/.ssh$ 
    
  • 执行命令

    acs@80826ae841a9:~/.ssh$ pwd
    /home/acs/.ssh
    acs@80826ae841a9:~/.ssh$ ls -al
    total 28
    drwx------ 1 acs acs 4096 Sep 24 23:49 .
    drwxr-xr-x 1 acs acs 4096 Sep 24 23:25 ..
    -rw-rw-r-- 1 acs acs   72 Sep 21 00:13 config
    -rw------- 1 acs acs 2602 Sep 24 23:03 id_rsa
    -rw-r--r-- 1 acs acs  570 Sep 24 23:25 id_rsa.pub
    -rw-r--r-- 1 acs acs  222 Sep 19 00:21 known_hosts
    acs@80826ae841a9:~/.ssh$ ssh myserver ls -al # 这个命令相当于,把在远程服务器端执行的ls -al命令的标准输出,重定向到当前终端
    total 300
    drwxr-xr-x    4 acs_11511 acs_11511   4096 Sep 24 23:49 .
    drwxr-xr-x 9002 root      root      266240 Dec 12  2022 ..
    -rw-------    1 acs_11511 acs_11511    320 Sep 25 00:00 .bash_history
    -rw-r--r--    1 acs_11511 acs_11511    220 Dec 11  2022 .bash_logout
    -rw-r--r--    1 acs_11511 acs_11511   3771 Dec 11  2022 .bashrc
    drwx------    2 acs_11511 acs_11511   4096 Sep 18 23:56 .cache
    -rw-r--r--    1 acs_11511 acs_11511    807 Dec 11  2022 .profile
    drwx------    2 acs_11511 acs_11511   4096 Sep 24 23:49 .ssh
    -rw-------    1 acs_11511 acs_11511   4498 Sep 24 23:26 .viminfo
    acs@80826ae841a9:~/.ssh$ ssh myserver 'for ((i=0;i<10;i++)) do echo ${i}; done' # 使用单引号正常显示结果。单引号在远程服务器进行解析,i的值在远程服务器随循环而变化
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    acs@80826ae841a9:~/.ssh$ ssh myserver "for ((i=0;i<10;i++)) do echo ${i}; done" # 使用双引号无法显示结果。双引号在本地服务器进行解析,本地服务器不知道i的值
    
    
    
    
    
    
    
    
    
    
    acs@80826ae841a9:~/.ssh$ 
    

scp传文件

  • 示例一

    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    homework  temp
    acs@80826ae841a9:~$ cd temp/
    acs@80826ae841a9:~/temp$ ls
    temp.cpp  temp.sh  test.sh
    acs@80826ae841a9:~/temp$ cd ..
    acs@80826ae841a9:~$ scp -r temp/ myserver:/home/acs_11511/ # 把当前目录下的temp整个文件夹,传送到远程服务器的/home/acs_11511/目录下
    .main.cpp.swp                                                                                                                             100%   12KB   5.9MB/s   00:00    
    temp.cpp                                                                                                                                  100%  132   156.6KB/s   00:00    
    temp.sh                                                                                                                                   100%   23    24.8KB/s   00:00    
    test.sh                                                                                                                                   100%   68    93.2KB/s   00:00    
    .test.sh.swp                                                                                                                              100%   12KB  12.7MB/s   00:00    
    acs@80826ae841a9:~$ ssh myserver
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ pwd
    /home/acs_11511
    acs_11511@acs:~$ ls
    temp
    acs_11511@acs:~$ cd temp
    acs_11511@acs:~/temp$ ls
    temp.cpp  temp.sh  test.sh
    acs_11511@acs:~/temp$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~$ 
    
  • 示例二

    acs@80826ae841a9:~$ pwd
    /home/acs
    acs@80826ae841a9:~$ ls
    homework
    acs@80826ae841a9:~$ scp -r myserver:/home/acs_11511/temp/ . # 把远程服务器的/home/acs_11511/目录下的temp整个文件夹,传送到当前目录下
    .main.cpp.swp                                                                                                                             100%   12KB  15.9MB/s   00:00    
    temp.cpp                                                                                                                                  100%  132   331.4KB/s   00:00    
    temp.sh                                                                                                                                   100%   23    54.4KB/s   00:00    
    test.sh                                                                                                                                   100%   68   169.8KB/s   00:00    
    .test.sh.swp                                                                                                                              100%   12KB  20.4MB/s   00:00    
    acs@80826ae841a9:~$ ls
    homework  temp
    acs@80826ae841a9:~$ cd temp/
    acs@80826ae841a9:~/temp$ ls
    temp.cpp  temp.sh  test.sh
    acs@80826ae841a9:~/temp$ 
    
  • 示例三

    acs@80826ae841a9:~/temp$ pwd
    /home/acs/temp
    acs@80826ae841a9:~/temp$ ls
    temp.cpp  temp.sh  test.sh
    acs@80826ae841a9:~/temp$ scp -P 22 temp.cpp temp.sh test.sh myserver:/home/acs_11511/ # 把当前目录下的这三个文件,传送到远程服务器的/home/acs_11511/目录下。命令中的"-P 22"可省略,除非想传送指定的端口号
    temp.cpp                                                                                                                                  100%  132    87.0KB/s   00:00    
    temp.sh                                                                                                                                   100%   23    43.4KB/s   00:00    
    test.sh                                                                                                                                   100%   68   158.0KB/s   00:00    
    acs@80826ae841a9:~/temp$ ssh myserver
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ pwd
    /home/acs_11511
    acs_11511@acs:~$ ls
    temp.cpp  temp.sh  test.sh
    acs_11511@acs:~$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~/temp$ 
    
  • 利用scp把.vimrc和.tmux.conf两个配置文件传送到远程服务器的/home/acs_11511/目录下,使远程服务器的vim和tmux的操作及其环境与AC Terminal一样

    acs@80826ae841a9:~$ pwd 
    /home/acs
    acs@80826ae841a9:~$ ls -al
    total 140
    drwxr-xr-x 1 acs  acs   4096 Sep 25 23:58 .
    drwxr-xr-x 1 root root  4096 Jul 23  2021 ..
    -rw------- 1 acs  acs   9903 Sep 25 23:51 .bash_history
    -rw-r--r-- 1 acs  acs    220 Jul 23  2021 .bash_logout
    -rw-r--r-- 1 acs  acs   3831 May 15 16:17 .bashrc
    drwx------ 2 acs  acs   4096 Jul 24 23:17 .cache
    drwx------ 3 acs  acs   4096 Jul 27 00:09 .config
    drwxrwxr-x 1 acs  acs   4096 Jul 27 22:59 .homework
    drwxr-xr-x 1 acs  acs   4096 Jul 23  2021 .ipython
    -rw-r--r-- 1 acs  acs    807 Jul 23  2021 .profile
    -rw------- 1 acs  acs      7 Aug 17  2021 .python_history
    drwx------ 1 acs  acs   4096 Sep 24 23:49 .ssh
    -rw-r--r-- 1 acs  acs      0 Jul 23  2021 .sudo_as_admin_successful
    -rw-r--r-- 1 acs  acs   1569 May 15 16:17 .tmux.conf
    drwxr-xr-x 1 acs  acs   4096 Sep  9  2021 .vim
    -rw------- 1 acs  acs  44297 Sep 25 23:58 .viminfo
    -rw-r--r-- 1 acs  acs   6128 May 15 16:17 .vimrc
    drwxrwxr-x 6 acs  acs   4096 Sep 18 23:42 homework
    drwxrwxr-x 2 acs  acs   4096 Sep 25 23:30 temp
    acs@80826ae841a9:~$ scp .vimrc .tmux.conf myserver:/home/acs_11511/
    .vimrc                                                                                                                                    100% 6128     2.7MB/s   00:00    
    .tmux.conf                                                                                                                                100% 1569     3.5MB/s   00:00    
    acs@80826ae841a9:~$ ssh myserver
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ pwd
    /home/acs_11511
    acs_11511@acs:~$ ls -al
    total 312
    drwxr-xr-x    4 acs_11511 acs_11511   4096 Sep 25 23:58 .
    drwxr-xr-x 9002 root      root      266240 Dec 12  2022 ..
    -rw-------    1 acs_11511 acs_11511    430 Sep 25 23:56 .bash_history
    -rw-r--r--    1 acs_11511 acs_11511    220 Dec 11  2022 .bash_logout
    -rw-r--r--    1 acs_11511 acs_11511   3771 Dec 11  2022 .bashrc
    drwx------    2 acs_11511 acs_11511   4096 Sep 18 23:56 .cache
    -rw-r--r--    1 acs_11511 acs_11511    807 Dec 11  2022 .profile
    drwx------    2 acs_11511 acs_11511   4096 Sep 24 23:49 .ssh
    -rw-r--r--    1 acs_11511 acs_11511   1569 Sep 25 23:58 .tmux.conf
    -rw-------    1 acs_11511 acs_11511   4498 Sep 24 23:26 .viminfo
    -rw-r--r--    1 acs_11511 acs_11511   6128 Sep 25 23:58 .vimrc
    acs_11511@acs:~$ exit
    logout
    Connection to 123.57.67.128 closed.
    acs@80826ae841a9:~$ 
    

git

git的基本概念

  • 工作区:仓库的目录
  • 暂存区:数据暂时存放的区域,即工作区写入版本库前的缓存区
  • 版本库:存放所有已经提交到本地仓库的代码版本
  • 版本库结构:树结构,树中每个节点代表一个代码版本

git的常用命令-本地环境

  • 设置全局用户名
  • 设置全局邮箱地址
acs@80826ae841a9:~$ pwd
/home/acs
acs@80826ae841a9:~$ ls -al
total 148
drwxr-xr-x 1 acs  acs   4096 Sep 26 21:58 .
drwxr-xr-x 1 root root  4096 Jul 23  2021 ..
-rw------- 1 acs  acs  10240 Dec 21 00:05 .bash_history
-rw-r--r-- 1 acs  acs    220 Jul 23  2021 .bash_logout
-rw-r--r-- 1 acs  acs   3831 May 15  2023 .bashrc
drwx------ 2 acs  acs   4096 Jul 24 23:17 .cache
drwx------ 3 acs  acs   4096 Jul 27 00:09 .config
drwxrwxr-x 1 acs  acs   4096 Jul 27 22:59 .homework
drwxr-xr-x 1 acs  acs   4096 Jul 23  2021 .ipython
-rw-r--r-- 1 acs  acs    807 Jul 23  2021 .profile
-rw------- 1 acs  acs      7 Aug 17  2021 .python_history
drwx------ 1 acs  acs   4096 Sep 26 20:50 .ssh
-rw-r--r-- 1 acs  acs      0 Jul 23  2021 .sudo_as_admin_successful
-rw-r--r-- 1 acs  acs   1569 May 15  2023 .tmux.conf
drwxr-xr-x 1 acs  acs   4096 Sep  9  2021 .vim
-rw------- 1 acs  acs  51664 Sep 26 21:58 .viminfo
-rw-r--r-- 1 acs  acs   6128 May 15  2023 .vimrc
drwxrwxr-x 6 acs  acs   4096 Sep 18 23:42 homework
drwxrwxr-x 2 acs  acs   4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ git config --global user.name cgw # 设置全局用户名
acs@80826ae841a9:~$ git config --global user.email qq398156587@163.com # 设置全局邮箱地址
acs@80826ae841a9:~$ ls -al
total 152
drwxr-xr-x 1 acs  acs   4096 Dec 21 23:46 .
drwxr-xr-x 1 root root  4096 Jul 23  2021 ..
-rw------- 1 acs  acs  10240 Dec 21 00:05 .bash_history
-rw-r--r-- 1 acs  acs    220 Jul 23  2021 .bash_logout
-rw-r--r-- 1 acs  acs   3831 May 15  2023 .bashrc
drwx------ 2 acs  acs   4096 Jul 24 23:17 .cache
drwx------ 3 acs  acs   4096 Jul 27 00:09 .config
-rw-rw-r-- 1 acs  acs     48 Dec 21 23:46 .gitconfig # 信息记录在这个文件里面
drwxrwxr-x 1 acs  acs   4096 Jul 27 22:59 .homework
drwxr-xr-x 1 acs  acs   4096 Jul 23  2021 .ipython
-rw-r--r-- 1 acs  acs    807 Jul 23  2021 .profile
-rw------- 1 acs  acs      7 Aug 17  2021 .python_history
drwx------ 1 acs  acs   4096 Sep 26 20:50 .ssh
-rw-r--r-- 1 acs  acs      0 Jul 23  2021 .sudo_as_admin_successful
-rw-r--r-- 1 acs  acs   1569 May 15  2023 .tmux.conf
drwxr-xr-x 1 acs  acs   4096 Sep  9  2021 .vim
-rw------- 1 acs  acs  51664 Sep 26 21:58 .viminfo
-rw-r--r-- 1 acs  acs   6128 May 15  2023 .vimrc
drwxrwxr-x 6 acs  acs   4096 Sep 18 23:42 homework
drwxrwxr-x 2 acs  acs   4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ cat .gitconfig 
[user]
        name = cgw
        email = qq398156587@163.com
acs@80826ae841a9:~$ 
  • 将当前目录配置成git仓库,信息记录在当前目录下隐藏的.git文件夹中
acs@80826ae841a9:~$ pwd   
/home/acs
acs@80826ae841a9:~$ ls -l
total 8
drwxrwxr-x 6 acs acs 4096 Sep 18 23:42 homework
drwxrwxr-x 2 acs acs 4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ mkdir project
acs@80826ae841a9:~$ ls -l
total 12
drwxrwxr-x 6 acs acs 4096 Sep 18 23:42 homework
drwxrwxr-x 2 acs acs 4096 Dec 21 23:52 project
drwxrwxr-x 2 acs acs 4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ cd project/
acs@80826ae841a9:~/project$ ls -al
total 12
drwxrwxr-x 2 acs acs 4096 Dec 21 23:52 .
drwxr-xr-x 1 acs acs 4096 Dec 21 23:52 ..
acs@80826ae841a9:~/project$ git init # 将当前目录配置成git仓库
Initialized empty Git repository in /home/acs/project/.git/
acs@80826ae841a9:~/project$ ls -al
total 16
drwxrwxr-x 3 acs acs 4096 Dec 21 23:52 .
drwxr-xr-x 1 acs acs 4096 Dec 21 23:52 ..
drwxrwxr-x 7 acs acs 4096 Dec 21 23:52 .git # 信息记录在当前目录下隐藏的.git文件夹中
acs@80826ae841a9:~/project$ cd .git/
acs@80826ae841a9:~/project/.git$ ls -l
total 32
-rw-rw-r-- 1 acs acs   23 Dec 21 23:52 HEAD
drwxrwxr-x 2 acs acs 4096 Dec 21 23:52 branches
-rw-rw-r-- 1 acs acs   92 Dec 21 23:52 config
-rw-rw-r-- 1 acs acs   73 Dec 21 23:52 description
drwxrwxr-x 2 acs acs 4096 Dec 21 23:52 hooks
drwxrwxr-x 2 acs acs 4096 Dec 21 23:52 info
drwxrwxr-x 4 acs acs 4096 Dec 21 23:52 objects
drwxrwxr-x 4 acs acs 4096 Dec 21 23:52 refs
acs@80826ae841a9:~/project/.git$ 
  • 查看仓库状态
  • 将某个文件添加到暂存区
  • 将暂存区的内容提交到当前分支
  • 当工作区有改动,暂存区为空时,比较的是“工作区与最后一次提交到版本库的共同文件”的差别;当工作区有改动,暂存区不为空时,比较的是“工作区与暂存区的共同文件”的差别
  • 将某个文件从暂存区中删掉,表示不管理这个文件
  • 将某个文件从暂存区中删掉,但是仍然管理这个文件
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ ls -al
total 16
drwxrwxr-x 3 acs acs 4096 Dec 21 23:52 .
drwxr-xr-x 1 acs acs 4096 Dec 21 23:52 ..
drwxrwxr-x 7 acs acs 4096 Dec 21 23:52 .git
acs@80826ae841a9:~/project$ vim readme.txt
acs@80826ae841a9:~/project$ cat readme.txt 
111
acs@80826ae841a9:~/project$ git status # 查看仓库状态
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        readme.txt

nothing added to commit but untracked files present (use "git add" to track)
acs@80826ae841a9:~/project$ git add readme.txt # 将readme.txt文件添加到暂存区
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   readme.txt

# acs@80826ae841a9:~/project$ git add . # 将所有待加入暂存区的文件加入暂存区
acs@80826ae841a9:~/project$ git commit -m "cgw add readme.txt" # 将暂存区的内容提交到当前分支的下一个结点,可以添加备注信息
[master (root-commit) 76eeda8] cgw add readme.txt
 1 file changed, 1 insertion(+)
 create mode 100644 readme.txt
acs@80826ae841a9:~/project$ vim readme.txt # 修改下readme.txt文件的内容
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
acs@80826ae841a9:~/project$ git status # 查看仓库状态
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")	
acs@80826ae841a9:~/project$ git diff readme.txt # 当工作区有改动,暂存区为空时,比较的是“工作区与最后一次提交到版本库的共同文件”的差别;当工作区有改动,暂存区不为空时,比较的是“工作区与暂存区的共同文件”的差别
diff --git a/readme.txt b/readme.txt
index 58c9bdf..a30a52a 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
 111
+222
acs@80826ae841a9:~/project$ git add readme.txt # 再将修改过内容的readme.txt文件添加到暂存区
acs@80826ae841a9:~/project$ git commit -m "cgw add 222" # 将暂存区的内容提交到当前分支的下一个结点
[master ca82a26] cgw add 222
 1 file changed, 1 deletion(-)
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git add readme.txt # 再将修改过内容的readme.txt文件添加到暂存区
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git rm --cached readme.txt # 将readme.txt文件从暂存区中删掉,表示不管理readme.txt文件
rm 'readme.txt'
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    readme.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        readme.txt

acs@80826ae841a9:~/project$ git add readme.txt # 要管理readme.txt文件时,再把它添加到暂存区即可
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git restore --staged readme.txt # 将readme.txt文件从暂存区中删掉,但是仍然管理readme.txt文件
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git add readme.txt 
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git commit -m "cgw add 333" # 将暂存区的内容提交到当前分支的下一个结点
[master 344061a] cgw add 333
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ 
  • 查看当前分支的所有版本
  • 将代码库回滚到前面的版本
  • 查看HEAD指针的移动历史(包括被回滚的版本)
  • 当工作区有改动,暂存区为空时,将某个文件的修改回滚到“工作区与最后一次提交到版本库的共同文件”的版本;当工作区有改动,暂存区不为空时,将某个文件的修改回滚到“工作区与暂存区的共同文件”的版本
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ ls -l
total 4
-rw-rw-r-- 1 acs acs 12 Dec 30 16:33 readme.txt
acs@80826ae841a9:~/project$ git log # 查看当前分支的所有版本
commit 344061a8b36985b34d2fe2091b90e0447c10bbe1 (HEAD -> master)
Author: cgw <qq398156587@163.com>
Date:   Sat Dec 30 16:49:16 2023 +0800

    cgw add 333

commit ca82a26f5539e6f67888814e7405881bb9156db2
Author: cgw <qq398156587@163.com>
Date:   Sat Dec 30 16:28:25 2023 +0800

    cgw add 222

commit 76eeda86e7387e09ded53023286d6fdb637dcb87
Author: cgw <qq398156587@163.com>
Date:   Sat Dec 30 15:54:56 2023 +0800

    cgw add readme.txt
acs@80826ae841a9:~/project$ git log --pretty=oneline # 查看当前分支的所有版本,可以显示的好看一些
344061a8b36985b34d2fe2091b90e0447c10bbe1 (HEAD -> master) cgw add 333 # 344061a即为版本号
ca82a26f5539e6f67888814e7405881bb9156db2 cgw add 222 # ca82a26即为版本号
76eeda86e7387e09ded53023286d6fdb637dcb87 cgw add readme.txt # 76eeda8即为版本号
acs@80826ae841a9:~/project$ git reset --hard HEAD^^ # 将代码库回滚到前2个版本。有一个^就表示往前回滚1个版本,有两个^就表示往前回滚2个版本,以此类推
HEAD is now at 76eeda8 cgw add readme.txt
# acs@80826ae841a9:~/project$ git reset --hard HEAD~ # 将代码库回滚到前1个版本
# acs@80826ae841a9:~/project$ git reset --hard HEAD~100 # 将代码库回滚到前100个版本
# acs@80826ae841a9:~/project$ git reset --hard 版本号 # 根据版本号,将代码库回滚到指定的版本
acs@80826ae841a9:~/project$ git log # 查看当前分支的所有版本
commit 76eeda86e7387e09ded53023286d6fdb637dcb87 (HEAD -> master)
Author: cgw <qq398156587@163.com>
Date:   Sat Dec 30 15:54:56 2023 +0800

    cgw add readme.txt
acs@80826ae841a9:~/project$ git reflog # 查看HEAD指针的移动历史(包括被回滚的版本)
76eeda8 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^^
344061a HEAD@{1}: commit: cgw add 333
ca82a26 HEAD@{2}: commit: cgw add 222
76eeda8 (HEAD -> master) HEAD@{3}: commit (initial): cgw add readme.txt
acs@80826ae841a9:~/project$ git reset --hard 344061a # 根据版本号,将代码库回滚到指定的版本
HEAD is now at 344061a cgw add 333
acs@80826ae841a9:~/project$ cat readme.txt
111
222
333
acs@80826ae841a9:~/project$ git reset --hard HEAD^^
HEAD is now at 76eeda8 cgw add readme.txt
acs@80826ae841a9:~/project$ cat readme.txt # 可以发现,版本回滚确实生效了
111
acs@80826ae841a9:~/project$ git reset --hard 344061a # 根据版本号,将代码库回滚到指定的版本
HEAD is now at 344061a cgw add 333
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
acs@80826ae841a9:~/project$ git status
On branch master
nothing to commit, working tree clean
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
444
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git restore readme.txt # 当工作区有改动,暂存区为空时,将readme.txt文件的修改回滚到“工作区与最后一次提交到版本库的共同文件”的版本;当工作区有改动,暂存区不为空时,将readme.txt文件的修改回滚到“工作区与暂存区的共同文件”的版本
acs@80826ae841a9:~/project$ git status
On branch master
nothing to commit, working tree clean
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
acs@80826ae841a9:~/project$ touch main.cpp                                                                                                                                   
acs@80826ae841a9:~/project$ ls -l                                                                                                                                            
total 4                                                                                                                                                                      
-rw-rw-r-- 1 acs acs  0 Dec 30 18:33 main.cpp                                                                                                                                
-rw-rw-r-- 1 acs acs 12 Dec 30 17:58 readme.txt                                                                                                                              
acs@80826ae841a9:~/project$ git status                                                                                                                                       
On branch master                           
Untracked files:                           
  (use "git add <file>..." to include in what will be committed)
        main.cpp                           

nothing added to commit but untracked files present (use "git add" to track)
acs@80826ae841a9:~/project$ git add .           
acs@80826ae841a9:~/project$ git status
On branch master                           
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   main.cpp

acs@80826ae841a9:~/project$ vim readme.txt
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
666
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   main.cpp

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   main.cpp
        modified:   readme.txt

acs@80826ae841a9:~/project$ git commit -m "cgw add main.cpp"
[master f8ad874] cgw add main.cpp
 2 files changed, 1 insertion(+)
 create mode 100644 main.cpp
acs@80826ae841a9:~/project$ vim main.cpp 
acs@80826ae841a9:~/project$ cat main.cpp 
111
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ cat readme.txt  
111
222
333
777
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git add main.cpp
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   main.cpp

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git commit -m "cgw save main.cpp"
[master badf2d6] cgw save main.cpp
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git restore readme.txt 
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
666
acs@80826ae841a9:~/project$ git status 
On branch master
nothing to commit, working tree clean
acs@80826ae841a9:~/project$ 
  • 可以把工作区中不小心删除的文件进行恢复,前提是这个文件曾经提交过到版本库中
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ ls -l
total 8
-rw-rw-r-- 1 acs acs  4 Dec 30 18:42 main.cpp
-rw-rw-r-- 1 acs acs 16 Dec 30 18:44 readme.txt
acs@80826ae841a9:~/project$ touch a.txt b.txt
acs@80826ae841a9:~/project$ ls -l
total 8
-rw-rw-r-- 1 acs acs  0 Dec 30 18:54 a.txt
-rw-rw-r-- 1 acs acs  0 Dec 30 18:54 b.txt
-rw-rw-r-- 1 acs acs  4 Dec 30 18:42 main.cpp
-rw-rw-r-- 1 acs acs 16 Dec 30 18:44 readme.txt
acs@80826ae841a9:~/project$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        a.txt
        b.txt

nothing added to commit but untracked files present (use "git add" to track)
acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git commit -m "cgw add a.txt b.txt"
[master 2165e17] cgw add a.txt b.txt
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 b.txt
acs@80826ae841a9:~/project$ git status
On branch master
nothing to commit, working tree clean
acs@80826ae841a9:~/project$ rm a.txt b.txt # 不小心删除的文件
acs@80826ae841a9:~/project$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    a.txt
        deleted:    b.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git add a.txt b.txt # 把这两个文件的修改加入到暂存区中,对文件的删除也属于文件的修改
acs@80826ae841a9:~/project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    a.txt
        deleted:    b.txt

acs@80826ae841a9:~/project$ ls -l
total 8
-rw-rw-r-- 1 acs acs  4 Dec 30 18:42 main.cpp
-rw-rw-r-- 1 acs acs 16 Dec 30 18:44 readme.txt
acs@80826ae841a9:~/project$ git restore --staged a.txt
acs@80826ae841a9:~/project$ git restore a.txt # 通过回滚,可以进行文件的恢复
acs@80826ae841a9:~/project$ ls -l
total 8
-rw-rw-r-- 1 acs acs  0 Dec 30 19:05 a.txt # 可以把a.txt文件恢复
-rw-rw-r-- 1 acs acs  4 Dec 30 18:42 main.cpp
-rw-rw-r-- 1 acs acs 16 Dec 30 18:44 readme.txt
acs@80826ae841a9:~/project$ 
  • 将工作区和暂存区中尚未提交的修改存入栈中

  • 查看栈中所有元素

  • 将栈顶存储的修改恢复到当前分支,同时删除栈顶元素

  • 将栈顶存储的修改恢复到当前分支,但不删除栈顶元素

    git stash apply
    
  • 删除栈顶存储的修改

    git stash drop
    
acs@80826ae841a9:~/project$ git checkout -b dev6
Switched to a new branch 'dev6'
acs@80826ae841a9:~/project$ vim readme.txt # 修改readme.txt文件
acs@80826ae841a9:~/project$ git add readme.txt 
acs@80826ae841a9:~/project$ vim readme.txt # 修改readme.txt文件
acs@80826ae841a9:~/project$ git status
On branch dev6
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

acs@80826ae841a9:~/project$ git stash # 将工作区和暂存区中尚未提交的修改存入栈中
Saved working directory and index state WIP on dev6: d165fff cgw add bbb
acs@80826ae841a9:~/project$ git stash list # 查看栈中所有元素
stash@{0}: WIP on dev6: d165fff cgw add bbb
acs@80826ae841a9:~/project$ git status
On branch dev6
nothing to commit, working tree clean
acs@80826ae841a9:~/project$ git checkout -b dev7 
Switched to a new branch 'dev7'
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ git add readme.txt 
acs@80826ae841a9:~/project$ git commit -m "fff"
[dev7 352675e] fff
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
acs@80826ae841a9:~/project$ git merge dev7
Updating d165fff..352675e
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git branch -d dev7
Deleted branch dev7 (was 352675e).
acs@80826ae841a9:~/project$ git checkout dev6
Switched to branch 'dev6'
acs@80826ae841a9:~/project$ git stash pop # 将栈顶存储的修改恢复到当前分支,同时删除栈顶元素
On branch dev6
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (f7e03d9dab8387e1ef228ff22acfafb409c3c5a3)
acs@80826ae841a9:~/project$ 

git的常用命令-云端环境

需要提前做好的准备工作:

1、先在代码管理平台(https://git.acwing.com/)注册账号,然后登录

2、新建一个项目,项目名字要和本地的项目名字一样

3、然后添加上本地服务器的ssh密钥的公钥信息,此时本地服务器即可通过ssh访问代码管理平台

  • 将本地仓库关联到远程仓库
  • 将本地的某个分支推送到远程仓库
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ ls -al
total 24
drwxrwxr-x 3 acs acs 4096 Dec 30 19:26 .
drwxr-xr-x 1 acs acs 4096 Dec 30 18:43 ..
drwxrwxr-x 8 acs acs 4096 Dec 30 20:36 .git
-rw-rw-r-- 1 acs acs    4 Dec 30 18:42 main.cpp
-rw-rw-r-- 1 acs acs   16 Dec 30 18:44 readme.txt
acs@80826ae841a9:~/project$ git remote add origin git@git.acwing.com:kkoyy459/project.git # 将本地仓库关联到远程仓库
acs@80826ae841a9:~/project$ 
acs@80826ae841a9:~/project$ git push origin master # 将本地的master分支推送到远程仓库
The authenticity of host 'git.acwing.com (47.93.222.173)' can't be established.
ECDSA key fingerprint is SHA256:OxENYBI4n6Nd8yOqmEdMazWuvBldKlP6ZJnOAAbCaeM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes # 输入yes即可
Warning: Permanently added 'git.acwing.com,47.93.222.173' (ECDSA) to the list of known hosts.
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (19/19), 1.60 KiB | 820.00 KiB/s, done.
Total 19 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/project.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
# acs@80826ae841a9:~/project$ git push -u # 将当前分支推送到远程仓库(第一次需要-u以后不需要)
acs@80826ae841a9:~/project$ 
  • 将远程某个仓库下载到当前目录下
acs@80826ae841a9:~$ pwd
/home/acs
acs@80826ae841a9:~$ ls -l 
total 12
drwxrwxr-x 6 acs acs 4096 Sep 18 23:42 homework
drwxrwxr-x 3 acs acs 4096 Dec 30 19:26 project
drwxrwxr-x 2 acs acs 4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ rm -rf project/
acs@80826ae841a9:~$ ls -l
total 8
drwxrwxr-x 6 acs acs 4096 Sep 18 23:42 homework
drwxrwxr-x 2 acs acs 4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ git clone git@git.acwing.com:kkoyy459/project.git # 将远程project仓库下载到当前目录下
Cloning into 'project'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 19 (delta 1), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (19/19), done.
Resolving deltas: 100% (1/1), done.
acs@80826ae841a9:~$ ls -l
total 12
drwxrwxr-x 6 acs acs 4096 Sep 18 23:42 homework
drwxrwxr-x 3 acs acs 4096 Dec 30 20:55 project
drwxrwxr-x 2 acs acs 4096 Sep 25 23:30 temp
acs@80826ae841a9:~$ 

一般默认是master分支,但是实际多人开发项目时,需要创建不同的分支

  • 创建并切换到某个分支
  • 查看所有分支和当前所处分支
  • 切换到某个分支
  • 将某个分支合并到当前分支上
  • 删除某个分支
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ ls -l 
total 8
-rw-rw-r-- 1 acs acs  4 Dec 30 20:55 main.cpp
-rw-rw-r-- 1 acs acs 16 Dec 30 20:55 readme.txt
acs@80826ae841a9:~/project$ git checkout -b dev # 创建并切换到dev这个分支
Switched to a new branch 'dev'
acs@80826ae841a9:~/project$ git branch # 查看所有分支和当前所处分支
* dev
  master
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
666
777
acs@80826ae841a9:~/project$ git status
On branch dev
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git commit -m "cgw add 777" # 将暂存区的内容提交到当前分支的下一个结点
[dev 6bd71bf] cgw add 777
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git branch
* dev
  master
acs@80826ae841a9:~/project$ git checkout master # 切换到master这个分支
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
acs@80826ae841a9:~/project$ git branch
  dev
* master
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
666
acs@80826ae841a9:~/project$ git merge dev # 将dev分支合并到当前分支上
Updating 8c713a9..6bd71bf
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ cat readme.txt 
111
222
333
666
777
acs@80826ae841a9:~/project$ git branch -d dev # 删除dev分支
Deleted branch dev (was 6bd71bf).
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$
acs@80826ae841a9:~/project$
acs@80826ae841a9:~/project$ # ==================================================================
acs@80826ae841a9:~/project$ # 下面是展示合并分支时,发生冲突的情况
acs@80826ae841a9:~/project$ pwd                                                                                                                                              
/home/acs/project                                                                                                                                                            
acs@80826ae841a9:~/project$ ls -l                                                                                                                                            
total 8                                                                                                                                                                      
-rw-rw-r-- 1 acs acs  4 Dec 30 20:55 main.cpp                                                                                                                                
-rw-rw-r-- 1 acs acs 20 Dec 30 21:24 readme.txt                                                                                                                              
acs@80826ae841a9:~/project$ git checkout -b dev2                                                                                                                             
Switched to a new branch 'dev2'                                                                                                                                              
acs@80826ae841a9:~/project$ git branch                                                                                                                                       
* dev2                                                                                                                                                                       
  master                                                                                                                                                                     
acs@80826ae841a9:~/project$ vim readme.txt                                                                                                                                   
acs@80826ae841a9:~/project$ git add .                                                                                                                                        
acs@80826ae841a9:~/project$ git commit -m "cgw add 888"                                                                                                                      
[dev2 222ad45] cgw add 888                                                                                                                                                   
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git checkout master                                                                                                                              
Switched to branch 'master'                                                                                                                                                  
Your branch is ahead of 'origin/master' by 1 commit.                                                                                                                         
  (use "git push" to publish your local commits)                                                                                                                             
acs@80826ae841a9:~/project$ vim readme.txt                                            
acs@80826ae841a9:~/project$ git add .                                                 
acs@80826ae841a9:~/project$ git commit -m "cgw add 999"                                                                                                                      
[master d5ece4c] cgw add 999                                                          
 1 file changed, 1 insertion(+)                                                       
acs@80826ae841a9:~/project$ git merge dev2 # 此时,将dev2分支合并到当前分支上时会报错,因为dev2分支最新的结点和当前分支上最新的结点都是把readme.txt文件进行修改了,会被认为有冲突。因此需要手动确认readme.txt文件后,重新提交到版本库                                          
Auto-merging readme.txt                                                               
CONFLICT (content): Merge conflict in readme.txt                                                                                                                             
Automatic merge failed; fix conflicts and then commit the result.                                                                                                            
acs@80826ae841a9:~/project$ git status                                                
On branch master                           
Your branch is ahead of 'origin/master' by 2 commits.                                                                                                                        
  (use "git push" to publish your local commits)                                                                                                                             

You have unmerged paths.                                                              
  (fix conflicts and run "git commit")                                                
  (use "git merge --abort" to abort the merge)                                                                                                                               

Unmerged paths:                            
  (use "git add <file>..." to mark resolution)                                                                                                                               
        both modified:   readme.txt                                                   

no changes added to commit (use "git add" and/or "git commit -a")                                                                                                            
acs@80826ae841a9:~/project$ vim readme.txt                                            
acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git commit -m "cgw fix conflicts"
[master e2169ff] cgw fix conflicts
acs@80826ae841a9:~/project$ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
acs@80826ae841a9:~/project$ git branch -d dev2
Deleted branch dev2 (was 222ad45).
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$ git push origin master
Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (12/12), 1.03 KiB | 525.00 KiB/s, done.
Total 12 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/project.git
   8c713a9..e2169ff  master -> master
acs@80826ae841a9:~/project$ 
  • 创建某个分支
  • 设置本地的某个分支对应远程仓库的某个分支
  • 删除远程仓库的某个分支
acs@80826ae841a9:~/project$ pwd
/home/acs/project
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$ git branch dev3 # 创建dev3分支
acs@80826ae841a9:~/project$ git checkout dev3
Switched to branch 'dev3'
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git commit -m "aaa"
[dev3 442e9e5] aaa
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git push --set-upstream origin dev3 # 设置本地的dev3分支对应远程仓库的dev3分支
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 293 bytes | 293.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: 
remote: To create a merge request for dev3, visit:
remote:   https://git.acwing.com/kkoyy459/project/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev3
remote: 
To git.acwing.com:kkoyy459/project.git
 * [new branch]      dev3 -> dev3
Branch 'dev3' set up to track remote branch 'dev3' from 'origin'. 
acs@80826ae841a9:~/project$ git branch    
* dev3
  master
acs@80826ae841a9:~/project$ git checkout master # 只有先切换到其它分支,才能把dev3分支删除掉
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
acs@80826ae841a9:~/project$ git branch -d dev3 # 删除dev3分支
warning: deleting branch 'dev3' that has been merged to
         'refs/remotes/origin/dev3', but not yet merged to HEAD.
Deleted branch dev3 (was 442e9e5).
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$ git push -d origin dev3 # 删除远程仓库的dev3分支
To git.acwing.com:kkoyy459/project.git
 - [deleted]         dev3
acs@80826ae841a9:~/project$ 
  • 将远程的某个分支与本地的某个分支对应
  • 将远程仓库的当前分支与本地仓库的当前分支合并
acs@80826ae841a9:~/project$ pwd                                                                                                                                              
/home/acs/project                                                                                                                                                            
acs@80826ae841a9:~/project$ ls -l                                                                                                                                            
total 8                                                                                                                                                                      
-rw-rw-r-- 1 acs acs  4 Dec 30 20:55 main.cpp                                         
-rw-rw-r-- 1 acs acs 28 Dec 31 15:37 readme.txt
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$ git checkout -b dev4
Switched to a new branch 'dev4'
acs@80826ae841a9:~/project$ vim readme.txt 
acs@80826ae841a9:~/project$ git add .
acs@80826ae841a9:~/project$ git commit -m "cgw add bbb" 
[dev4 d165fff] cgw add bbb
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git push --set-upstream origin dev4
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 299.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: 
remote: To create a merge request for dev4, visit:
remote:   https://git.acwing.com/kkoyy459/project/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev4
remote: 
To git.acwing.com:kkoyy459/project.git
 * [new branch]      dev4 -> dev4
Branch 'dev4' set up to track remote branch 'dev4' from 'origin'.
acs@80826ae841a9:~/project$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
acs@80826ae841a9:~/project$ git branch -d dev4
warning: deleting branch 'dev4' that has been merged to
         'refs/remotes/origin/dev4', but not yet merged to HEAD.
Deleted branch dev4 (was d165fff).
acs@80826ae841a9:~/project$ git branch
* master
acs@80826ae841a9:~/project$ git checkout -b dev4
Switched to a new branch 'dev4'
acs@80826ae841a9:~/project$ git branch --set-upstream-to=origin/dev4 dev4 # 将远程的dev4分支与本地的dev4分支对应,前提是本地需要先创建dev4分支
Branch 'dev4' set up to track remote branch 'dev4' from 'origin'.
acs@80826ae841a9:~/project$ git pull # 将远程仓库的当前分支与本地仓库的当前分支合并
Updating e2169ff..d165fff
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
# acs@80826ae841a9:~/project$ git pull origin dev4 # 将远程仓库的dev4分支与本地仓库的当前分支合并
acs@80826ae841a9:~/project$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
acs@80826ae841a9:~/project$ git merge dev4
Updating e2169ff..d165fff
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
acs@80826ae841a9:~/project$ git branch -d dev4
Deleted branch dev4 (was d165fff).
acs@80826ae841a9:~/project$ git push -d origin dev4
To git.acwing.com:kkoyy459/project.git
 - [deleted]         dev4
acs@80826ae841a9:~/project$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 299.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git.acwing.com:kkoyy459/project.git
   e2169ff..d165fff  master -> master
acs@80826ae841a9:~/project$ 
  • 将远程的branch_name分支拉取到本地,不会与本地仓库的当前分支合并

    git checkout -t origin/branch_name
    

thrift

thrift官网:https://thrift.apache.org/

thrift教程:https://thrift.apache.org/tutorial/

  • .thrift文件内容参考:https://raw.githubusercontent.com/apache/thrift/HEAD/tutorial/tutorial.thrift

thrift也被称为RPC(远程函数调用)框架

项目内容

本项目的主要任务是:

  • 实现一个游戏节点(在AC Terminal服务器里)

    • 在调用匹配节点的服务时,此节点为客户端
  • 实现一个匹配节点(在AC Terminal服务器里)

    • 在被游戏节点调用时,此节点为服务端
    • 在调用数据存储节点的服务时,此节点为客户端
  • 还有一个别人已经实现好的数据存储节点(在myserver服务器里,服务端口是9090),我们只需要去调用即可

项目演示

基础版匹配系统

已经提前完成好,但是没有演示出来的工作:

1、已经将当前目录thrift_lesson配置成git仓库

2、已经将本地仓库thrift_lesson关联到远程仓库

3、在当前目录thrift_lesson下,已经新建了三个目录(game、match_system、thrift)和一个文件(readme.md)

acs@80826ae841a9:~/thrift_lesson$ pwd
/home/acs/thrift_lesson
acs@80826ae841a9:~/thrift_lesson$ ls -l
total 16
drwxrwxr-x 2 acs acs 4096 Jan  2 23:24 game # 模拟game端服务器,相当于游戏节点
drwxrwxr-x 3 acs acs 4096 Jan  2 23:58 match_system # 模拟match_system端服务器,相当于匹配节点
-rw-rw-r-- 1 acs acs   41 Jan  2 23:11 readme.md
drwxrwxr-x 2 acs acs 4096 Jan  2 23:47 thrift # 存储所有的thrift的接口
acs@80826ae841a9:~/thrift_lesson$ 
acs@80826ae841a9:~/thrift_lesson$ cd thrift/
acs@80826ae841a9:~/thrift_lesson$ vim match.thrift # 新建一个match.thrift文件,看官网教程模仿
acs@80826ae841a9:~/thrift_lesson/thrift$ ls
match.thrift
acs@80826ae841a9:~/thrift_lesson/thrift$ cat match.thrift 
namespace cpp match_service

struct User {
    1: i32 id,
    2: string name,
    3: i32 score
}

service Match {
    i32 add_user(1: User user, 2: string info), 

    i32 remove_user(1: User user, 2: string info),
}
acs@80826ae841a9:~/thrift_lesson/thrift$ 
acs@80826ae841a9:~/thrift_lesson/thrift$ cd .. 
acs@80826ae841a9:~/thrift_lesson$ ls -l
total 16
drwxrwxr-x 2 acs acs 4096 Jan  2 23:24 game
drwxrwxr-x 3 acs acs 4096 Jan  2 23:58 match_system
-rw-rw-r-- 1 acs acs   41 Jan  2 23:11 readme.md
drwxrwxr-x 2 acs acs 4096 Jan  2 23:47 thrift
acs@80826ae841a9:~/thrift_lesson$ cd match_system/
acs@80826ae841a9:~/thrift_lesson/match_system$ mkdir src
acs@80826ae841a9:~/thrift_lesson/match_system$ ls -l
total 4
drwxrwxr-x 3 acs acs 4096 Jan  2 23:59 src
acs@80826ae841a9:~/thrift_lesson/match_system$ cd src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ thrift -r --gen cpp ../../thrift/match.thrift # 通过刚刚新建的match.thrift文件,生成一个CPP版本的服务器
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 4
drwxrwxr-x 2 acs acs 4096 May  2 20:32 gen-cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd gen-cpp/
acs@80826ae841a9:~/thrift_lesson/match_system/src/gen-cpp$ ls -l
total 52
-rw-rw-r-- 1 acs acs 24115 May  2 20:32 Match.cpp
-rw-rw-r-- 1 acs acs 13108 May  2 20:32 Match.h
-rw-rw-r-- 1 acs acs  1492 May  2 20:32 Match_server.skeleton.cpp # 这个就是用CPP实现match.thrift文件中的thrift接口的一个样例,可以发现,我们定义完thrift接口后,其实不需要手动实现代码
-rw-rw-r-- 1 acs acs  3437 May  2 20:32 match_types.cpp
-rw-rw-r-- 1 acs acs  1688 May  2 20:32 match_types.h
acs@80826ae841a9:~/thrift_lesson/match_system/src/gen-cpp$ cat Match_server.skeleton.cpp 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "Match.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace  ::match_service;

class MatchHandler : virtual public MatchIf {
 public:
  MatchHandler() {
    // Your initialization goes here
  }

  int32_t add_user(const User& user, const std::string& info) {
    // Your implementation goes here
    printf("add_user\n");
  }

  int32_t remove_user(const User& user, const std::string& info) {
    // Your implementation goes here
    printf("remove_user\n");
  }

};

int main(int argc, char **argv) {
  int port = 9090;
  ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
  ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
  ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src/gen-cpp$ cd ..
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 4
drwxrwxr-x 2 acs acs 4096 May  2 20:49 gen-cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ mv gen-cpp/ match_server # 改下文件名
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 4
drwxrwxr-x 2 acs acs 4096 May  2 20:49 match_server # 表示在被游戏节点调用时,此节点为服务端
acs@80826ae841a9:~/thrift_lesson/match_system/src$ mv match_server/Match_server.skeleton.cpp main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 8
-rw-rw-r-- 1 acs acs 1492 May  2 20:58 main.cpp # 具体的业务逻辑,仍然是需要我们手动定义的,因此我们要修改文件的内容
drwxrwxr-x 2 acs acs 4096 May  2 20:49 match_server
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp                                               
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp                                               
// This autogenerated skeleton file illustrates how to build a server.                                        
// You should copy it to another filename to avoid overwriting it.                                            
                                                                                                              
#include "match_server/Match.h"                                                                               
#include <thrift/protocol/TBinaryProtocol.h>                                                                  
#include <thrift/server/TSimpleServer.h>                                                                      
#include <thrift/transport/TServerSocket.h>                                                                   
#include <thrift/transport/TBufferTransports.h>                                                               
                                                                                                              
using namespace ::apache::thrift;                                                                             
using namespace ::apache::thrift::protocol;                                                                   
using namespace ::apache::thrift::transport;                                                                  
using namespace ::apache::thrift::server;                                                                     

using namespace  ::match_service;

class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            return 0;
        }

};

int main(int argc, char **argv) {
    int port = 9090;
    ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
    ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
    ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp match_server/*.cpp # 编译CPP文件
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 800
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o # 编译好的CPP文件
-rw-rw-r-- 1 acs acs   1648 May  2 21:11 main.cpp
-rw-rw-r-- 1 acs acs 443984 May  2 21:14 main.o # 编译好的CPP文件
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o # 编译好的CPP文件
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift # 把所有编译好的CPP文件链接起来,因为这里要用到thrift的动态链接库,所以要加上-lthrift
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1096
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 300352 May  2 21:22 main # 得到一个可执行文件
-rw-rw-r-- 1 acs acs   1648 May  2 21:11 main.cpp
-rw-rw-r-- 1 acs acs 443984 May  2 21:14 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp                                                                                                                               
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp                                                                                                                               
// This autogenerated skeleton file illustrates how to build a server.                                                                                                                        
// You should copy it to another filename to avoid overwriting it.                                                                                                                            
                                                                                                                                                                                              
#include "match_server/Match.h"                                                                                                                                                               
#include <thrift/protocol/TBinaryProtocol.h>                                                                                                                                                  
#include <thrift/server/TSimpleServer.h>                                                                                                                                                      
#include <thrift/transport/TServerSocket.h>                                                                                                                                                   
#include <thrift/transport/TBufferTransports.h>                                                                                                                                               
                                                                                                                                                                                              
#include <iostream>                                                                                                                                                                           
                                                                                                                                                                                              
using namespace ::apache::thrift;                                                                                                                                                             
using namespace ::apache::thrift::protocol;                                                                                                                                                   
using namespace ::apache::thrift::transport;                                                                                                                                                  
using namespace ::apache::thrift::server;                                                                                                                                                     
                                                                                                                                                                                              
using namespace  ::match_service;                                                                                                                                                             
using namespace std;                                                                                                                                                                          
                                                                                                                                                                                              
class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            return 0;
        }

};

int main(int argc, char **argv) {
    int port = 9090;
    ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
    ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
    ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);

    cout << "Start Match Server" << endl;

    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift # 把所有编译好的CPP文件链接起来,因为这里要用到thrift的动态链接库,所以要加上-lthrift
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1100
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 304968 May  2 21:29 main # 得到一个可执行文件
-rw-rw-r-- 1 acs acs   1734 May  2 21:27 main.cpp
-rw-rw-r-- 1 acs acs 445272 May  2 21:28 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 执行一下可执行文件,看看情况
Start Match Server
^C # 键盘按下CTRL + c
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status                                                                                                                                 
On branch master                                                                                                                                                                              
Untracked files:                                                                                                                                                                              
  (use "git add <file>..." to include in what will be committed)                                                                                                                              
        ../                                    

nothing added to commit but untracked files present (use "git add" to track)                                                                                                                  
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add .                                                                                                                                  
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status                                                                                                                                 
On branch master                               
Changes to be committed:                       
  (use "git restore --staged <file>..." to unstage)                                            
        new file:   Match.o                                                                    
        new file:   main                       
        new file:   main.cpp                                                                   
        new file:   main.o                     
        new file:   match_server/Match.cpp                                                     
        new file:   match_server/Match.h                                                       
        new file:   match_server/match_types.cpp                                               
        new file:   match_server/match_types.h                                                 
        new file:   match_types.o                                                              

acs@80826ae841a9:~/thrift_lesson/match_system/src$ git restore --staged *.o # 一般不会把编译好的CPP文件持久化到版本库中                                                                                                                  
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git restore --staged main # 一般不会把可执行文件持久化到版本库中                                                                                                                 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ # 一般只会把原文件持久化到版本库中
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   main.cpp
        new file:   match_server/Match.cpp
        new file:   match_server/Match.h
        new file:   match_server/match_types.cpp
        new file:   match_server/match_types.h

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        Match.o
        main
        main.o
        match_types.o

acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "add match server"
[master 2ae1fe4] add match server
 5 files changed, 1573 insertions(+)
 create mode 100644 match_system/src/main.cpp
 create mode 100644 match_system/src/match_server/Match.cpp
 create mode 100644 match_system/src/match_server/Match.h
 create mode 100644 match_system/src/match_server/match_types.cpp
 create mode 100644 match_system/src/match_server/match_types.h
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (10/10), 7.40 KiB | 1.85 MiB/s, done.
Total 10 (delta 0), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   e23a048..2ae1fe4  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd /home/acs/thrift_lesson/   
acs@80826ae841a9:~/thrift_lesson$ ls -l
total 16
drwxrwxr-x 2 acs acs 4096 Jan  2 23:24 game
drwxrwxr-x 3 acs acs 4096 Jan  2 23:58 match_system
-rw-rw-r-- 1 acs acs   41 Jan  2 23:11 readme.md
drwxrwxr-x 2 acs acs 4096 Jan  2 23:47 thrift
acs@80826ae841a9:~/thrift_lesson$ cd game/
acs@80826ae841a9:~/thrift_lesson/game$ mkdir src
acs@80826ae841a9:~/thrift_lesson/game$ ls -l
total 4
drwxrwxr-x 2 acs acs 4096 May  3 10:24 src
acs@80826ae841a9:~/thrift_lesson/game$ cd src
acs@80826ae841a9:~/thrift_lesson/game/src$ thrift -r --gen py ../../thrift/match.thrift # 通过刚刚新建的match.thrift文件,生成一个Python版本的服务器
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
total 4
drwxrwxr-x 3 acs acs 4096 May  3 10:30 gen-py
acs@80826ae841a9:~/thrift_lesson/game/src$ mv gen-py/ match_client # 改下文件名
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
total 4
drwxrwxr-x 3 acs acs 4096 May  3 10:30 match_client # 表示在调用匹配节点的服务时,此节点为客户端
acs@80826ae841a9:~/thrift_lesson/game/src$ cd match_client/
acs@80826ae841a9:~/thrift_lesson/game/src/match_client$ ls -l
total 4
-rw-rw-r-- 1 acs acs    0 May  3 10:30 __init__.py
drwxrwxr-x 2 acs acs 4096 May  3 10:30 match
acs@80826ae841a9:~/thrift_lesson/game/src/match_client$ cd match/
acs@80826ae841a9:~/thrift_lesson/game/src/match_client/match$ ls -l
total 32
-rwxr-xr-x 1 acs acs  2992 May  3 10:30 Match-remote # 这个文件是用Python实现服务端的一个样例,在这里我们用不到,可以删掉,因为我们需要的是客户端
-rw-rw-r-- 1 acs acs 14947 May  3 10:30 Match.py
-rw-rw-r-- 1 acs acs    43 May  3 10:30 __init__.py
-rw-rw-r-- 1 acs acs   366 May  3 10:30 constants.py
-rw-rw-r-- 1 acs acs  3291 May  3 10:30 ttypes.py
acs@80826ae841a9:~/thrift_lesson/game/src/match_client/match$ rm Match-remote 
acs@80826ae841a9:~/thrift_lesson/game/src/match_client/match$ ls -l
total 28
-rw-rw-r-- 1 acs acs 14947 May  3 10:30 Match.py
-rw-rw-r-- 1 acs acs    43 May  3 10:30 __init__.py
-rw-rw-r-- 1 acs acs   366 May  3 10:30 constants.py
-rw-rw-r-- 1 acs acs  3291 May  3 10:30 ttypes.py
acs@80826ae841a9:~/thrift_lesson/game/src/match_client/match$ cd ../../
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
total 4
drwxrwxr-x 3 acs acs 4096 May  3 10:30 match_client
acs@80826ae841a9:~/thrift_lesson/game/src$ vim client.py # 基于官网给出的用Python实现客户端的样例代码,自己修改实现代码
acs@80826ae841a9:~/thrift_lesson/game/src$ cat client.py 
from match_client.match import Match
from match_client.match.ttypes import User

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol


def main():
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = Match.Client(protocol)

    # Connect!
    transport.open()

    user = User(1, 'yxc', 1500)
    client.add_user(user, "")

    # Close!
    transport.close()

if __name__ == "__main__":
    main()
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
total 8
-rw-rw-r-- 1 acs acs  770 May  3 11:14 client.py
drwxrwxr-x 3 acs acs 4096 May  3 10:30 match_client
acs@80826ae841a9:~/thrift_lesson/game/src$ 
  • 下面打开了两个Terminal

    • 第一个Terminal

      acs@80826ae841a9:~/thrift_lesson/game/src$ pwd
      /home/acs/thrift_lesson/game/src
      acs@80826ae841a9:~/thrift_lesson/game/src$ cd ../../match_system/src/                                                                                                                         
      acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
      total 1100
      -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
      -rwxrwxr-x 1 acs acs 304968 May  2 21:29 main
      -rw-rw-r-- 1 acs acs   1734 May  2 21:27 main.cpp
      -rw-rw-r-- 1 acs acs 445272 May  2 21:28 main.o
      drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
      -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
      acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
      Start Match Server
      add_user # 每启动一次游戏节点的客户端,则会弹出一行这个东西,说明游戏节点的客户端成功调用了匹配节点的服务端
      add_user
      add_user
      ^C
      acs@80826ae841a9:~/thrift_lesson/match_system/src$ 
      
    • 第二个Terminal

      acs@80826ae841a9:~/thrift_lesson/game/src$ pwd
      /home/acs/thrift_lesson/game/src
      acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
      total 8
      -rw-rw-r-- 1 acs acs  770 May  3 11:14 client.py
      drwxrwxr-x 3 acs acs 4096 May  3 10:30 match_client
      acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端
      acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端
      acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端
      acs@80826ae841a9:~/thrift_lesson/game/src$ 
      
acs@80826ae841a9:~/thrift_lesson/game/src$ pwd 
/home/acs/thrift_lesson/game/src
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
total 8
-rw-rw-r-- 1 acs acs  770 May  3 11:14 client.py
drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
acs@80826ae841a9:~/thrift_lesson/game/src$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../
        ../../match_system/src/Match.o
        ../../match_system/src/main
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

nothing added to commit but untracked files present (use "git add" to track)
acs@80826ae841a9:~/thrift_lesson/game/src$ git add .
acs@80826ae841a9:~/thrift_lesson/game/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   client.py
        new file:   match_client/__init__.py
        new file:   match_client/__pycache__/__init__.cpython-38.pyc
        new file:   match_client/match/Match.py
        new file:   match_client/match/__init__.py
        new file:   match_client/match/__pycache__/Match.cpython-38.pyc
        new file:   match_client/match/__pycache__/__init__.cpython-38.pyc
        new file:   match_client/match/__pycache__/ttypes.cpython-38.pyc
        new file:   match_client/match/constants.py
        new file:   match_client/match/ttypes.py

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../match_system/src/Match.o
        ../../match_system/src/main
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

acs@80826ae841a9:~/thrift_lesson/game/src$ git restore --staged *.pyc # 一般不会把.pyc后缀的文件持久化到版本库中,因为这些文件都是中间过程的文件
acs@80826ae841a9:~/thrift_lesson/game/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   client.py
        new file:   match_client/__init__.py
        new file:   match_client/match/Match.py
        new file:   match_client/match/__init__.py
        new file:   match_client/match/constants.py
        new file:   match_client/match/ttypes.py

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        match_client/__pycache__/
        match_client/match/__pycache__/
        ../../match_system/src/Match.o
        ../../match_system/src/main
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

acs@80826ae841a9:~/thrift_lesson/game/src$ git commit -m "add match client"
[master 2bf6f1c] add match client
 6 files changed, 617 insertions(+)
 create mode 100644 game/src/client.py
 create mode 100644 game/src/match_client/__init__.py
 create mode 100644 game/src/match_client/match/Match.py
 create mode 100644 game/src/match_client/match/__init__.py
 create mode 100644 game/src/match_client/match/constants.py
 create mode 100644 game/src/match_client/match/ttypes.py
acs@80826ae841a9:~/thrift_lesson/game/src$ git push origin master
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (12/12), 4.27 KiB | 1.42 MiB/s, done.
Total 12 (delta 0), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   2ae1fe4..2bf6f1c  master -> master
acs@80826ae841a9:~/thrift_lesson/game/src$ 
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l                                               
total 8                                                                                        
-rw-rw-r-- 1 acs acs  770 May  3 11:14 client.py                                               
drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client                                            
acs@80826ae841a9:~/thrift_lesson/game/src$ vim client.py # 修改代码
acs@80826ae841a9:~/thrift_lesson/game/src$ cat client.py                                                                                                                                      
from match_client.match import Match                                                                                                                                                          
from match_client.match.ttypes import User                                                                                                                                                    
                                                                                                                                                                                              
from thrift import Thrift                                                                                                                                                                     
from thrift.transport import TSocket                                                                                                                                                          
from thrift.transport import TTransport                                                                                                                                                       
from thrift.protocol import TBinaryProtocol                                                                                                                                                   
                                                                                                                                                                                              
from sys import stdin


def operate(op, user_id, username, score):
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = Match.Client(protocol)

    # Connect!
    transport.open()

    user = User(user_id, username, score)

    if op == "add":
        client.add_user(user, "")
    elif op == "remove":
        client.remove_user(user, "")

    # Close!
    transport.close()


def main():
    for line in stdin:
        op, user_id, username, score = line.split(' ')
        operate(op, int(user_id), username, int(score))


if __name__ == "__main__":
    main()
acs@80826ae841a9:~/thrift_lesson/game/src$ 

下面打开了两个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/game/src$ pwd
    /home/acs/thrift_lesson/game/src
    acs@80826ae841a9:~/thrift_lesson/game/src$ cd ../../match_system/src/
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1100
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rwxrwxr-x 1 acs acs 304968 May  2 21:29 main
    -rw-rw-r-- 1 acs acs   1734 May  2 21:27 main.cpp
    -rw-rw-r-- 1 acs acs 445272 May  2 21:28 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
    Start Match Server
    add_user
    remove_user
    add_user
    add_user
    remove_user
    
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/game/src$ pwd
    /home/acs/thrift_lesson/game/src
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应
    add 1 yxc 1500
    remove 1 yxc 1500
    add 2 cgw 1000
    add 3 xxx 999
    remove 4 fff 888
    
    
acs@80826ae841a9:~/thrift_lesson/game/src$ pwd                                                                                                                                                
/home/acs/thrift_lesson/game/src                                                                                                                                                              
acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l                                                                                                                                              
total 8                                                                                                                                                                                       
-rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py                                                                                                                                              
drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client                                                                                                                                           
acs@80826ae841a9:~/thrift_lesson/game/src$ git status                                                                                                                                         
On branch master                                                                                                                                                                              
Changes not staged for commit:                                                                                                                                                                
  (use "git add <file>..." to update what will be committed)                                                                                                                                  
  (use "git restore <file>..." to discard changes in working directory)                                                                                                                       
        modified:   client.py                                                                                                                                                                 
                                                                                                                                                                                              
Untracked files:                                                                                                                                                                              
  (use "git add <file>..." to include in what will be committed)                                                                                                                              
        match_client/__pycache__/                                                                                                                                                             
        match_client/match/__pycache__/                                                                                                                                                       
        ../../match_system/src/Match.o                                                                                                                                                        
        ../../match_system/src/main                                                                                                                                                           
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/game/src$ git add .
acs@80826ae841a9:~/thrift_lesson/game/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   client.py
        new file:   match_client/__pycache__/__init__.cpython-38.pyc
        new file:   match_client/match/__pycache__/Match.cpython-38.pyc
        new file:   match_client/match/__pycache__/__init__.cpython-38.pyc
        new file:   match_client/match/__pycache__/ttypes.cpython-38.pyc

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../match_system/src/Match.o
        ../../match_system/src/main
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

acs@80826ae841a9:~/thrift_lesson/game/src$ git restore --staged *.pyc # 一般不会把.pyc后缀的文件持久化到版本库中,因为这些文件都是中间过程的文件
acs@80826ae841a9:~/thrift_lesson/game/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   client.py

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        match_client/__pycache__/
        match_client/match/__pycache__/
        ../../match_system/src/Match.o
        ../../match_system/src/main
        ../../match_system/src/main.o
        ../../match_system/src/match_types.o

acs@80826ae841a9:~/thrift_lesson/game/src$ git commit -m "finish match-client"
[master b9f6107] finish match-client
 1 file changed, 16 insertions(+), 3 deletions(-)
acs@80826ae841a9:~/thrift_lesson/game/src$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 676 bytes | 676.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   2bf6f1c..b9f6107  master -> master
acs@80826ae841a9:~/thrift_lesson/game/src$ 
acs@80826ae841a9:~/thrift_lesson/game/src$ cd ../../match_system/src/
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1100
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 304968 May  2 21:29 main
-rw-rw-r-- 1 acs acs   1734 May  2 21:27 main.cpp
-rw-rw-r-- 1 acs acs 445272 May  2 21:28 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp                                                                                                                               
// This autogenerated skeleton file illustrates how to build a server.                                                                                                                        
// You should copy it to another filename to avoid overwriting it.                                                                                                                            
                                                                                                                                                                                              
#include "match_server/Match.h"                                                                                                                                                               
#include <thrift/protocol/TBinaryProtocol.h>                                                                                                                                                  
#include <thrift/server/TSimpleServer.h>                                                                                                                                                      
#include <thrift/transport/TServerSocket.h>                                                                                                                                                   
#include <thrift/transport/TBufferTransports.h>                                                                                                                                               
                                                                                                                                                                                              
#include <iostream>                                                                                                                                                                           
#include <thread>                                                                                                                                                                             
#include <mutex>                                                                                                                                                                              
#include <condition_variable>                                                                                                                                                                 
#include <queue>                                                                                                                                                                              
#include <vector>                                                                                                                                                                             
                                                                                                                                                                                              
using namespace ::apache::thrift;                                                                                                                                                             
using namespace ::apache::thrift::protocol;                                                                                                                                                   
using namespace ::apache::thrift::transport;                                                                                                                                                  
using namespace ::apache::thrift::server;                                                                                                                                                     
                                                                                                                                                                                              
using namespace  ::match_service;                                                                                                                                                             
using namespace std;                                                                                                                                                                          
                                                                                                                                                                                              
                                                                                                                                                                                              
struct Task
{                                                                                                                                                                                             
    User user;                                                                                                                                                                                
    string type;
};

struct MessageQueue
{
    queue<Task> q;
    mutex m;
    condition_variable cv;
}message_queue;


class Pool
{
    public:
        void save_result(int a, int b)
        {
            printf("Match Result: %d %d\n", a, b);
        }

        void match()
        {
            while (users.size() > 1)
            {
                auto a = users[0], b = users[1];
                users.erase(users.begin());
                users.erase(users.begin());

                save_result(a.id, b.id);
            }
        }

        void add(User user)
        {
            users.push_back(user);
        }

        void remove(User user)
        {
            for (uint32_t i = 0; i < users.size(); i++)
                if (users[i].id == user.id)
                {
                    users.erase(users.begin() + i);
                    break;
                }
        }

    private:
        vector<User> users;
}pool;


class MatchHandler : virtual public MatchIf {
	public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "add"});
            message_queue.cv.notify_all();

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "remove"});
            message_queue.cv.notify_all();

            return 0;
        }

};


void consume_task()
{
    while (true)
    {
        unique_lock<mutex> lck(message_queue.m);
        if (message_queue.q.empty())
        {
            message_queue.cv.wait(lck);
        }
        else
        {
            auto task = message_queue.q.front();
            message_queue.q.pop();
            lck.unlock();

            if (task.type == "add") pool.add(task.user);
            else if (task.type == "remove") pool.remove(task.user);

            pool.match();
        }
    }
}

int main(int argc, char **argv) {
    int port = 9090;
    ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
    ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
    ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);

    cout << "Start Match Server" << endl;

    thread matching_thread(consume_task);
    
    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift -pthread # 把所有编译好的CPP文件链接起来,因为这里要用到thrift和thread的动态链接库,所以要加上-lthrift、-pthread
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

下面打开了两个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd  
    /home/acs/thrift_lesson/match_system/src
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1292
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rwxrwxr-x 1 acs acs 354832 May  4 17:24 main
    -rw-rw-r-- 1 acs acs   3642 May  4 17:10 main.cpp
    -rw-rw-r-- 1 acs acs 592984 May  4 17:17 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
    Start Match Server
    add_user
    add_user
    Match Result: 1 2
    add_user
    remove_user
    add_user
    add_user
    Match Result: 4 5
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../game/src/
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应
    add 1 1 1000
    add 2 2 1000
    add 3 3 1000
    remove 3 3 1000
    add 4 4 1000
    add 5 5 1000
    
    
acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd              
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        main
        main.o
        match_types.o

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        main
        main.o
        match_types.o

acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "match-server version:2.0"
[master 269c41b] match-server version:2.0
 1 file changed, 94 insertions(+)
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.58 KiB | 807.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   b9f6107..269c41b  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../thrift/
acs@80826ae841a9:~/thrift_lesson/thrift$ ls -l
total 4
-rw-rw-r-- 1 acs acs 216 Jan  2 23:47 match.thrift
acs@80826ae841a9:~/thrift_lesson/thrift$ vim save.thrift # 新建一个save.thrift文件,内容为数据存储节点提供给匹配节点进行调用的接口,这个接口别人已经实现好,直接copy别人的内容就行
acs@80826ae841a9:~/thrift_lesson/thrift$ cat save.thrift 
namespace cpp save_service

service Save {

    /**
     * username: myserver的名称
     * password: myserver的密码的md5sum的前8位
     * 用户名密码验证成功会返回0,验证失败会返回1
     * 验证成功后,结果会被保存到myserver:homework/lesson_6/result.txt中
     */
    i32 save_data(1: string username, 2: string password, 3: i32 player1_id, 4: i32 player2_id)
}
acs@80826ae841a9:~/thrift_lesson/thrift$ ls -l
total 8
-rw-rw-r-- 1 acs acs 216 Jan  2 23:47 match.thrift
-rw-rw-r-- 1 acs acs 404 May  5 18:34 save.thrift
acs@80826ae841a9:~/thrift_lesson/thrift$ homework 4 getinfo # 获取myserver的名称和密码
User: acs_11511 # myserver的名称
HostName: 123.57.67.128
Password: ******** # myserver的密码(此处密码已经手动屏蔽)
acs@80826ae841a9:~/thrift_lesson/thrift$ md5sum # 可以把指定的字符串转变成md5sum
******** # 输入myserver的密码,然后键盘按下回车,然后键盘按下CTRL + d
92da7fd2b3421476ef7c0b20e69ddfe0  - # 可以获得myserver的密码的md5sum
acs@80826ae841a9:~/thrift_lesson/thrift$ 
acs@80826ae841a9:~/thrift_lesson/thrift$ cd ../match_system/src/
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1292
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 354832 May  4 17:24 main
-rw-rw-r-- 1 acs acs   3642 May  4 17:10 main.cpp
-rw-rw-r-- 1 acs acs 592984 May  4 17:17 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
acs@80826ae841a9:~/thrift_lesson/match_system/src$ thrift -r --gen cpp ../../thrift/save.thrift # 通过刚刚新建的save.thrift文件,生成一个CPP版本的服务器
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1296
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
drwxrwxr-x 2 acs acs   4096 May  5 19:00 gen-cpp
-rwxrwxr-x 1 acs acs 354832 May  4 17:24 main
-rw-rw-r-- 1 acs acs   3642 May  4 17:10 main.cpp
-rw-rw-r-- 1 acs acs 592984 May  4 17:17 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
acs@80826ae841a9:~/thrift_lesson/match_system/src$ mv gen-cpp/ save_client # 改下文件名
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1296
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 354832 May  4 17:24 main
-rw-rw-r-- 1 acs acs   3642 May  4 17:10 main.cpp
-rw-rw-r-- 1 acs acs 592984 May  4 17:17 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:00 save_client # 表示在调用数据存储节点的服务时,此节点为客户端
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd save_client/
acs@80826ae841a9:~/thrift_lesson/match_system/src/save_client$ ls -l
total 36
-rw-rw-r-- 1 acs acs 14502 May  5 19:00 Save.cpp
-rw-rw-r-- 1 acs acs 11764 May  5 19:00 Save.h
-rw-rw-r-- 1 acs acs  1759 May  5 19:00 Save_server.skeleton.cpp # 这个文件是用CPP实现服务端的一个样例,在这里我们用不到,可以删掉,因为我们需要的是客户端 
-rw-rw-r-- 1 acs acs   468 May  5 19:00 save_types.h
acs@80826ae841a9:~/thrift_lesson/match_system/src/save_client$ rm Save_server.skeleton.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src/save_client$ ls -l
total 32
-rw-rw-r-- 1 acs acs 14502 May  5 19:00 Save.cpp
-rw-rw-r-- 1 acs acs 11764 May  5 19:00 Save.h
-rw-rw-r-- 1 acs acs   468 May  5 19:00 save_types.h
acs@80826ae841a9:~/thrift_lesson/match_system/src/save_client$ 
acs@80826ae841a9:~/thrift_lesson/match_system/src/save_client$ cd ..
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1296
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rwxrwxr-x 1 acs acs 354832 May  4 17:24 main
-rw-rw-r-- 1 acs acs   3642 May  4 17:10 main.cpp
-rw-rw-r-- 1 acs acs 592984 May  4 17:17 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "match_server/Match.h"
#include "save_client/Save.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/transport/TSocket.h>

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace ::match_service;
using namespace ::save_service;
using namespace std;


struct Task
{
    User user;
    string type;
};

struct MessageQueue
{
    queue<Task> q;
    mutex m;
    condition_variable cv;
}message_queue;


class Pool
{
    public:
        void save_result(int a, int b)
        {
            printf("Match Result: %d %d\n", a, b);


            std::shared_ptr<TTransport> socket(new TSocket("123.57.67.128", 9090));
            std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
            std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
            SaveClient client(protocol);

            try {
                transport->open();

                int res = client.save_data("acs_11511", "92da7fd2", a, b);

                if (!res) puts("success");
                else puts("failed");

                transport->close();
            } catch (TException& tx) {
                cout << "ERROR: " << tx.what() << endl;
            }
        }

        void match()
        {
            while (users.size() > 1)
            {
                auto a = users[0], b = users[1];
                users.erase(users.begin());
                users.erase(users.begin());

                save_result(a.id, b.id);
            }
        }

        void add(User user)
        {
            users.push_back(user);
        }

        void remove(User user)
        {
            for (uint32_t i = 0; i < users.size(); i++)
                if (users[i].id == user.id)
                {
                    users.erase(users.begin() + i);
                    break;
                }
        }

    private:
        vector<User> users;
}pool;


class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "add"});
            message_queue.cv.notify_all();

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "remove"});
            message_queue.cv.notify_all();

            return 0;
        }

};


void consume_task()
{
    while (true)
    {
        unique_lock<mutex> lck(message_queue.m);
        if (message_queue.q.empty())
        {
            message_queue.cv.wait(lck);
        }
        else
        {
            auto task = message_queue.q.front();
            message_queue.q.pop();
            lck.unlock();

            if (task.type == "add") pool.add(task.user);
            else if (task.type == "remove") pool.remove(task.user);

            pool.match();
        }
    }
}

int main(int argc, char **argv) {
    int port = 9090;
    ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
    ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
    ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);

    cout << "Start Match Server" << endl;

    thread matching_thread(consume_task);

    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c save_client/*.cpp # 编译CPP文件
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift -pthread # 把所有编译好的CPP文件链接起来,因为这里要用到thrift和thread的动态链接库,所以要加上-lthrift、-pthread
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1708
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 447504 May  5 20:00 main
-rw-rw-r-- 1 acs acs   4435 May  5 19:57 main.cpp
-rw-rw-r-- 1 acs acs 633184 May  5 19:59 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

下面打开了三个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
    /home/acs/thrift_lesson/match_system/src
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1708
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
    -rwxrwxr-x 1 acs acs 447504 May  5 20:00 main
    -rw-rw-r-- 1 acs acs   4435 May  5 19:57 main.cpp
    -rw-rw-r-- 1 acs acs 633184 May  5 19:59 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动 
    Start Match Server
    add_user
    add_user
    Match Result: 3 4
    success
    add_user
    add_user
    Match Result: 5 100
    success
    
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../game/src/
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应
    add 3 3 1000
    add 4 4 1000
    add 5 5 1000
    add 100 100 1000
    
    
    
  • 第三个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ssh myserver 
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ cd homework/lesson_6/
    acs_11511@acs:~/homework/lesson_6$ ls -l
    total 4
    -rw-r--r-- 1 acs_11511 acs_11511 21 May  5 20:12 result.txt
    acs_11511@acs:~/homework/lesson_6$ cat result.txt # 查看数据存储节点是否成功把数据存储下来
    result: 3 4
    177d5bf3
    acs_11511@acs:~/homework/lesson_6$ cat result.txt 
    result: 5 100
    1a639ac5
    acs_11511@acs:~/homework/lesson_6$ 
    
acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1708
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 447504 May  5 20:00 main
-rw-rw-r-- 1 acs acs   4435 May  5 19:57 main.cpp
-rw-rw-r-- 1 acs acs 633184 May  5 19:59 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        Save.o
        main
        main.o
        match_types.o
        save_client/
        ../../thrift/save.thrift

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add ../../game/src/client.py 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add ../../thrift/save.thrift 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add save_client/
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   main.cpp
        new file:   save_client/Save.cpp
        new file:   save_client/Save.h
        new file:   save_client/save_types.h
        new file:   ../../thrift/save.thrift

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        Save.o
        main
        main.o
        match_types.o

acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "implement save-client"
[master ad9345f] implement save-client
 5 files changed, 907 insertions(+), 1 deletion(-)
 create mode 100644 match_system/src/save_client/Save.cpp
 create mode 100644 match_system/src/save_client/Save.h
 create mode 100644 match_system/src/save_client/save_types.h
 create mode 100644 thrift/save.thrift
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (11/11), 6.10 KiB | 2.03 MiB/s, done.
Total 11 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   269c41b..ad9345f  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

优化版匹配系统

acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "match_server/Match.h"
#include "save_client/Save.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/transport/TSocket.h>

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <unistd.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace ::match_service;
using namespace ::save_service;
using namespace std;


struct Task
{
    User user;
    string type;
};

struct MessageQueue
{
    queue<Task> q;
    mutex m;
    condition_variable cv;
}message_queue;


class Pool
{
    public:
        void save_result(int a, int b)
        {
            printf("Match Result: %d %d\n", a, b);


            std::shared_ptr<TTransport> socket(new TSocket("123.57.67.128", 9090));
            std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
            std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
            SaveClient client(protocol);

            try {
                transport->open();

                int res = client.save_data("acs_11511", "92da7fd2", a, b);

                if (!res) puts("success");
                else puts("failed");

                transport->close();
            } catch (TException& tx) {
                cout << "ERROR: " << tx.what() << endl;
            }
        }

        void match()
        {
            while (users.size() > 1)
            {
                sort(users.begin(), users.end(), [&](User& a, User& b){
                    return a.score < b.score;
                        });

                bool flag = true;
                for (uint32_t i = 1; i < users.size(); i++)
                {
                    auto a = users[i - 1], b = users[i];
                    if (b.score - a.score <= 50)
                    {
                        users.erase(users.begin() + i - 1, users.begin() + i + 1);
                        save_result(a.id, b.id);

                        flag = false;
                        break;
                    }
                }
                if (flag) break;
            }
        }

        void add(User user)
        {
            users.push_back(user);
        }

        void remove(User user)
        {
            for (uint32_t i = 0; i < users.size(); i++)
                if (users[i].id == user.id)
                {
                    users.erase(users.begin() + i);
                    break;
                }
        }

    private:
        vector<User> users;
}pool;


class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "add"});
            message_queue.cv.notify_all();

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "remove"});
            message_queue.cv.notify_all();

            return 0;
        }

};


void consume_task()
{
    while (true)
    {
        unique_lock<mutex> lck(message_queue.m);
        if (message_queue.q.empty())
        {
            // message_queue.cv.wait(lck);
            lck.unlock();
            pool.match();
            sleep(1);
        }
        else
        {
            auto task = message_queue.q.front();
            message_queue.q.pop();
            lck.unlock();

            if (task.type == "add") pool.add(task.user);
            else if (task.type == "remove") pool.remove(task.user);

            pool.match();
        }
    }
}

int main(int argc, char **argv) {
    int port = 9090;
    ::std::shared_ptr<MatchHandler> handler(new MatchHandler());
    ::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
    ::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);

    cout << "Start Match Server" << endl;

    thread matching_thread(consume_task);

    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift -pthread # 把所有编译好的CPP文件链接起来,因为这里要用到thrift和thread的动态链接库,所以要加上-lthrift、-pthread
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

下面打开了三个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
    /home/acs/thrift_lesson/match_system/src
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1760
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
    -rwxrwxr-x 1 acs acs 466680 May  5 21:13 main
    -rw-rw-r-- 1 acs acs   5015 May  5 21:11 main.cpp
    -rw-rw-r-- 1 acs acs 671536 May  5 21:11 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
    Start Match Server
    add_user
    add_user
    add_user
    Match Result: 3 1
    success
    add_user
    remove_user
    add_user
    add_user
    Match Result: 6 4
    success
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../game/src/
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应 
    add 1 1 1000
    add 2 2 2000
    add 3 3 999
    add 4 4 3000
    remove 2 2 2000
    add 5 5 1999
    add 6 6 2999
    
    
    
  • 第三个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ssh myserver
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ cd homework/lesson_6/
    acs_11511@acs:~/homework/lesson_6$ ls -l
    total 4
    -rw-r--r-- 1 acs_11511 acs_11511 21 May  5 21:20 result.txt
    acs_11511@acs:~/homework/lesson_6$ cat result.txt # 查看数据存储节点是否成功把数据存储下来
    result: 1 3
    564ad18e
    acs_11511@acs:~/homework/lesson_6$ cat result.txt 
    result: 4 6
    1861a1c1
    acs_11511@acs:~/homework/lesson_6$ 
    
acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd    
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1760
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 466680 May  5 21:13 main
-rw-rw-r-- 1 acs acs   5015 May  5 21:11 main.cpp
-rw-rw-r-- 1 acs acs 671536 May  5 21:11 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        Save.o
        main
        main.o
        match_types.o

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "match server:3.0"
[master 33f4422] match server:3.0
 1 file changed, 22 insertions(+), 5 deletions(-)
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 825 bytes | 412.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   ad9345f..33f4422  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

强化版匹配系统

acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1760
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 466680 May  5 21:13 main
-rw-rw-r-- 1 acs acs   5759 May  5 21:47 main.cpp
-rw-rw-r-- 1 acs acs 671536 May  5 21:11 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "match_server/Match.h"
#include "save_client/Save.h"
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/ThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/transport/TSocket.h>
#include <thrift/TToString.h>

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <unistd.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace ::match_service;
using namespace ::save_service;
using namespace std;


struct Task
{
    User user;
    string type;
};

struct MessageQueue
{
    queue<Task> q;
    mutex m;
    condition_variable cv;
}message_queue;


class Pool
{
    public:
        void save_result(int a, int b)
        {
            printf("Match Result: %d %d\n", a, b);


            std::shared_ptr<TTransport> socket(new TSocket("123.57.67.128", 9090));
            std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
            std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
            SaveClient client(protocol);

            try {
                transport->open();

                int res = client.save_data("acs_11511", "92da7fd2", a, b);

                if (!res) puts("success");
                else puts("failed");

                transport->close();
            } catch (TException& tx) {
                cout << "ERROR: " << tx.what() << endl;
            }
        }

        void match()
        {
            while (users.size() > 1)
            {
                sort(users.begin(), users.end(), [&](User& a, User& b){
                        return a.score < b.score;
                        });

                bool flag = true;
                for (uint32_t i = 1; i < users.size(); i++)
                {
                    auto a = users[i - 1], b = users[i];
                    if (b.score - a.score <= 50)
                    {
                        users.erase(users.begin() + i - 1, users.begin() + i + 1);
                        save_result(a.id, b.id);

                        flag = false;
                        break;
                    }
                }
                if (flag) break;
            }
        }

        void add(User user)
        {
            users.push_back(user);
        }

        void remove(User user)
        {
            for (uint32_t i = 0; i < users.size(); i++)
                if (users[i].id == user.id)
                {
                    users.erase(users.begin() + i);
                    break;
                }
        }

    private:
        vector<User> users;
}pool;


class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "add"});
            message_queue.cv.notify_all();

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "remove"});
            message_queue.cv.notify_all();

            return 0;
        }

};

class MatchCloneFactory : virtual public MatchIfFactory {
    public:
        ~MatchCloneFactory() override = default;
        MatchIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override
        {
            std::shared_ptr<TSocket> sock = std::dynamic_pointer_cast<TSocket>(connInfo.transport);
            /*cout << "Incoming connection\n";
            cout << "\tSocketInfo: "  << sock->getSocketInfo() << "\n";
            cout << "\tPeerHost: "    << sock->getPeerHost() << "\n";
            cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n";
            cout << "\tPeerPort: "    << sock->getPeerPort() << "\n";*/
            return new MatchHandler;
        }
        void releaseHandler(MatchIf* handler) override {
            delete handler;
        }
};

void consume_task()
{
    while (true)
    {
        unique_lock<mutex> lck(message_queue.m);
        if (message_queue.q.empty())
        {
            // message_queue.cv.wait(lck);
            lck.unlock();
            pool.match();
            sleep(1);
        }
        else
        {
            auto task = message_queue.q.front();
            message_queue.q.pop();
            lck.unlock();

            if (task.type == "add") pool.add(task.user);
            else if (task.type == "remove") pool.remove(task.user);

            pool.match();
        }
    }
}

int main(int argc, char **argv) {
    TThreadedServer server(
            std::make_shared<MatchProcessorFactory>(std::make_shared<MatchCloneFactory>()),
            std::make_shared<TServerSocket>(9090), //port
            std::make_shared<TBufferedTransportFactory>(),
            std::make_shared<TBinaryProtocolFactory>());

    cout << "Start Match Server" << endl;

    thread matching_thread(consume_task);

    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift -pthread # 把所有编译好的CPP文件链接起来,因为这里要用到thrift和thread的动态链接库,所以要加上-lthrift、-pthread
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

下面打开了三个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
    /home/acs/thrift_lesson/match_system/src
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1932
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
    -rwxrwxr-x 1 acs acs 544600 May  6 11:04 main
    -rw-rw-r-- 1 acs acs   5763 May  6 11:04 main.cpp
    -rw-rw-r-- 1 acs acs 768440 May  6 11:04 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
    Start Match Server
    add_user
    add_user
    Match Result: 1 2
    success
    
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../game/src/
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应
    add 1 1 1000
    add 2 2 1000
    
    
    
  • 第三个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ssh myserver 
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ cd homework/lesson_6/
    acs_11511@acs:~/homework/lesson_6$ ls -l
    total 4
    -rw-r--r-- 1 acs_11511 acs_11511 21 May  6 14:02 result.txt
    acs_11511@acs:~/homework/lesson_6$ cat result.txt # 查看数据存储节点是否成功把数据存储下来
    result: 1 2
    141da30f
    acs_11511@acs:~/homework/lesson_6$
    
acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd   
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1932
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 544600 May  6 11:04 main
-rw-rw-r-- 1 acs acs   5763 May  6 11:04 main.cpp
-rw-rw-r-- 1 acs acs 768440 May  6 11:04 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        Save.o
        main
        main.o
        match_types.o

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "match server:4.0"
[master e9fcacf] match server:4.0
 1 file changed, 27 insertions(+), 9 deletions(-)
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.04 KiB | 1.04 MiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   33f4422..e9fcacf  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

终极版匹配系统

acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1932
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 544600 May  6 11:04 main
-rw-rw-r-- 1 acs acs   6378 May  6 15:38 main.cpp
-rw-rw-r-- 1 acs acs 768440 May  6 11:04 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ vim main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ cat main.cpp 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "match_server/Match.h"
#include "save_client/Save.h"
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/ThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/transport/TSocket.h>
#include <thrift/TToString.h>

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <unistd.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace ::match_service;
using namespace ::save_service;
using namespace std;


struct Task
{
    User user;
    string type;
};

struct MessageQueue
{
    queue<Task> q;
    mutex m;
    condition_variable cv;
}message_queue;


class Pool
{
    public:
        void save_result(int a, int b)
        {
            printf("Match Result: %d %d\n", a, b);


            std::shared_ptr<TTransport> socket(new TSocket("123.57.67.128", 9090));
            std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
            std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
            SaveClient client(protocol);

            try {
                transport->open();

                int res = client.save_data("acs_11511", "92da7fd2", a, b);

                if (!res) puts("success");
                else puts("failed");

                transport->close();
            } catch (TException& tx) {
                cout << "ERROR: " << tx.what() << endl;
            }
        }

        bool check_match(uint32_t i, uint32_t j)
        {
            auto a = users[i], b = users[j];

            int dt = abs(a.score - b.score);
            int a_max_dif = wt[i] * 50;
            int b_max_dif = wt[j] * 50;

            return dt <= a_max_dif && dt <= b_max_dif;
        }

        void match()
        {
            for (uint32_t i = 0; i < wt.size(); i++)
                wt[i]++;

            while (users.size() > 1)
            {
                bool flag = true;
                for (uint32_t i = 0; i < users.size(); i++)
                {
                    for (uint32_t j = i + 1; j < users.size(); j++)
                    {
                        if (check_match(i, j))
                        {
                            auto a = users[i], b = users[j];
                            users.erase(users.begin() + j);
                            users.erase(users.begin() + i);
                            wt.erase(wt.begin() + j);
                            wt.erase(wt.begin() + i);
                            save_result(a.id, b.id);
                            flag = false;
                            break;
                        }
                    }

                    if (!flag) break;
                }
                if (flag) break;
            }
        }

        void add(User user)
        {
            users.push_back(user);
            wt.push_back(0);
        }

        void remove(User user)
        {
            for (uint32_t i = 0; i < users.size(); i++)
                if (users[i].id == user.id)
                {
                    users.erase(users.begin() + i);
                    wt.erase(wt.begin() + i);
                    break;
                }
        }

    private:
        vector<User> users;
        vector<int> wt;
}pool;


class MatchHandler : virtual public MatchIf {
    public:
        MatchHandler() {
            // Your initialization goes here
        }

        int32_t add_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("add_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "add"});
            message_queue.cv.notify_all();

            return 0;
        }

        int32_t remove_user(const User& user, const std::string& info) {
            // Your implementation goes here
            printf("remove_user\n");

            unique_lock<mutex> lck(message_queue.m);
            message_queue.q.push({user, "remove"});
            message_queue.cv.notify_all();

            return 0;
        }

};

class MatchCloneFactory : virtual public MatchIfFactory {
    public:
        ~MatchCloneFactory() override = default;
        MatchIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override
        {
            std::shared_ptr<TSocket> sock = std::dynamic_pointer_cast<TSocket>(connInfo.transport);
            /*cout << "Incoming connection\n";
            cout << "\tSocketInfo: "  << sock->getSocketInfo() << "\n";
            cout << "\tPeerHost: "    << sock->getPeerHost() << "\n";
            cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n";
            cout << "\tPeerPort: "    << sock->getPeerPort() << "\n";*/
            return new MatchHandler;
        }
        void releaseHandler(MatchIf* handler) override {
            delete handler;
        }
};

void consume_task()
{
    while (true)
    {
        unique_lock<mutex> lck(message_queue.m);
        if (message_queue.q.empty())
        {
            // message_queue.cv.wait(lck);
            lck.unlock();
            pool.match();
            sleep(1);
        }
        else
        {
            auto task = message_queue.q.front();
            message_queue.q.pop();
            lck.unlock();

            if (task.type == "add") pool.add(task.user);
            else if (task.type == "remove") pool.remove(task.user);

        }
    }
}

int main(int argc, char **argv) {
    TThreadedServer server(
            std::make_shared<MatchProcessorFactory>(std::make_shared<MatchCloneFactory>()),
            std::make_shared<TServerSocket>(9090), //port
            std::make_shared<TBufferedTransportFactory>(),
            std::make_shared<TBinaryProtocolFactory>());

    cout << "Start Match Server" << endl;

    thread matching_thread(consume_task);

    server.serve();
    return 0;
}

acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ -c main.cpp # 因为我们修改了main.cpp的内容,所以需要重新编译一次main.cpp
acs@80826ae841a9:~/thrift_lesson/match_system/src$ g++ *.o -o main -lthrift -pthread # 把所有编译好的CPP文件链接起来,因为这里要用到thrift和thread的动态链接库,所以要加上-lthrift、-pthread
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

下面打开了三个Terminal

  • 第一个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd
    /home/acs/thrift_lesson/match_system/src
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
    total 1940
    -rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
    -rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
    -rwxrwxr-x 1 acs acs 544576 May  6 15:41 main
    -rw-rw-r-- 1 acs acs   6378 May  6 15:41 main.cpp
    -rw-rw-r-- 1 acs acs 776648 May  6 15:41 main.o
    drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
    -rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
    drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ./main # 先把匹配节点的服务端启动
    Start Match Server
    add_user
    add_user
    add_user
    add_user
    Match Result: 3 4
    success
    Match Result: 1 2
    success
    
    
    
  • 第二个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ cd ../../game/src/
    acs@80826ae841a9:~/thrift_lesson/game/src$ ls -l
    total 8
    -rw-rw-r-- 1 acs acs 1070 May  3 17:27 client.py
    drwxrwxr-x 4 acs acs 4096 May  3 16:32 match_client
    acs@80826ae841a9:~/thrift_lesson/game/src$ python3 client.py # 启动一次游戏节点的客户端,从终端读入参数,然后观察匹配节点的服务端有什么反应
    add 1 1 1000
    add 2 2 2000
    add 3 3 4000
    add 4 4 4500
    
    
    
  • 第三个Terminal

    acs@80826ae841a9:~/thrift_lesson/match_system/src$ ssh myserver
    Welcome to AC Server
     * Tutorial:        https://www.acwing.com/activity/content/57/
         __    __________      __ ______  ___ _______
        /  \  / ______/ /      \ \| ||  \ | |/  _____|
       / /\ \ | |     | |  /\  | || || \ \| || /   ___
      / /__\ \| |     | | /  \ | || || |\ \ || |   |_ |
     / ______ \ \_____\ \/ /\ \/ /| || | \  || \____| |
    /_/      \_\_______\__/  \__/ |_||_|  \_|\________/
    
    acs_11511@acs:~$ cd homework/lesson_6/
    acs_11511@acs:~/homework/lesson_6$ ls -l
    total 4
    -rw-r--r-- 1 acs_11511 acs_11511 21 May  6 15:46 result.txt
    acs_11511@acs:~/homework/lesson_6$ cat result.txt # 查看数据存储节点是否成功把数据存储下来
    result: 1 2
    141da30f
    acs_11511@acs:~/homework/lesson_6$ 
    
acs@80826ae841a9:~/thrift_lesson/match_system/src$ pwd 
/home/acs/thrift_lesson/match_system/src
acs@80826ae841a9:~/thrift_lesson/match_system/src$ ls -l
total 1940
-rw-rw-r-- 1 acs acs 318344 May  2 21:14 Match.o
-rw-rw-r-- 1 acs acs 282384 May  5 20:00 Save.o
-rwxrwxr-x 1 acs acs 544576 May  6 15:41 main
-rw-rw-r-- 1 acs acs   6378 May  6 15:41 main.cpp
-rw-rw-r-- 1 acs acs 776648 May  6 15:41 main.o
drwxrwxr-x 2 acs acs   4096 May  2 21:09 match_server
-rw-rw-r-- 1 acs acs  42648 May  2 21:14 match_types.o
drwxrwxr-x 2 acs acs   4096 May  5 19:04 save_client
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../game/src/match_client/__pycache__/
        ../../game/src/match_client/match/__pycache__/
        Match.o
        Save.o
        main
        main.o
        match_types.o

no changes added to commit (use "git add" and/or "git commit -a")
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git add main.cpp 
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git commit -m "match server:5.0"
[master d2029c5] match server:5.0
 1 file changed, 32 insertions(+), 13 deletions(-)
acs@80826ae841a9:~/thrift_lesson/match_system/src$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 922 bytes | 461.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
To git.acwing.com:kkoyy459/thrift_lesson.git
   e9fcacf..d2029c5  master -> master
acs@80826ae841a9:~/thrift_lesson/match_system/src$ 

管道、环境变量与常用命令

管道

  • 管道:类似于文件重定向,可以将前一个命令的stdout(标准输出)重定向到下一个命令的stdin(标准输入)

  • 管道命令仅处理stdout(标准输出),会忽略stderr(标准错误输出)

  • 管道右边的命令必须要能接受stdin(标准输入)

  • 多个管道命令可以串联

  • 管道与文件重定向的区别

    • 文件重定向:左边为命令,右边为文件

    • 管道:左右两边均为命令,左边有stdout(标准输出),右边有stdin(标准输入)

例子

acs@80826ae841a9:~/homework/lesson_6/thrift_lesson/game/src$ pwd
/home/acs/homework/lesson_6/thrift_lesson/game/src
acs@80826ae841a9:~/homework/lesson_6/thrift_lesson/game/src$ ls -l
total 8
-rw-rw-r-- 1 acs acs 1068 May  7 10:13 client.py
drwxrwxr-x 4 acs acs 4096 May  6 19:37 match_client
acs@80826ae841a9:~/homework/lesson_6/thrift_lesson/game/src$ find . -name '*.py' | xargs cat | wc -l # 统计当前目录及其子目录下的所有.py文件的总行数
643
acs@80826ae841a9:~/homework/lesson_6/thrift_lesson/game/src$ 

环境变量

在Linux系统中,有的配置信息记录在文件中,有的配置信息记录在环境变量中

  • 环境变量

    • 在Linux系统中,会用很多环境变量来记录配置信息,我们可以通过修改环境变量来方便地修改配置信息
    • 环境变量(类似于全局变量)可以被各个进程访问到
  • 显示环境变量

    • env

      acs@80826ae841a9:~$ pwd
      /home/acs
      acs@80826ae841a9:~$ ls -l
      total 16
      drwxrwxr-x 8 acs acs 4096 May  6 19:04 homework
      drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
      -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
      drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
      acs@80826ae841a9:~$ env # 显示当前的环境变量
      SHELL=/bin/bash
      TMUX=/tmp/tmux-1000/default,870,0
      PWD=/home/acs
      LOGNAME=acs
      MOTD_SHOWN=pam
      HOME=/home/acs
      LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
      SSH_CONNECTION=182.92.217.102 53920 172.17.0.13 22
      LESSCLOSE=/usr/bin/lesspipe %s %s
      TERM=screen
      LESSOPEN=| /usr/bin/lesspipe %s
      USER=acs
      TMUX_PANE=%0
      SHLVL=2
      SSH_CLIENT=182.92.217.102 53920 22
      PATH=/home/acs/.homework:/home/acs/.homework:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
      SSH_TTY=/dev/pts/1
      _=/usr/bin/env
      OLDPWD=/home/acs/homework/lesson_6/thrift_lesson/game/src
      acs@80826ae841a9:~$ 
      
    • set

      acs@80826ae841a9:~$ pwd
      /home/acs
      acs@80826ae841a9:~$ ls -l
      total 16
      drwxrwxr-x 8 acs acs 4096 May  6 19:04 homework
      drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
      -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
      drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
      acs@80826ae841a9:~$ set # 显示当前的Shell变量和函数
      BASH=/bin/bash
      BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
      BASH_ALIASES=()
      BASH_ARGC=([0]="0")
      BASH_ARGV=()
      BASH_CMDS=()
      BASH_LINENO=()
      BASH_SOURCE=()
      BASH_VERSINFO=([0]="5" [1]="0" [2]="17" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
      BASH_VERSION='5.0.17(1)-release'
      COLUMNS=190
      DIRSTACK=()
      EUID=1000
      GROUPS=()
      HISTCONTROL=ignoreboth
      HISTFILE=/home/acs/.bash_history
      HISTFILESIZE=2000
      HISTSIZE=1000
      HOME=/home/acs
      HOSTNAME=80826ae841a9
      HOSTTYPE=x86_64
      IFS=$' \t\n'
      LESSCLOSE='/usr/bin/lesspipe %s %s'
      LESSOPEN='| /usr/bin/lesspipe %s'
      LINES=41
      LOGNAME=acs
      LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
      MACHTYPE=x86_64-pc-linux-gnu
      MAILCHECK=60
      MOTD_SHOWN=pam
      OPTERR=1
      OPTIND=1
      OSTYPE=linux-gnu
      PATH=/home/acs/.homework:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
      PIPESTATUS=([0]="0")
      PPID=853
      PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
      PS2='> '
      PS4='+ '
      PWD=/home/acs
      SHELL=/bin/bash
      SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
      SHLVL=1
      SSH_CLIENT='182.92.217.102 53920 22'
      SSH_CONNECTION='182.92.217.102 53920 172.17.0.13 22'
      SSH_TTY=/dev/pts/1
      TERM=xterm
      UID=1000
      USER=acs
      _=clear
      acs@80826ae841a9:~$ 
      
    • export

      acs@80826ae841a9:~$ pwd
      /home/acs
      acs@80826ae841a9:~$ ls -l
      total 16
      drwxrwxr-x 8 acs acs 4096 May  6 19:04 homework
      drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
      -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
      drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
      acs@80826ae841a9:~$ export # 显示当前已经设置为环境变量的变量列表
      declare -x HOME="/home/acs"
      declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
      declare -x LESSOPEN="| /usr/bin/lesspipe %s"
      declare -x LOGNAME="acs"
      declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
      declare -x MOTD_SHOWN="pam"
      declare -x OLDPWD
      declare -x PATH="/home/acs/.homework:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
      declare -x PWD="/home/acs"
      declare -x SHELL="/bin/bash"
      declare -x SHLVL="1"
      declare -x SSH_CLIENT="182.92.217.102 53920 22"
      declare -x SSH_CONNECTION="182.92.217.102 53920 172.17.0.13 22"
      declare -x SSH_TTY="/dev/pts/1"
      declare -x TERM="xterm"
      declare -x USER="acs"
      acs@80826ae841a9:~$ echo $PATH # 输出环境变量PATH的值
      /home/acs/.homework:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
      acs@80826ae841a9:~$ 
      
  • 环境变量的定义、修改、删除操作,可以参考《shell语法》这一章节中的知识点,这里就不再过多的赘述

  • 将,对环境变量的修改,应用到未来的所有环境下(即持久化)

    • 没有持久化的例子,当你重新打开一个新的Terminal的时候,会发现环境变量HOME的值没有改变

      acs@80826ae841a9:~$ cd ~
      acs@80826ae841a9:~$ pwd
      /home/acs
      acs@80826ae841a9:~$ ls -l
      total 16
      drwxrwxr-x 8 acs acs 4096 May  6 19:04 homework
      drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
      -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
      drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
      acs@80826ae841a9:~$ echo $HOME
      /home/acs
      acs@80826ae841a9:~$ export HOME="/home/acs/homework" # 修改环境变量HOME的值
      acs@80826ae841a9:/home/acs$ cd ~
      acs@80826ae841a9:~$ pwd
      /home/acs/homework
      acs@80826ae841a9:~$ ls -l
      total 24
      drwxrwxr-x 12 acs acs 4096 May  2 15:56 lesson_1
      drwxrwxr-x 12 acs acs 4096 Aug  4  2023 lesson_2
      drwxrwxr-x  7 acs acs 4096 Sep  7  2023 lesson_3
      drwxrwxr-x  7 acs acs 4096 Sep 18  2023 lesson_4
      drwxrwxr-x  3 acs acs 4096 Dec 31 18:44 lesson_5
      drwxrwxr-x  3 acs acs 4096 May  6 19:04 lesson_6
      acs@80826ae841a9:~$ 
      
    • 持久化的例子,当你重新打开一个新的Terminal的时候,会发现环境变量HOME的值已经改变

      acs@80826ae841a9:~$ cd ~
      acs@80826ae841a9:~$ pwd   
      /home/acs
      acs@80826ae841a9:~$ ls -al
      total 172
      drwxr-xr-x 1 acs  acs   4096 May 12 18:37 .
      drwxr-xr-x 1 root root  4096 Jul 23  2021 ..
      -rw------- 1 acs  acs  20722 May 12 18:37 .bash_history
      -rw-r--r-- 1 acs  acs    220 Jul 23  2021 .bash_logout
      -rw-r--r-- 1 acs  acs   3831 May 15  2023 .bashrc
      drwx------ 2 acs  acs   4096 Jul 24  2023 .cache
      drwx------ 3 acs  acs   4096 Jul 27  2023 .config
      -rw-rw-r-- 1 acs  acs     48 Dec 31 20:14 .gitconfig
      drwxrwxr-x 1 acs  acs   4096 Jul 27  2023 .homework
      drwxr-xr-x 1 acs  acs   4096 Jul 23  2021 .ipython
      -rw-r--r-- 1 acs  acs    807 Jul 23  2021 .profile
      -rw------- 1 acs  acs      7 Aug 17  2021 .python_history
      drwx------ 1 acs  acs   4096 Sep 26  2023 .ssh
      -rw-r--r-- 1 acs  acs      0 Jul 23  2021 .sudo_as_admin_successful
      -rw-r--r-- 1 acs  acs   1569 May 15  2023 .tmux.conf
      drwxr-xr-x 1 acs  acs   4096 Sep  9  2021 .vim
      -rw------- 1 acs  acs  49564 May  7 10:17 .viminfo
      -rw-r--r-- 1 acs  acs   6128 May 15  2023 .vimrc
      drwxrwxr-x 8 acs  acs   4096 May  6 19:04 homework
      drwxrwxr-x 2 acs  acs   4096 Sep 25  2023 temp
      -rwxrwxr-x 1 acs  acs    103 Dec 31 21:00 test.sh
      drwxrwxr-x 6 acs  acs   4096 Jan  2 23:24 thrift_lesson
      acs@80826ae841a9:~$ vim .bashrc # 在.bashrc文件的最后一行中,加上export HOME=/home/acs/homework
      acs@80826ae841a9:~$ cat .bashrc 
      # ~/.bashrc: executed by bash(1) for non-login shells.
      # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
      # for examples
      
      # If not running interactively, don't do anything
      case $- in
          *i*) ;;
            *) return;;
      esac
      
      # don't put duplicate lines or lines starting with space in the history.
      # See bash(1) for more options
      HISTCONTROL=ignoreboth
      
      # append to the history file, don't overwrite it
      shopt -s histappend
      
      # for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
      HISTSIZE=1000
      HISTFILESIZE=2000
      
      # check the window size after each command and, if necessary,
      # update the values of LINES and COLUMNS.
      shopt -s checkwinsize
      
      # If set, the pattern "**" used in a pathname expansion context will
      # match all files and zero or more directories and subdirectories.
      #shopt -s globstar
      
      # make less more friendly for non-text input files, see lesspipe(1)
      [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
      
      # set variable identifying the chroot you work in (used in the prompt below)
      if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
          debian_chroot=$(cat /etc/debian_chroot)
      fi
      
      # set a fancy prompt (non-color, unless we know we "want" color)
      case "$TERM" in
          xterm-color|*-256color) color_prompt=yes;;
      esac
      
      # uncomment for a colored prompt, if the terminal has the capability; turned
      # off by default to not distract the user: the focus in a terminal window
      # should be on the output of commands, not on the prompt
      #force_color_prompt=yes
      
      if [ -n "$force_color_prompt" ]; then
          if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
              # We have color support; assume it's compliant with Ecma-48
              # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
              # a case would tend to support setf rather than setaf.)
              color_prompt=yes
          else
              color_prompt=
          fi
      fi
      
      if [ "$color_prompt" = yes ]; then
          PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
      else
          PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
      fi
      unset color_prompt force_color_prompt
      
      # If this is an xterm set the title to user@host:dir
      case "$TERM" in
      xterm*|rxvt*)
          PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
          ;;
      *)
          ;;
      esac
      
      # enable color support of ls and also add handy aliases
      if [ -x /usr/bin/dircolors ]; then
          test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
          alias ls='ls --color=auto'
          #alias dir='dir --color=auto'
          #alias vdir='vdir --color=auto'
      
          alias grep='grep --color=auto'
          alias fgrep='fgrep --color=auto'
          alias egrep='egrep --color=auto'
      fi
      
      # colored GCC warnings and errors
      #export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
      
      # some more ls aliases
      alias ll='ls -alF'
      alias la='ls -A'
      alias l='ls -CF'
      
      # Add an "alert" alias for long running commands.  Use like so:
      #   sleep 10; alert
      alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
      
      # Alias definitions.
      # You may want to put all your additions into a separate file like
      # ~/.bash_aliases, instead of adding them here directly.
      # See /usr/share/doc/bash-doc/examples in the bash-doc package.
      
      if [ -f ~/.bash_aliases ]; then
          . ~/.bash_aliases
      fi
      
      # enable programmable completion features (you don't need to enable
      # this, if it's already enabled in /etc/bash.bashrc and /etc/profile
      # sources /etc/bash.bashrc).
      if ! shopt -oq posix; then
        if [ -f /usr/share/bash-completion/bash_completion ]; then
          . /usr/share/bash-completion/bash_completion
        elif [ -f /etc/bash_completion ]; then
          . /etc/bash_completion
        fi
      fi
      
      export PATH=/home/acs/.homework:$PATH
      alias tmux='tmux -u'
      
      export HOME=/home/acs/homework
      acs@80826ae841a9:~$ source .bashrc # 引入.bashrc文件
      acs@80826ae841a9:/home/acs$ cd ~
      acs@80826ae841a9:~$ pwd 
      /home/acs/homework
      acs@80826ae841a9:~$ ls -al
      total 36
      drwxrwxr-x  8 acs acs 4096 May  6 19:04 .
      drwxr-xr-x  1 acs acs 4096 May 12 18:40 ..
      drwxrwxr-x 12 acs acs 4096 May  2 15:56 lesson_1
      drwxrwxr-x 12 acs acs 4096 Aug  4  2023 lesson_2
      drwxrwxr-x  7 acs acs 4096 Sep  7  2023 lesson_3
      drwxrwxr-x  7 acs acs 4096 Sep 18  2023 lesson_4
      drwxrwxr-x  3 acs acs 4096 Dec 31 18:44 lesson_5
      drwxrwxr-x  3 acs acs 4096 May  6 19:04 lesson_6
      acs@80826ae841a9:~$ 
      
  • 为什么这样做,可以,**将,对环境变量的修改,应用到未来的所有环境下(即持久化)**呢?

    • 因为
      • 每次ssh登陆远程服务器时,都会先启动一个bash命令行给我们
        • 每次启动bash时,都会先执行.bashrc
      • 每次tmux新开一个pane时,都会先启动一个bash命令行给我们
        • 每次启动bash时,都会先执行.bashrc
    • 因此未来所有新开的环境都会先加载我们修改的内容
    • 所以可以实现持久化
  • 常见的环境变量

    • HOME:用户的家目录

      acs@80826ae841a9:~$ echo $HOME
      /home/acs
      acs@80826ae841a9:~$ 
      
    • PATH:用于指定可执行文件的路径

      • 路径与路径之间用冒号隔开
      • 当需要执行某个可执行文件,但某个可执行文件同时出现在多个路径中时,按照从左到右的优先顺序,优先选择第一个路径下的可执行文件进行执行
      acs@80826ae841a9:~$ echo $PATH
      /home/acs/.homework:/home/acs/.homework:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
      acs@80826ae841a9:~$ 
      
    • LD_LIBRARY_PATH:用于指定动态链接库(.so文件)的路径,其内容是以冒号分隔的路径列表**(按照从左到右的优先顺序)**

      acs@80826ae841a9:~$ echo $LD_LIBRARY_PATH
      
      acs@80826ae841a9:~$
      
    • C_INCLUDE_PATH:用于指定C语言的头文件的路径,其内容是以冒号分隔的路径列表**(按照从左到右的优先顺序)**

      acs@80826ae841a9:/$ echo $C_INCLUDE_PATH
      
      acs@80826ae841a9:/$ 
      
    • CPLUS_INCLUDE_PATH:用于指定CPP的头文件的路径,其内容是以冒号分隔的路径列表**(按照从左到右的优先顺序)**

      acs@80826ae841a9:/$ echo $CPLUS_INCLUDE_PATH
      
      acs@80826ae841a9:/$ 
      
    • PYTHONPATH:用于指定Python导入包的路径,其内容是以冒号分隔的路径列表**(按照从左到右的优先顺序)**

      acs@80826ae841a9:/$ echo $PYTHONPATH
      
      acs@80826ae841a9:/$ 
      
    • JAVA_HOME:JDK的安装目录

      acs@80826ae841a9:/$ echo $JAVA_HOME
      
      acs@80826ae841a9:/$ 
      
    • CLASSPATH:用于指定Java导入类的路径,其内容是以冒号分隔的路径列表**(按照从左到右的优先顺序)**

      acs@80826ae841a9:/$ echo $CLASSPATH
      
      acs@80826ae841a9:/$ 
      

常用命令

  • Linux命令非常多,本节讲解几个常用命令。其他命令依赖于大家根据实际操作环境,现用现查即可。

  • 系统状况相关的命令

    • top:查看前几个进程的信息(类似于任务管理器)
      • 打开后,键盘按下M:按使用内存排序
      • 打开后,键盘按下P:按使用CPU排序
      • 打开后,键盘按下q:退出
    • df -h:查看硬盘使用情况
    • free -h:查看内存使用情况
    • du -sh:查看当前目录占用的硬盘空间
    • ps aux:查看所有进程
    • kill -9 pid:杀死进程编号为pid的进程
    • kill -s SIGTERM pid:传递某个具体的信号,杀死进程编号为pid的进程
    • netstat -nt:查看所有网络连接
    • w:列出当前登陆的用户
    • ping www.baidu.com:检查是否连网
  • 文件权限相关的命令

    • chmod +x file:给文件名为file的文件添加可执行权限
    • chmod -x file:去掉文件名为file的文件的可执行权限
    • chmod 777 file:将文件名为file的文件的权限状态改成777
    • chmod 777 file -R:递归修改目录名为file的目录的权限
  • 文件检索相关的命令

    • find path -name ‘*.py’:搜索目录名为path的目录及其子目录下的所有.py文件
    • grep xxx:从stdin(标准输入)中读取若干行内容,如果某行的内容中包含xxx,则输出该行,否则忽略该行,键盘按下CTRL + d即可退出
    • wc:从stdin(标准输入)中直接读取内容,键盘按下CTRL + d即可退出
      • wc file:统计文件名为file的文件中的行数、单词数、字节数
      • wc -l file:统计文件名为file的文件中的行数
      • wc -w file:统计文件名为file的文件中的单词数
      • wc -c file:统计文件名为file的文件中的字节数
    • tree:展示当前目录的文件结构
      • tree path:展示目录名为path的目录的文件结构
      • tree -a:展示隐藏文件
    • ag xxx:从当前目录及其子目录下的所有文件中检索出xxx,并且分别说明是在哪个文件的哪一行,这个命令很好使!!!
    • cut命令,分割内容,从stdin(标准输入)中读取多行数据
      • echo $PATH | cut -d ‘:’ -f 3,5:输出环境变量PATH根据冒号分割后的第3块和第5块的内容
      • echo $PATH | cut -d ‘:’ -f 3-5:输出环境变量PATH根据冒号分割后的第3块到第5块的所有内容
      • echo $PATH | cut -c 3,5:输出环境变量PATH第3个和第5个字符
      • echo $PATH | cut -c 3-5:输出环境变量PATH第3个到第5个的所有字符
    • sort:从stdin(标准输入)中读取若干行内容,将每行内容按字典序排序,键盘按下CTRL + d即可退出
      • sort file:将文件名为file的文件中的每行内容按字典序排序
    • xargs的作用是,将stdin(标准输入)中的内容根据空格或回车分割,分割后的内容作为后面的那个命令的参数
      • find . -name ‘*.py’ | xargs cat | wc -l:统计当前目录及其子目录下的所有.py文件的总行数
  • 查看文件内容相关的命令

    • more file:浏览文件名为file的文件的内容
      • 键盘按下回车,查看下一行
      • 键盘按下空格,查看下一页
      • 键盘按下b,查看上一页
      • 键盘按下q,即可退出
    • less file:浏览文件名为file的文件的内容
      • 键盘按下回车,查看下一行
      • 键盘按下y,查看上一行
      • 键盘按下Page Down,查看下一页
      • 键盘按下Page Up,查看上一页
      • 键盘按下q,即可退出
    • head -3 file:展示文件名为file的文件的前3行内容
      • 支持从stdin(标准输入)中读取内容,键盘按下CTRL + d即可退出
    • tail -3 file:展示文件名为file的文件的末尾3行内容
      • 支持从stdin(标准输入)中读取内容,键盘按下CTRL + d即可退出
  • 用户相关的命令

    • history:展示当前用户的最近1000条的历史操作,内容存放在家目录下的.bash_history文件中
  • 工具相关的命令

    • md5sum:可以从stdin(标准输入)中读取内容,然后键盘按下回车,然后键盘按下CTRL + d,即可得到内容的哈希值

      • md5sum file:得到文件名为file的文件的哈希值
    • time command:统计命令为command的命令的执行时间

    • ipython3:打开一个交互式的python3环境

      • 可以当计算器用

        acs@80826ae841a9:~$ ipython3 
        Python 3.8.10 (default, Jun  2 2021, 10:49:15) 
        Type 'copyright', 'credits' or 'license' for more information
        IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.
        
        In [1]: (3 + 1) * (4 + 2) # 算加法                      
        Out[1]: 24
        
        In [2]: 4 / 3 # 算除法                                  
        Out[2]: 1.3333333333333333
        
        In [3]: 4 // 3 # 算除法,整除                                
        Out[3]: 1
        
        In [4]: 2 ** 3 # 2的3次方                                
        Out[4]: 8
        
        In [5]: 2 ** 64 # 2的64次方                                
        Out[5]: 18446744073709551616
        
        In [6]: 2 ** 128 # 2的128次方,可见是支持高精度的                               
        Out[6]: 340282366920938463463374607431768211456
        
        In [7]: exit                                   
        acs@80826ae841a9:~$ 
        
      • 可以执行shell脚本

        acs@80826ae841a9:~$ ipython3 
        Python 3.8.10 (default, Jun  2 2021, 10:49:15) 
        Type 'copyright', 'credits' or 'license' for more information
        IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.
        
        In [1]: var = 2 ** 111 + 3 ** 78               
        
        In [2]: ! echo $var # 可以执行shell脚本,在ipython3中,!后面会被解析成shell脚本                            
        16425799416689925560045733048873865337
        
        In [3]: exit                                   
        acs@80826ae841a9:~$ 
        
    • watch -n 0.1 command:每隔0.1秒执行一次命令为command的命令,键盘按下CTRL + c即可退出

    • tar命令

      • 可以压缩文件

        acs@80826ae841a9:~$ pwd
        /home/acs
        acs@80826ae841a9:~$ ls -l
        total 16
        drwxrwxr-x 9 acs acs 4096 May 12 19:15 homework
        drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
        -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
        drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
        acs@80826ae841a9:~$ tar -zcvf ttt.tar.gz temp/* # 压缩整个目录
        temp/temp.cpp
        temp/temp.sh
        temp/test.sh
        acs@80826ae841a9:~$ ls -l
        total 20
        drwxrwxr-x 9 acs acs 4096 May 12 19:15 homework
        drwxrwxr-x 2 acs acs 4096 Sep 25  2023 temp
        -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
        drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
        -rw-rw-r-- 1 acs acs  323 May 14 20:10 ttt.tar.gz
        acs@80826ae841a9:~$ 
        
      • 可以解压压缩包

        acs@80826ae841a9:~$ pwd
        /home/acs
        acs@80826ae841a9:~$ ls -l
        total 16
        drwxrwxr-x 9 acs acs 4096 May 12 19:15 homework
        -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
        drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
        -rw-rw-r-- 1 acs acs  323 May 14 20:10 ttt.tar.gz
        acs@80826ae841a9:~$ tar -zxvf ttt.tar.gz # 解压压缩包
        temp/temp.cpp
        temp/temp.sh
        temp/test.sh
        acs@80826ae841a9:~$ ls -l
        total 20
        drwxrwxr-x 9 acs acs 4096 May 12 19:15 homework
        drwxrwxr-x 2 acs acs 4096 May 14 20:13 temp
        -rwxrwxr-x 1 acs acs  103 Dec 31 21:00 test.sh
        drwxrwxr-x 6 acs acs 4096 Jan  2 23:24 thrift_lesson
        -rw-rw-r-- 1 acs acs  323 May 14 20:10 ttt.tar.gz
        acs@80826ae841a9:~$ 
        
    • diff file1 file2:查找文件名为file1的文件与文件名为file2的文件的不同点

  • 安装软件相关的命令

    • sudo command:以root的身份执行命令为command的命令,需要输入当前用户的密码才可以
    • apt-get install xxx:安装名字为xxx的软件
    • pip install xxx --user --upgrade:安装名字为xxx的,–user表示将软件包安装到当前用户的主目录下

租云服务器及配环境

概述

云平台的作用

  • 存放我们的docker容器,让计算跑在云端
    • 我们未来的主要开发环境是在租的云服务器上的docker容器中。因为云服务器上的docker容器相当于是在云服务器里面再建一个虚拟的云服务器,这个虚拟的云服务器,即docker容器,具有独立性,可迁移性!!!
  • 获得公网IP地址,让每个人可以访问到我们的服务

我们未来租的云服务器大致可分为两种

  • 毛坯服务器,可定制化比较强,可以根据自己的需求搭建。一般是各种框架、thrift等会跑在这种需要自己搭建环境的服务器上
  • 精装服务器,已经提供好各种服务,一般都是一些标准化的东西,我们拿来直接用即可。一般是通过socket、http等形式使用服务

任选一个云平台(阿里云,腾讯云,华为云)即可,推荐配置如下

  • CPU:1核,内存:2GB,硬盘空间:25G(后期可以动态扩容,前期配置低一些也没关系)

  • 网络带宽采用按量付费,最大带宽拉满即可(费用取决于用量,与最大带宽无关)

  • 系统版本:Ubuntu 20.04 LTS(推荐用统一版本,避免后期出现配置不兼容的问题)

  • 云服务器一般要开放以下端口

    • 80(HTTP)

    • 443(HTTPS)

    • 22(SSH)

租腾讯云云服务器及配环境

前提:已经租好腾讯云云服务器,且22端口已经开放

  • 在AC Terminal上,通过ssh登录已经租好的腾讯云云服务器

    ssh ubuntu@xxx.xxx.xxx.xxx # 注意,腾讯云云服务器默认分配的是ubuntu用户,而不是root用户。xxx.xxx.xxx.xxx为云服务器的公网IP
    
  • 在腾讯云云服务器上,创建acs用户,并且授予acs用户sudo权限

    sudo adduser acs # 创建acs用户,密码和ubuntu用户的密码一样。因为当前使用的是ubuntu用户,所以最前面要加上sudo
    
    sudo usermod -aG sudo acs # 给acs用户分配sudo权限。因为当前使用的是ubuntu用户,所以最前面要加上sudo
    
  • 在腾讯云云服务器上,切换到acs用户,验证一下是否创建acs用户成功

    su acs
    
  • 在AC Terminal上,配置免密登录方式,登录云服务器(直接进入acs用户),详细操作可以参考《ssh》这一章节中的知识点,这里就不再过多的赘述

  • 在AC Terminal上,通过ssh登录已经租好的腾讯云云服务器

    ssh cgwserver # 登录云服务器(直接进入acs用户)
    
  • 在腾讯云云服务器上,安装tmux

    sudo apt-get update # 安装新软件前先执行这个命令,是为了确保你的系统获取到最新的软件包信息,以便在安装新软件时使用最新版本的软件包,以确保你安装的软件是最新的版本
    
    sudo apt-get install tmux # 安装tmux
    
  • 在AC Terminal上,将AC Terminal的配置传到腾讯云云服务器上,可以让腾讯云云服务器的基本使用环境和AC Terminal一致

    scp .bashrc .vimrc .tmux.conf cgwserver:/home/acs/
    
    
  • 在腾讯云云服务器上,打开tmux(养成好习惯,所有工作都在tmux里进行,防止意外关闭终端后,工作进度丢失),然后在tmux中安装docker(安装教程参考docker官网:Install Docker Engine on Ubuntu | Docker Docs

    • 安装完成后,可以查看下docker的版本

      docker --version # 安装完成后,可以查看下docker的版本
      

Docker

在AC Terminal上,已经有相对应的docker镜像可供我们在云服务器上使用

acs@80826ae841a9:/var/lib/acwing/docker/images$ pwd
/var/lib/acwing/docker/images
acs@80826ae841a9:/var/lib/acwing/docker/images$ ls -lh
total 1.8G
-rw-r--r-- 1 acs acs 1.5G Oct 28  2021 django_lesson_1_0.tar # 这是Django框架课的镜像,报了名才会有
-rw-r--r-- 1 acs acs 301M Oct 18  2021 docker_lesson_1_0.tar # 这是Linux基础课的镜像,报了名才会有
acs@80826ae841a9:/var/lib/acwing/docker/images$ 
  • 在腾讯云云服务器上,为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入到安装docker的过程中自动创建的docker用户组里面(详情请参考docker官网:Linux post-installation steps for Docker Engine | Docker Docs

    sudo usermod -aG docker $USER
    

    执行完此操作后,需要退出服务器,再重新登录回来,才可以省去sudo权限

  • docker

    • 镜像(image),可能会存在多个镜像,这些镜像的相同部分,在docker中只会存储一份,这是docker的空间优化机制
      • 容器(container),用相同的镜像生成的容器的环境都完全一样,容器修改完成后,也可以制作成一个镜像

镜像

  • 拉取一个镜像

    docker pull ubuntu:20.04 # 拉取一个名称为ubuntu,版本号为20.04的镜像。镜像的格式为:名称:版本号
    
  • 查看所有镜像

    docker images
    
  • 删除某个镜像

    • 第一种方法

      docker image rm ubuntu:20.04 # 删除名称为ubuntu,版本号为20.04的镜像
      
    • 第二种方法

      docker rmi ubuntu:20.04 # 删除名称为ubuntu,版本号为20.04的镜像
      
  • 把某个容器制作成一个镜像

    docker commit be9201155c08 cgw_temp:10.01 # 将容器ID为be9201155c08的容器制作成一个名称为cgw_temp,版本号为10.01的镜像
    
  • 将某个镜像导出成存放于本地中的某个文件

    docker save -o ubuntu_20_04.tar ubuntu:20.04 # 将名称为ubuntu,版本号为20.04的镜像,导出成存放于本地中的ubuntu_20_04.tar文件
    
  • 从存放于本地中的某个文件中加载出一个镜像

    docker load -i ubuntu_20_04.tar # 从存放于本地中的ubuntu_20_04.tar文件中加载出一个镜像
    

容器

  • 利用某个镜像创建一个容器

    docker create -it ubuntu:20.04 # 利用名称为ubuntu,版本号为20.04的镜像,创建一个容器
    
  • 查看所有容器

    docker ps -a
    
  • 查看正在运行的容器

    docker ps
    
  • 启动某个容器

    docker start a62bd026d5fb # 启动容器ID为a62bd026d5fb的容器
    
  • 停止某个正在运行的容器

    docker stop a62bd026d5fb # 停止容器ID为a62bd026d5fb的容器
    
  • 重启某个正在运行的容器

    docker restart a62bd026d5fb # 重启容器ID为a62bd026d5fb的容器
    
  • 利用某个镜像创建并启动一个容器

    docker run -itd ubuntu:20.04 # 利用名称为ubuntu,版本号为20.04的镜像,创建并启动一个容器
    
  • 进入正在运行的某个容器

    docker attach be9201155c08 # 进入正在运行的容器ID为be9201155c08的容器
    

    键盘按下CTRL + p,然后键盘按下CTRL + q,退出并挂起当前容器

    键盘按下CTRL + d,退出并停止当前容器

  • 在正在运行的某个容器中执行命令

    docker exec be9201155c08 ls -l # 在正在运行的容器ID为be9201155c08的容器中执行ls -l命令
    
  • 删除已停止的某个容器

    docker rm a62bd026d5fb # 删除已停止的容器ID为a62bd026d5fb的容器
    
  • 删除所有已停止的容器

    docker container prune
    
  • 将已停止的某个容器导出成存放于本地中的某个文件

    docker export -o temp.tar 14185706f3fd # 将已停止的容器ID为14185706f3fd的容器导出成存放于本地中的temp.tar文件
    
  • 从存放于本地中的某个文件中加载出一个容器模板镜像,并将容器模板镜像命名为:名称:版本号

    docker import temp.tar yxchhh:10.07 # 从存放于本地中的temp.tar文件中加载出一个容器模板镜像,并将容器模板镜像命名为:yxchhh:10.07
    
  • 注意,docker save/load与docker export/import的区别

    • docker save/load:会保存完整记录,体积更大
    • docker export/import:会丢弃历史记录和元数据信息,仅保存容器当时的快照状态
  • 查看正在运行的某个容器内的所有进程

    docker top be9201155c08 # 查看正在运行的容器ID为be9201155c08的容器内的所有进程
    
  • 查看所有容器的统计信息,包括CPU、内存、硬盘空间、网络等信息

    docker stats
    

    键盘按下CTRL + c,即可退出

  • 在本地和某个正在运行的容器间复制文件

    • 把存放于本地中的某个文件复制到正在运行的某个容器中

      docker cp temp.tar be9201155c08:/root/ # 把存放于本地中的temp.tar文件复制到正在运行的容器ID为be9201155c08的容器中的/root/路径下
      
    • 把存放于正在运行的某个容器中的某个文件复制到本地中

      docker cp be9201155c08:/root/ . # 把存放于正在运行的容器ID为be9201155c08的容器中的/root目录复制到本地中,这里复制目录时,不需要加-r
      
  • 将某个容器重命名

    docker rename be9201155c08 yxc_lesson # 将容器ID为be9201155c08的容器重命名
    
  • 修改某个容器的内存、CPU等限制

    docker update be9201155c08 --memory 500MB # 将容器ID为be9201155c08的容器的内存上限改为500MB
    

通过ssh登录某个正在运行的容器

前提:在腾讯云云服务器上,已经存在一个名称为docker_lesson,版本号为1.0的镜像

  • 利用名称为docker_lesson,版本号为1.0的镜像,创建并启动一个容器,并且把容器内的22端口映射到本地(即自己租的腾讯云云服务器)的20000端口,容器名称改成my_docker_server

    docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0
    
  • 进入正在运行的容器名称为my_docker_server的容器

    docker attach my_docker_server
    
  • 进入正在运行的容器名称为my_docker_server的容器后,执行如下命令,可以给容器名称为my_docker_server的容器的root用户设置一个密码,密码和本地(云服务器)acs用户的密码一样

    passwd
    
  • 键盘按下CTRL + p,然后键盘按下CTRL + q,退出并挂起当前容器

  • 在腾讯云官网上,给自己租的腾讯云云服务器开放20000端口

  • 进入正在运行的容器名称为my_docker_server的容器后,创建acs用户,并且授予acs用户sudo权限

    adduser acs # 创建acs用户,密码和本地(云服务器)acs用户的密码一样
    
    usermod -aG sudo acs # 给acs用户分配sudo权限
    
  • 在正在运行的容器名称为my_docker_server的容器上,切换到acs用户,验证一下是否创建acs用户成功

    su acs
    
  • 键盘按下CTRL + p,然后键盘按下CTRL + q,退出并挂起当前容器

  • 在AC Terminal上,配置免密登录方式,登录云服务器的正在运行的容器名称为my_docker_server的容器(直接进入acs用户),详细操作可以参考《ssh》这一章节中的知识点,这里就不再过多的赘述

  • 接下来,可以在正在运行的容器名称为my_docker_server的容器上,安装tmux,安装docker等等。也可以在AC Terminal上,将AC Terminal的配置传到腾讯云云服务器的正在运行的容器名称为my_docker_server的容器上,可以让腾讯云云服务器的正在运行的容器名称为my_docker_server的容器的基本使用环境和AC Terminal一致

修改软件源

如果通过apt-get下载软件的速度较慢,可以参考清华大学开源软件镜像站(ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror)中的内容,修改软件源

补充内容

.vimrc

acs@80826ae841a9:~$ cat .vimrc 
" An example for a vimrc file.
"
" To use it, copy it to
"     for Unix and OS/2:  ~/.vimrc
"             for Amiga:  s:.vimrc
"  for MS-DOS and Win32:  $VIM\_vimrc
"           for OpenVMS:  sys$login:.vimrc

" When started as "evim", evim.vim will already have done these settings.
if v:progname =~? "evim"
  finish
endif

" Use Vim settings, rather then Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
set nocompatible

" allow backspacing over everything in insert mode
set backspace=indent,eol,start

if has("vms")
  set nobackup          " do not keep a backup file, use versions instead
else
  set backup            " keep a backup file
endif
set history=50          " keep 50 lines of command line history
set ruler               " show the cursor position all the time
set showcmd             " display incomplete commands
set incsearch           " do incremental searching
"==========================================================================
"My Setting-sunshanlu
"==========================================================================
vmap <leader>y :w! /tmp/vitmp<CR>
nmap <leader>p :r! cat /tmp/vitmp<CR>

"语法高亮
syntax enable
syntax on
"显示行号
set nu

"修改默认注释颜色
"hi Comment ctermfg=DarkCyan
"允许退格键删除
"set backspace=2
"启用鼠标
set mouse=a
set selection=exclusive
set selectmode=mouse,key
"按C语言格式缩进
set cindent
set autoindent
set smartindent
set shiftwidth=4

" 允许在有未保存的修改时切换缓冲区
"set hidden

" 设置无备份文件
set writebackup
set nobackup

"显示括号匹配
set showmatch
"括号匹配显示时间为1(单位是十分之一秒)
set matchtime=5
"显示当前的行号列号:
set ruler
"在状态栏显示正在输入的命令
set showcmd

set foldmethod=syntax
"默认情况下不折叠
set foldlevel=100
" 开启状态栏信息
set laststatus=2
" 命令行的高度,默认为1,这里设为2
set cmdheight=2


" 显示Tab符,使用一高亮竖线代替
set list
"set listchars=tab:\|\ ,
set listchars=tab:>-,trail:-


"侦测文件类型
filetype on
"载入文件类型插件
filetype plugin on
"为特定文件类型载入相关缩进文件
filetype indent on
" 启用自动补全
filetype plugin indent on 


"设置编码自动识别, 中文引号显示
filetype on "打开文件类型检测
"set fileencodings=euc-cn,ucs-bom,utf-8,cp936,gb2312,gb18030,gbk,big5,euc-jp,euc-kr,latin1
set fileencodings=utf-8,gb2312,gbk,gb18030
"这个用能很给劲,不管encoding是什么编码,都能将文本显示汉字
"set termencoding=gb2312
set termencoding=utf-8
"新建文件使用的编码
set fileencoding=utf-8
"set fileencoding=gb2312
"用于显示的编码,仅仅是显示
set encoding=utf-8
"set encoding=utf-8
"set encoding=euc-cn
"set encoding=gbk
"set encoding=gb2312
"set ambiwidth=double
set fileformat=unix


"设置高亮搜索
set hlsearch
"在搜索时,输入的词句的逐字符高亮
set incsearch

" 着色模式
set t_Co=256
"colorscheme wombat256mod
"colorscheme gardener
"colorscheme elflord
colorscheme desert
"colorscheme evening
"colorscheme darkblue
"colorscheme torte
"colorscheme default

" 字体 && 字号
set guifont=Monaco:h10
"set guifont=Consolas:h10

" :LoadTemplate       根据文件后缀自动加载模板
"let g:template_path='/home/ruchee/.vim/template/'

" :AuthorInfoDetect   自动添加作者、时间等信息,本质是NERD_commenter && authorinfo的结合
""let g:vimrc_author='sunshanlu'
""let g:vimrc_email='sunshanlu@baidu.com'
""let g:vimrc_homepage='http://www.sunshanlu.com'
"
"
" Ctrl + E            一步加载语法模板和作者、时间信息
""map <c-e> <ESC>:AuthorInfoDetect<CR><ESC>Gi
""imap <c-e> <ESC>:AuthorInfoDetect<CR><ESC>Gi
""vmap <c-e> <ESC>:AuthorInfoDetect<CR><ESC>Gi



" ======= 引号 && 括号自动匹配 ======= "
"
":inoremap ( ()<ESC>i

":inoremap ) <c-r>=ClosePair(')')<CR>
"
":inoremap { {}<ESC>i
"
":inoremap } <c-r>=ClosePair('}')<CR>
"
":inoremap [ []<ESC>i
"
":inoremap ] <c-r>=ClosePair(']')<CR>
"
":inoremap < <><ESC>i
"
":inoremap > <c-r>=ClosePair('>')<CR>
"
"":inoremap " ""<ESC>i
"
":inoremap ' ''<ESC>i
"
":inoremap ` ``<ESC>i
"
":inoremap * **<ESC>i

" 每行超过80个的字符用下划线标示
""au BufRead,BufNewFile *.s,*.asm,*.h,*.c,*.cpp,*.java,*.cs,*.lisp,*.el,*.erl,*.tex,*.sh,*.lua,*.pl,*.php,*.tpl,*.py,*.rb,*.erb,*.vim,*.js,*.jade,*.coffee,*.css,*.xml,*.html,*.shtml,*.xhtml Underlined /.\%81v/
"
"
" For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries
" let &guioptions = substitute(&guioptions, "t", "", "g")

" Don't use Ex mode, use Q for formatting
map Q gq

" This is an alternative that also works in block mode, but the deleted
" text is lost and it only works for putting the current register.
"vnoremap p "_dp

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
  syntax on
  set hlsearch
endif

" Only do this part when compiled with support for autocommands.
if has("autocmd")

  " Enable file type detection.
  " Use the default filetype settings, so that mail gets 'tw' set to 72,
  " 'cindent' is on in C files, etc.
  " Also load indent files, to automatically do language-dependent indenting.
  filetype plugin indent on

  " Put these in an autocmd group, so that we can delete them easily.
  augroup vimrcEx
  au!

  " For all text files set 'textwidth' to 80 characters.
  autocmd FileType text setlocal textwidth=80

  " When editing a file, always jump to the last known cursor position.
  " Don't do it when the position is invalid or when inside an event handler
  " (happens when dropping a file on gvim).
  autocmd BufReadPost *
    \ if line("'\"") > 0 && line("'\"") <= line("$") |
    \   exe "normal g`\"" |
    \ endif

  augroup END

else

  set autoindent                " always set autoindenting on

endif " has("autocmd")

" 增加鼠标行高亮
set cursorline
hi CursorLine  cterm=NONE   ctermbg=darkred ctermfg=white

" 设置tab是四个空格
set ts=4
set expandtab

" 主要给Tlist使用
let Tlist_Exit_OnlyWindow = 1
let Tlist_Auto_Open = 1
acs@80826ae841a9:~$ 

.tmux.conf

acs@80826ae841a9:~$ cat .tmux.conf 
set-option -g status-keys vi
setw -g mode-keys vi

setw -g monitor-activity on

# setw -g c0-change-trigger 10
# setw -g c0-change-interval 100

# setw -g c0-change-interval 50
# setw -g c0-change-trigger  75


set-window-option -g automatic-rename on
set-option -g set-titles on
set -g history-limit 100000

#set-window-option -g utf8 on

# set command prefix
set-option -g prefix C-a
unbind-key C-b
bind-key C-a send-prefix

bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

bind < resize-pane -L 7
bind > resize-pane -R 7
bind - resize-pane -D 7
bind + resize-pane -U 7


bind-key -n M-l next-window
bind-key -n M-h previous-window



set -g status-interval 1
# status bar
set -g status-bg black
set -g status-fg blue


#set -g status-utf8 on
set -g status-justify centre
set -g status-bg default
set -g status-left " #[fg=green]#S@#H #[default]"
set -g status-left-length 20


# mouse support
# for tmux 2.1
# set -g mouse-utf8 on
set -g mouse on
#
# for previous version
#set -g mode-mouse on
#set -g mouse-resize-pane on
#set -g mouse-select-pane on
#set -g mouse-select-window on


#set -g status-right-length 25
set -g status-right "#[fg=green]%H:%M:%S #[fg=magenta]%a %m-%d #[default]"

# fix for tmux 1.9
bind '"' split-window -vc "#{pane_current_path}"
bind '%' split-window -hc "#{pane_current_path}"
bind 'c' new-window -c "#{pane_current_path}"

# run-shell "powerline-daemon -q"

# vim: ft=conf
acs@80826ae841a9:~$ 

.bashrc

acs@80826ae841a9:~$ cat .bashrc 
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        # We have color support; assume it's compliant with Ecma-48
        # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
        # a case would tend to support setf rather than setaf.)
        color_prompt=yes
    else
        color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

export PATH=/home/acs/.homework:$PATH
alias tmux='tmux -u'

export PATH=/home/acs/homework/lesson_7/homework_0:$PATH
acs@80826ae841a9:~$ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值