目录
-
1.Linux常用文件管理命令
-
2.tmux终端复用器/vim命令式文本编辑器
-
3.Shell语法
- 3.1 Shell—版本
- 3.2 新建一个test.sh文件
- 3.3 Shell文件—运行方式
- 3.4 Shell—注释
- 3.5 Shell—变量
- 3.6 Shell—默认变量,文件参数, “$”的用法
- 3.7 Shell—数组
- 3.8 shell—expr命令
- 3.9 shell—read命令
- 3.10 shell—echo命令
- 3.11 Shell—printf命令
- 3.12 Shell—test命令与判断符号[]
- 3.13 shell—判断语句
- 3.14 shell—循环语句
- 3.15 Shell—函数
- 3.16 shell—exit命令
- 3.17 shell—文件重定向
- 3.18 shell—引入外部脚本/文件
-
4.SSH远程服务器登录/SCP服务器间传输文件
-
5.Git仓库/云端交互
-
6.thrift跨语言开发框架
-
7.管道/环境变量/其余linux常用命令
-
8.云服务器租赁
-
9.docker环境配置
1.Linux常用文件管理命令
(1) ctrl + c
: 取消命令,并且换行
(2) ctrl + u
: 清空本行命令
(3) tab
键:可以补全命令和文件名,如果补全不了快速按两下tab
键,可以显示备选选项
(4) ls
: 列出当前目录下所有文件,蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件
ls -l
是全部信息,ls -l -h
是全部信息人性化输出, ls -a
是显示包括隐藏文件
(5) pwd
: 显示当前路径
(6) cd XXX
: 进入XXX目录下, cd ..
返回上层目录, cd ~/
返回home目录, cd -
返回上一个待过的目录
(7) cp XXX YYY
: 将XXX文件复制成YYY,XXX和YYY可以是一个路径,比如../dir_c/a.txt
,表示上层目录下的dir_c文件夹下的文件a.txt, cp -r
代表递归复制,可以复制文件夹
(8) mkdir XXX
: 创建目录XXX,多重创建可以使用mkdir xxx/xxx -p
(9) rm XXX
: 删除普通文件; rm XXX -r
: 删除文件夹, rm xxx/*
删除xxx内所有文件
(10) mv XXX YYY
: 将XXX文件移动到YYY,和cp命令一样,XXX和YYY可以是一个路径;重命名也是用这个命令
(11) touch XXX
: 创建一个文件
(12) cat XXX
: 展示文件XXX中的内容
(13) 复制文本:
windows/Linux下:Ctrl + insert
,Mac下:command + c
(14) 粘贴文本:
windows/Linux下:Shift + insert
,Mac下:command + v
根目录下:
bin
文件下是可执行文件
lib
是安装包,各种头文件
2.tmux终端复用器/vim命令式文本编辑器
tmux 的功能:
- 分屏
- 允许在断开shell 连接后,后台继续运行进程
tmux 的结构:
一个 tmux 中可以打开多个 session
, 一个 session
可以打开多个 pane
, 一个pane
打开一个shell
,也就是我们看到的黑框。
tmux 常用命令: (这里注意,正常未改键的tmux应该是Ctrl+B,但由于我替换了键位,所以是Ctrl+A)
tmux
: 新建一个session- 切分屏幕:
左右分屏: 先按ctrl +a
再按%
上下分屏: 先按ctrl +a
再按"
- 选中当前
pane
: 可以用鼠标直接点,或者是 先按ctrl +a
再按 上下左右四个方向键 - 关闭当前
pane
:
先选中当前pane
按下ctrl + d
当一个window
所有的pane
都被关闭了,则这个window
也会被关闭,当一个session
中所有window
都被关闭了,那么这个session
也会被关闭 - 调整某个
pane
的分割线
用鼠标直接拖动分割线
先选中某个pane
, 再同时按下ctrl + a + 方向键
- 使某个
pane
全屏或者取消全屏:
选中某个pane
先按ctrl +a
再按z
- 挂起当前
session
: 也就是 退出当前的session
,但是里面的窗口并不关闭
先按ctrl+a
后按d
- 恢复之前的 tmux 连接
tmux a
session
选择: 先按ctlr +a
再按s
可以按上下方向键来选择session
,再按左右方向键来展开- 创建一个
window
: 先按ctrl+a
再按c
create - 选择
window
: 先按ctrl+a
再按w
,同session
,也可以打开合上,不过这个可以自动展开到window
这一级,上面的只会展开到session
这一级 - 翻阅内容: 先按
ctrl +a
再按PageUp
- 复制文本
先选中文本: 按shift
并用鼠标拖动来选中文本
ctrl+insert
复制,shift +insert
粘贴
vim 是命令行模式下的超强文本编辑器.
有三种模式:
使用方式为 vim filename
.
这个可以打开一个已经存在的文件
或者创建一个新的文件,并且重命名为 filename
详细操作
在不同的模式下生效:
- 光标移动:
-
h j k l
(4个方向键) 对应 4个方向键,一次一格 -
n<Space>
:n
是一个具体数字,光标在当前行内向右移动n
个字符 -
0 / Home
:光标移动到本行开头 -
$ / End
:光标移动到本行末尾 -
行间移动:
-
G
:光标移动到最后一行 -
:n/nG
:n
为数字,光标移动到第n
行 -
gg
:光标移动到第一行 也就是1G
-
n<Enter>
n
为数字,光标向下移动n
行
- 查找 替换
/word
:查找光标之下的第一个word
字符串?word
:查找光标之上的第一个word
字符串n
:重复之前的查找操作,可以循环查N
:反向重复之前的查找操作(之前那次是向上找,那这次就向下找):n1,n2s/word1/word2/g
:在n1
行和n2
行之间寻找word1
这个字符串,并将该字符串替换成word2
:1,$s/word1/word2/g
:替换全文中的word1
替换为word2
:1,$s/word1/word2/gc
:替换全文中的word1
替换为word2
,并每次替换前需要确认
- 文本的选中,复制,粘贴
v
:选中文本d
:删除(其实不应该叫删除,应该是剪切)选中的文本dd
:删除当前这一行y
:复制当前选中的文本yy
:复制当前行p
:粘贴,在光标的下一个位置(只删除了部分文本)或者下一行(删除了一整行)粘贴u
:撤销操作,ctrl+ r
:取消撤销>
:将选中的文本整体向右缩进<
:将选中的文本整体向左缩进
- 文件的报存:
:w
保存:w!
强制保存:q
退出:q!
强制退出:wq
保存并且退出
- 粘贴模式:
:set paste
:设置粘贴模式,此模式下取消代码的自动缩进:set nopaste
:取消粘贴模式,开启代码自动缩进:set nu
:显示行号:set nonu
:隐藏行号gg=G
将全文代码格式化:noh
关闭高亮
- 保命操作:
ctrl + q
当 vim 卡死时, 可以取消当前正在执行的命令
- 异常处理:
每次用vim编辑文件时,会自动创建一个.filename.swp
的临时文件。
如果打开某个文件时,该文件的swp
文件已存在,则会报错。此时解决办法有两种:
- 找到正在打开该文件的程序,并退出
- 直接删掉该
swp
文件即可
3.Shell语法
3.1 Shell—版本
Linux系统中一般默认使用bash
,所以接下来讲解bash中的语法。
文件开头需要写#! /bin/bash
,指明bash
为脚本解释器。
3.2 新建一个test.sh文件
#! /bin/bash
echo "Hello World!"
3.3 Shell文件—运行方式
3.1 作为可执行文件
user:~$ chmod +x test.sh # 使脚本具有可执行权限user:~$ ./test.sh # 当前路径下执行
Hello World! # 脚本输出user:~$ /home/acs/test.sh # 绝对路径下执行
Hello World! # 脚本输出user:~$ ~/test.sh # 家目录路径下执行
Hello World! # 脚本输出
3.2 用解释器执行
user:~$ bash test.sh # 调用bash
Hello World! # 脚本输出
3.4 Shell—注释
4.1 单行注释
# 这是一行注释
4.2 多行注释 (EOF可以替换为任意字符)
:<<EOF
第一行注释
第二行注释
第三行注释
EOF
3.5 Shell—变量
5.1 定义变量
name1='shuo' # 单引号定义字符串
name2="shuo" # 双引号定义字符串
name3=shuo # 也可以不加引号,同样表示字符串
5.2 使用变量
name=shuo
echo $name # 输出shuo
echo ${name} # 输出shuo
echo ${name}acwing # 输出shuoacwing
5.3 只读变量
使用readonly
或者declare
可以将变量变为只读。
name=shuo
readonly name
declare -r name # 两种写法均可
name=abc # 会报错,因为此时name只读
5.4 删除变量
使用unset
可以删除变量。
name=shuo
unset name
echo $name # 输出空行
5.5 变量类型
自定义变量(局部变量):子进程不能访问的变量
环境变量(全局变量):子进程可以访问的变量
自定义变量改成环境变量:
name=shuo # 定义变量
export name # 第一种方法
declare -x name # 第二种方法
环境变量改为自定义变量:
export name=shuo # 定义环境变量
declare +x name # 改为自定义变量
5.6 字符串
字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号与双引号的区别:
- 单引号中的内容会原样输出,不会执行、不会取变量;
- 双引号中的内容可以执行、可以取变量;
name=shuo # 不用引号
echo 'hello, $name \"hh\"' # 单引号字符串,输出 hello, $name \"hh\"
echo "hello, $name \"hh\"" # 双引号字符串,输出 hello, shuo "hh"
获取字符串长度:
name="shuo"
echo ${#name} # 输出4
提取子串:
name="hello, shuo"
echo ${name:0:5} # 提取从0开始的5个字符
3.6 Shell—默认变量,文件参数, “$”的用法
6.1 在执行Shell脚本时,可以向脚本传递参数。
这些参数通过特定的变量访问:
$1
,$2
,$3
, … :分别代表传递给脚本的第一个、第二个、第三个等参数。$0
:代表脚本文件本身的名称,包含其路径。
例如,创建一个名为 test.sh
的文件,并编写以下脚本:
#! /bin/bashecho "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
执行此脚本并传递参数,例如:
user:~$ chmod +x test.sh
user:~$ ./test.sh 1 2 3 4
输出会显示文件名和四个参数的值。
6.2 其他参数相关变量:
$#
:代表传递给文件的参数个数。在上面的例子中,其值为4。$*
:由所有参数构成的字符串,参数之间用空格隔开。例如,"$1 $2 $3 $4"
。$@
:每个参数分别用双引号括起来的字符串。例如,"$1" "$2" "$3" "$4"
。$$
:脚本当前运行的进程ID。$?
:上一条命令的退出状态(不是标准输出,而是退出码)。0表示正常退出,其他值表示有错误。$(command)
:返回command
这条命令的标准输出(stdout),可以嵌套使用。`command`
:也是返回command
命令的标准输出,但不支持嵌套。
3.7 Shell—数组
在Shell脚本中,数组可以存储多种类型的值。
这些数组仅支持一维结构,并且在初始化时不需要指定数组的大小。数组的索引从0开始。
7.1定义数组
- 使用小括号
()
来表示数组,数组元素之间用空格隔开。例如:
array=(1 abc "def" shuo)
- 也可以分别直接定义数组中每个元素的值:
array[0]=1
array[1]=abc
array[2]="def"
array[3]=shuo
7.2读取数组元素
- 使用
$
符号和大括号{}
来读取数组中的某个元素。格式为${array[index]}
。例如:
array=(1 abc "def" shuo)
echo ${array[0]}
echo ${array[1]}
7.3读取整个数组
array=(1 abc "def" shuo)
echo ${array[*]}
7.4数组长度
- 数组的长度(即数组中元素的数量)
array=(1 abc "def" shuo)
echo ${#array[*]}
3.8 shell—expr命令
8.1 expr命令
expr
命令在Shell中用于求表达式的值。表达式的格式要求如下:
- 表达式的每一项之间需要用空格隔开。
- Shell的特定字符前需要使用反斜杠
\
进行转义。 - 包含空格和其他特殊字符的字符串应用引号括起来。
8.2 输出和退出码
expr
命令的结果会在标准输出(stdout)中显示。- 对于逻辑关系表达式,结果为真时,stdout输出1,否则输出0。
expr
的退出码:对于逻辑关系表达式,结果为真时,退出码为0,否则为1。
8.3 字符串表达式
length STRING
:返回字符串STRING
的长度。index STRING CHARSET
:返回CHARSET
中任意单个字符在STRING
中最前面的位置(下标从1开始)。如果STRING
中完全不存在CHARSET
中的字符,则返回0。substr STRING POSITION LENGTH
:返回STRING
字符串中从POSITION
开始,长度最大为LENGTH
的子串。负数、0或非数值作为POSITION
或LENGTH
将返回空字符串。
str="Hello World!"echo `expr length "$str"` # ``不是单引号,表示执行该命令,输出12
echo `expr index "$str" aWd` # 输出7,下标从1开始
echo `expr substr "$str" 2 3` # 输出 ell
8.4 整数表达式
expr
支持普通的算术操作。算术表达式的优先级低于字符串表达式,高于逻辑关系表达式。- 加减(
+
,-
)、乘除取模(*
,/
,%
)等运算。操作数会被转换为整数,转换失败会报错。 - 括号
()
可以改变优先级,但需用反斜杠转义。
a=3
b=4echo `expr $a + $b` # 输出7
echo `expr $a - $b` # 输出-1
echo `expr $a \* $b` # 输出12,*需要转义
echo `expr $a / $b` # 输出0,整除
echo `expr $a % $b` # 输出3
echo `expr \( $a + 1 \) \* \( $b + 1 \)` # 输出20,值为(a + 1) * (b + 1)
8.5 逻辑关系表达式
|
和&
运算符:|
运算符在第一个参数非空且非0时返回第一个参数的值,否则返回第二个参数的值;&
运算符在两个参数都非空且非0时返回第一个参数的值,否则返回0。- 比较运算符(
<
,<=
,=
,==
,!=
,>=
,>
):比较两端的参数,返回1表示真,返回0表示假。==
是=
的同义词。expr
首先尝试将参数转换为整数进行算术比较,失败时按字符集排序规则进行字符比较。 - 括号
()
可以改变优先级,但需用反斜杠转义。
a=3
b=4echo `expr $a \> $b` # 输出0,>需要转义
echo `expr $a '<' $b` # 输出1,也可以将特殊字符用引号引起来
echo `expr $a '>=' $b` # 输出0
echo `expr $a \<\= $b` # 输出1c=0
d=5echo `expr $c \& $d` # 输出0
echo `expr $a \& $b` # 输出3
echo `expr $c \| $d` # 输出5
echo `expr $a \| $b` # 输出3
8.6 结合使用
其实``的使用本质很类似与python中format格式化输出,f"{}"中的{},往里填东西即可
那么就可以用更清晰的方式输出:
name=shuo
echo "name is $name, count is `expr length "$name"`, well done!"# 输出:name is shuo, count is 4, well done!
3.9 shell—read命令
read
命令在Shell中用于从标准输入中读取单行数据。该命令读取到文件结束符(EOF)时,退出码(exit code)为1,否则为0。
9.1 参数说明
-p
:后面可以跟随提示信息,用于在读取输入之前显示给用户。-t
:后面跟随秒数,定义输入字符的等待时间。如果超过这个时间用户没有输入,Shell将自动忽略此命令。
9.2 实例
- 基本使用:
user:~$ read name # 读入name的值
shuo # 标准输入
user:~$ echo $name # 输出name的值
shuo # 标准输出
在这个例子中,read name
读取一行数据并将其存储在变量name
中。
- 使用
-p
和-t
参数:
user:~$ read -p "Please input your name: " -t 30 name # 读入name的值,等待时间30秒
Please input your name: shuo # 标准输入
user:~$ echo $name # 输出name的值
shuo # 标准输出
3.10 shell—echo命令
echo
命令在Shell中用于输出字符串。它的基本格式为 echo STRING
。
10.1 显示普通字符串
- 使用
echo
直接显示字符串。例如:
echo "Hello AC Terminal"
echo Hello AC Terminal # 引号可以省略
10.2 显示转义字符
- 使用双引号时,可以包含转义字符。例如:
echo "\"Hello AC Terminal\"" # 使用双引号,转义字符有效
echo \"Hello AC Terminal\" # 省略双引号
注意:使用单引号时,转义字符不会被识别。
10.3 显示变量
echo
可以用来显示变量的值。例如:
name=shuo
echo "My name is $name" # 输出 My name is shuo
10.4 显示换行
- 使用
-e
选项来启用转义字符,例如换行符\n
。例如:
echo -e "Hi \n shuo"
输出结果将是两行:Hi
和 shuo
。
10.5 显示不换行
- 结合
-e
和转义字符\c
实现不换行。例如:
s
echo -e "Hi \c"
echo "shuo"
输出结果将在同一行:Hi shuo
。
10.6 显示结果定向至文件
- 使用重定向
>
将echo
的输出写入文件。例如:
echo "Hello World" > output.txt # 输出到output.txt文件
10.7 原样输出字符串
- 使用单引号可以原样输出字符串,不进行转义或取变量。例如:
name=shuo
echo '$name\"' # 输出 $name\"
10.8 显示命令的执行结果
- 使用反引号(
`
)来执行命令并显示其输出。例如:
echo `date` # 显示当前日期和时间
3.11 Shell—printf命令
printf
默认不添加换行符
11.1 命令格式
printf
的基本格式是printf format-string [arguments...]
,其中format-string
是格式化字符串,arguments
是相应的参数。
11.2 用法示例
printf "%10d.\n" 123 # 占10位,右对齐
printf "%-10.2f.\n" 123.123321 # 占10位,保留2位小数,左对齐
printf "My name is %s\n" "shuo" # 格式化输出字符串
printf "%d * %d = %d\n" 2 3 `expr 2 \* 3` # 表达式的值作为参数
结果
123.
123.12 .
My name is shuo
2 * 3 = 6
3.12 Shell—test命令与判断符号[]
12.1 逻辑运算符 &&
和 ||
&&
表示逻辑与(AND),||
表示逻辑或(OR)。- 二者遵循短路原则:
expr1 && expr2
:如果expr1
为假(false),则不会执行expr2
。expr1 || expr2
:如果expr1
为真(true),则不会执行expr2
。
- 表达式的退出码为0表示真(true),非零表示假(false),与C/C++定义相反。
12.2 test
命令
- 用于判断文件类型和比较变量。
- 使用退出码(exit code)返回结果,0为真(true),1为假(false)
- 这里要注意,
expr
命令是stdout输出,并且是1为真,0为假,刚刚好和test
相反 - 例如:
test 2 -lt 3
判断2是否小于3,为真。test -e test.sh
判断文件test.sh
是否存在。
12.3 文件类型判断
test -e filename
:判断文件是否存在。- 其他参数:
-f
:是否为普通文件。-d
:是否为目录。
12.4 文件权限判断
test -r filename
:判断文件是否可读。- 其他参数:
-w
:文件是否可写。-x
:文件是否可执行。-s
:文件是否非空。
12.5 整数间的比较
test $a -eq $b
:判断变量a
是否等于b
。- 其他参数:
-eq
:是否等于。-ne
:是否不等于。-gt
:是否大于。-lt
:是否小于。-ge
:是否大于等于。-le
:是否小于等于。
12.6 字符串比较
test -z STRING
:判断字符串是否为空。test -n STRING
:判断字符串是否非空。test str1 == str2
:判断两个字符串是否相等。test str1 != str2
:判断两个字符串是否不等。
12.7 多重条件判定
test -r filename -a -x filename
:判断文件是否同时可读且可执行。- 参数:
-a
:两条件同时成立。-o
:两条件至少一个成立。!
:取反。
12.8 判断符号 []
[]
与test
用法类似,常用于if
语句中。[ 2 -lt 3 ]
:判断2是否小于3。- 注意事项:
[]
内的每一项都要用空格隔开。- 变量最好用双引号括起来,常数最好用单或双引号括起来。
- 如:
[ "$name" == "shuo" ]
,防止因空格导致参数解析错误。
3.13 shell—判断语句
13.1 单层if
a=3
b=4if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
thenecho ${a}在范围内
fi
- 输出结果:
3在范围内
13.2 单层if-else
a=3
b=4if ! [ "$a" -lt "$b" ]
thenecho ${a}不小于${b}
elseecho ${a}小于${b}
fi
- 输出结果:
3小于4
13.3 多层if-elif-else
a=4if [ $a -eq 1 ]
thenecho ${a}等于1
elif [ $a -eq 2 ]
thenecho ${a}等于2
elif [ $a -eq 3 ]
thenecho ${a}等于3
elseecho 其他
fi
- 输出结果:
其他
13.4 case...esac
结构
a=4case $a in1)echo ${a}等于1;; 2)echo ${a}等于2;; 3)echo ${a}等于3;; *)echo 其他;;
esac
-
输出结果:
其他
3.14 shell—循环语句
14.1 for...in...do...done
循环
示例:
- 遍历并输出一系列值:
for i in a 2 cc doecho $i done
- 遍历当前目录下的所有文件:
for file in `ls` doecho $file done
- 输出1到10:
for i in $(seq 1 10) doecho $i done
- 遍历字母a到z:
for i in {a..z} doecho $i done
14.2 for ((...;...;...)) do...done
循环
-
命令格式:
for ((expression; condition; expression)) do语句1语句2... done
-
示例:输出1到10:
for ((i=1; i<=10; i++)) doecho $i done
14.3 while...do...done
循环
示例:读取输入直到EOF(文件结束符):
while read name
doecho $name
done
14.4 until...do...done
循环
示例:等待用户输入"yes"或"YES":
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
doread -p "Please input yes/YES to stop this program: " word
done
14.5 break
命令
- 用于跳出当前一层循环。
示例:在嵌套循环中使用break:while read name dofor ((i=1;i<=10;i++))docase $i in8)break;;*)echo $i;;esacdone done
14.6 continue
命令
- 用于跳过当前循环的剩余部分,进入下一次循环。
示例:输出1到10中的所有奇数:for ((i=1;i<=10;i++)) doif [ `expr $i % 2` -eq 0 ]thencontinuefiecho $i done
14.7 死循环的处理
- 如果Shell程序出现死循环,可以使用Ctrl+C中断。
- 也可以使用
top
命令找到进程的PID,然后使用kill -9 PID
命令终止进程。
3.15 Shell—函数
在 bash 中,函数的行为类似于C/C++中的函数,但有一些差异,特别是在返回值处理方面。
15.1 定义函数
-
命令格式:
[function] func_name() { # function关键字可以省略语句1语句2... }
15.2 返回值和输出
-
函数的
return
返回的是退出码(exit code),取值范围是0-255,其中0表示正常结束。 -
要获取函数的输出结果,可以通过
echo
输出到标准输出(stdout),然后使用$(function_name)
来捕获这些输出。 -
示例:不获取返回值和输出值:
func() {name=shuoecho "Hello $name" }func
-
输出结果:
Hello shuo
-
-
示例:获取返回值和输出值:
func() {name=shuoecho "Hello $name"return 123 }output=$(func) ret=$?echo "output = $output" echo "return = $ret"
-
输出结果:
output = Hello shuo return = 123
-
15.3 函数的输入参数
-
在函数内部,
$1
表示第一个输入参数,$2
表示第二个输入参数,以此类推。 -
注意:函数内的
$0
仍然是文件名,而不是函数名。 -
示例:递归函数计算总和:
func() { # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0word=""while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]doread -p "要进入func($1)函数吗?请输入y/n:" worddoneif [ "$word" == 'n' ]thenecho 0return 0fi if [ $1 -le 0 ] thenecho 0return 0fi sum=$(func $(expr $1 - 1))echo $(expr $sum + $1) }echo $(func 10)
-
输出结果:
55
-
15.4 函数内的局部变量
-
可以在函数内定义局部变量,其作用范围仅限于当前函数。
-
在递归函数中特别有用。
-
示例:
#! /bin/bashfunc() {local name=shuoecho $name } funcecho $name
-
输出结果:
shuo
第一行输出为函数内的 name
变量,第二行尝试在函数外访问 name
变量时未输出任何内容,因为 name
是局部变量。
3.16 shell—exit命令
exit
命令在Shell中用于退出当前Shell进程,并返回一个退出状态。这个退出状态可以通过$?
来接收。
16.1 使用方法
exit
命令可以带有一个整数参数,用于指定退出状态。如果没有指定参数,默认的退出状态是0。- 退出状态只能是一个介于0到255之间的整数。其中,0表示成功,任何其他值都表示失败。
16.2 示例
-
创建脚本
test.sh
,内容如下:#! /bin/bashif [ $# -ne 1 ] # 检查传入的参数个数 thenecho "arguments not valid"exit 1 elseecho "arguments valid"exit 0 fi
-
执行脚本并检查退出状态:
User:~$ chmod +x test.sh User:~$ ./test.sh acwing arguments valid User:~$ echo $? # 传入一个参数,正常退出,exit code为0 0 User:~$ ./test.sh arguments not valid User:~$ echo $? # 传入参数个数不是1,非正常退出,exit code为1 1
在这个例子中,脚本test.sh
根据传入的参数个数来决定退出状态。如果参数个数不等于1,则脚本以状态1退出,表示错误;如果参数个数等于1,则以状态0退出,表示成功。通过$?
,我们可以检查脚本执行后的退出状态。
3.17 shell—文件重定向
在Shell中,每个进程默认打开三个文件描述符:
stdin
(标准输入):用于从命令行读取数据,文件描述符为0。stdout
(标准输出):用于向命令行输出数据,文件描述符为1。stderr
(标准错误输出):同样用于向命令行输出数据,但专门用于错误信息,文件描述符为2。
文件重定向允许将这些文件描述符重定向到其他文件。
17.1 重定向命令列表
- 命令及其说明:
command > file
:将stdout
重定向到file
中。command < file
:将stdin
重定向到file
中。command >> file
:将stdout
以追加方式重定向到file
中。command n> file
:将文件描述符n
重定向到file
中。command n>> file
:将文件描述符n
以追加方式重定向到file
中。
17.2 输入和输出重定向
- 示例:将
stdout
重定向到文件,并从文件中读取数据。echo -e "Hello \c" > output.txt # 将stdout重定向到output.txt中 echo "World" >> output.txt # 将字符串追加到output.txt中 read str < output.txt # 从output.txt中读取字符串 echo $str # 输出结果:Hello World
17.3 同时重定向stdin
和stdout
-
创建一个bash脚本:
#! /bin/bash read a read b echo $(expr "$a" + "$b")
-
准备
input.txt
文件,内容为:3 4
-
执行命令:
User:~$ chmod +x test.sh # 添加可执行权限
User:~$ ./test.sh < input.txt > output.txt # 从input.txt中读取内容,将输出写入output.txt中
User:~$ cat output.txt # 查看output.txt中的内容
7
3.18 shell—引入外部脚本/文件
在Shell脚本中,可以类似于C/C++中的include
操作来引入其他文件中的代码。这允许在一个脚本中使用另一个文件定义的变量、函数等。
示例
-
创建
test1.sh
,内容如下:#! /bin/bash name=shuo # 定义变量name
-
创建
test2.sh
,内容如下:#! /bin/bash source test1.sh # 或 . test1.sh echo My name is: $name # 使用test1.sh中定义的变量
-
执行命令:
User:~$ chmod +x test2.sh
User:~$ ./test2.sh
My name is: shuo
4.SSH远程服务器登录/SCP服务器间传输文件
ssh登录
4.1 基本用法
- 远程登录服务器:
`ssh user@hostname`
user
: 用户名hostname
: IP地址或域名
- 第一次登录时会提示:
输入The authenticity of host '123.57.47.211 (123.57.47.211)' can't be established. ECDSA key fingerprint is SHA256:iy237yysfCe013/l+kpDGfEG9xxHxm0dnxnAbJTPpG8. Are you sure you want to continue connecting (yes/no/[fingerprint])?
yes
,然后回车即可。这样会将该服务器的信息记录在~/.ssh/known_hosts
文件中。 - 输入密码即可登录到远程服务器。
- 默认登录端口号为22。如果想登录某一特定端口:
`ssh user@hostname -p 22`
4.2 配置文件
- 创建文件
~/.ssh/config
。 - 在文件中输入:
Host myserver1HostName IP地址或域名User 用户名Host myserver2HostName IP地址或域名User 用户名
- 之后再使用服务器时,可以直接使用别名
myserver1
、myserver2
。
4.3 密钥登录
- 创建密钥:
然后一直回车即可。`ssh-keygen`
- 执行结束后,
~/.ssh/
目录下会多两个文件:id_rsa
:私钥id_rsa.pub
:公钥
- 想免密码登录哪个服务器,就将公钥中的内容,复制到该服务器中的
~/.ssh/authorized_keys
文件里即可。 - 使用如下命令一键添加公钥:
`ssh-copy-id myserver`
4.4 执行命令
-
命令格式:
ssh user@hostname command
-
例如:
ssh user@hostname ls -a
-
单引号中的
$i
可以求值:ssh myserver 'for ((i = 0; i < 10; i ++ )) do echo $i; done'
-
双引号中的
$i
不可以求值:ssh myserver "for ((i = 0; i < 10; i ++ )) do echo $i; done"
scp文件传输
4.5 基本用法
-
命令格式:
`scp source destination`
将
source
路径下的文件复制到destination
中。 -
一次复制多个文件:
`scp source1 source2 destination`
4.6 复制文件夹:(注意一点,复制文件夹时一定要在目标目录路径后加/
,这样才会复制文件夹而不是文件)
- 将本地家目录中的
tmp
文件夹复制到myserver
服务器中的/home/acs/
目录下:`scp -r ~/tmp myserver:/home/acs/`
- 将本地家目录中的
tmp
文件夹复制到myserver
服务器中的~/homework/
目录下:`scp -r ~/tmp myserver:homework/`
- 将
myserver
服务器中的~/homework/
文件夹复制到本地的当前路径下:`scp -r myserver:homework .`
4.7 指定服务器的端口号:
`scp -P 22 source1 source2 destination`
注意:scp
的-r
、-P
等参数尽量加在source
和destination
之前。
- 使用scp配置其他服务器的vim和tmux:
`scp ~/.vimrc ~/.tmux.conf myserver:`
5.Git仓库/云端交互
代码托管平台:
1.git.acwing.com
2.github.com
1.1. git基本概念
- 工作区:仓库的目录。工作区是独立于各个分支的。
- 暂存区:数据暂时存放的区域,类似于工作区写入版本库前的缓存区。暂存区是独立于各个分支的。
- 版本库:存放所有已经提交到本地仓库的代码版本。
- 版本结构:树结构,树中每个节点代表一个代码版本。
1.2 git常用命令
git config --global user.name xxx
:设置全局用户名,信息记录在~/.gitconfig
文件中。git config --global user.email xxx@xxx.com
:设置全局邮箱地址,信息记录在~/.gitconfig
文件中。git init
:将当前目录配置成 git 仓库,信息记录在隐藏的.git
文件夹中。git add XX
:将 XX 文件添加到暂存区。git add .
:将所有待加入暂存区的文件加入暂存区。
git rm --cached XX
:将文件从仓库索引目录中删掉。git commit -m "给自己看的备注信息"
:将暂存区的内容提交到当前分支。git status
:查看仓库状态。git diff XX
:查看 XX 文件相对于暂存区修改了哪些内容。
当工作区有改动,临时区为空,diff的对比是“工作区与最后一次commit提交的仓库的共同文件”;
当工作区有改动,临时区不为空,diff对比的是“工作区与暂存区的共同文件”。
git log
:查看当前分支的所有版本。git log --oneline --graph
也不错,如果log显示太多可以按q退出。
git reflog
:查看 HEAD 指针的移动历史(包括被回滚的版本)。git reset --hard HEAD^
或git reset --hard HEAD~
:将代码库回滚到上一个版本。git reset --hard HEAD^^
:往上回滚两次,以此类推。git reset --hard HEAD~100
:往上回滚 100 个版本。git reset --hard 版本号
:回滚到某一特定版本。
git checkout — XX
或git restore XX
:将 XX 文件尚未加入暂存区的修改全部撤销。
git restore file和git restore --staged file的详细使用区别:12.1 git restore file命令也有两种,一种是暂存区有东西,一种是暂存区没有东西,
当暂存区有file文件的时候,执行git restore file命令,将会把暂存区的与file同名的文件覆盖到工作区的file文件,称为暂存回滚。
当暂存区没有file文件的时候,执行git restore file命令,将会在当前版本库中寻找与file同名的文件,将该文件把工作区的file文件覆盖掉,也成为版本回滚。12.2 git restore --staged file命令则是只把暂存区的file文件删除,其他的什么都不变,这样做是为了直接与版本库的file文件接轨,要不然只要暂存区有file的同名文件存在,就不会走到版本库,所以只能先把暂存区的file文件删掉,再执行git restore file 才能用版本库的版本回滚。)
git remote add origin git@git.acwing.com:xxx/XXX.git
:将本地仓库关联到远程仓库。git push -u
(第一次需要-u
,以后不需要):将当前分支推送到远程仓库。git push origin branch_name
:将本地的某个分支推送到远程仓库。
git clone git@git.acwing.com:xxx/XXX.git
:将远程仓库 XXX 下载到当前目录下。git checkout -b branch_name
:创建并切换到 branch_name 这个分支。git branch
:查看所有分支和当前所处分支。git checkout branch_name
:切换到 branch_name 这个分支。git merge branch_name
:将分支 branch_name 合并到当前分支上。git branch -d branch_name
:删除本地仓库的 branch_name 分支。git branch branch_name
:创建新分支。git push --set-upstream origin branch_name
:设置本地的 branch_name 分支对应远程仓库的 branch_name 分支。git push -d origin branch_name
:删除远程仓库的 branch_name 分支。git pull
:将远程仓库的当前分支与本地仓库的当前分支合并。git pull origin branch_name
:将远程仓库的 branch_name 分支与本地仓库的当前分支合并。
git branch --set-upstream-to=origin/branch_name1 branch_name2
:将远程的 branch_name1 分支与本地的 branch_name2 分支对应。- 这里有可能遇到本地git库未同步信息,可以使用
git fetch
来同步信息后再将分支进行对应。
- 这里有可能遇到本地git库未同步信息,可以使用
git checkout -t origin/branch_name
:将远程的 branch_name 分支拉取到本地。git stash
:将工作区和暂存区中尚未提交的修改存入栈中。git stash apply
:将栈顶存储的修改恢复到当前分支,但不删除栈顶元素。git stash drop
:删除栈顶存储的修改。git stash pop
:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素。git stash list
:查看栈中所有元素。
6.thrift跨语言开发框架
项目源代码地址: acgit-thrift-learning
一、项目描述
游戏匹配服务
- 服务分为三部分:分别是game,match_system,save_server
- game为match_client端,通过match.thrift接口向match_system完成添加用户和删除用户的操作
- match_system由两部分组成,分别为match_server端和save_client端。match_server端负责接收match_client端的操作,将用户添加进匹配池,并且在匹配结束之后通过save.thrift接口将用户数据上传至另一个服务器
- save_server用于接收match_system上传的匹配成功的用户信息
游戏匹配服务项目流程
- 构建match.thrift接口
- 通过match.thrift接口构建服务端和客户端
- 先将服务端和客户端跑通,能完成基本的连接通信
- 完成match.thrift的客户端需求
- 构建save.thrift接口
- 通过save.thrift接口构建服务端和客户端
- 将客户端业务添加到match_system当中,将save.thrift服务端完成(本项目save.thrift服务端已经完成)
- 根据业务需求完善match_system
1.创建match-server:
cd thrift_lesson/match_system/src
thrift -r --gen cpp ../../thrift/match.thrift
mv gen-cpp match_server
mv match_server/Match_server.skeleton.cpp main.cpp
2.创建save-client:
cd thrift_lesson/match_system/src
thrift -r --gen cpp ../../thrift/save.thrift
mv gen-cpp save_client
rm save_client/Save_server.skeleton.cpp
修改main.cpp,源代码在ACgit-shuo-main.cpp:
编译:
g++ -c main.cpp match_server/*.cpp save_client/*.cpp
链接:
g++ *.o -o main -lthrift -pthread
启动服务:
./main
3.创建match-client:
cd thrift_lesson/game/src
thrift -r --gen py ../../thrift/match.thrift
mv gen-py match_client
创建client.py,源代码在ACgit-shuo-client.cpp:
执行client.py:
python3 client.py
二、项目完成过程
- 在gitlab上创建项目,在teminal中创建thrift文件并将当前文件初始化为仓库
- 根据项目需求创建文件夹本项目中一共分为三个模块game,match_system,thrift
- 在thrift文件夹中创建match.thrift文件,登录thrift官方网站查看tutorial.thrift官方文档根据项目需求完成match.thrift,本项目需要定义三个部分
- 命名空间(cpp)
- 接口传入的用户信息(int 用户id,string 用户名,int 分数)
- match.thrift接口服务内容(添加用户,删除用户)
- 由thrift接口生成服务端,进入match_system文件夹中(最好多创建一个src文件夹)在src文件夹下执行thrift官方文档中
thrift -r --gen <language> <Thrift filename>
直接生成服务端,生成的文件为gen.cpp将其改名为match_server,进入match_server文件夹查看Match_server.skeleton.cpp为服务端代码,将其copy到src目录下并重命名为main.cpp - 打开main.cpp,先在函数后面加上返回值,并编译文件(在工程中一般先将文件编译成功再加具体的逻辑),cpp文件编译包括两步,编译和链接
- 编译
g++ -c <filename>.cpp
- 链接
g++ *.o -o main -lthrift -pthread
./main
运行文件
- 由thrift接口生成客户端,在game文件夹中创建src文件夹,执行
thrift -r --gen py tutorial.thrift
生成gen.py将其改名为match_client,查看文件中有服务器端文件Match-remote将其删除,因为目前只需要生成客户端(注意:在cpp中生成客户端此文件必须删除,因为cpp编译文件中只能有一个main函数) - 在src目录下创建client.py,将官方文档中的client端代码复制到client.py中,注意修改头文件,执行
python3 <filename>
看看编译成功。如果编译成功则在代码中加上用户信息并调用服务端的函数,先启动服务端的main.cpp,再运行client.py看看服务端和客户端是否连接成功。修改代码使其能够读取终端中输入用户,编译运行如成功运行则match客户端完成 - 修改服务端,具体修改逻辑参考
- 在thrift文件夹目录下新建save.thrift,在y总目录中将内容复制过来,在src目录下同样执行
thrift -r --gen py tutorial.thrift
生成gen.cpp文件将其改名为save.client,进入文件夹将里面的.skeleton.cpp删除 - 在main.cpp中实现save_client的功能,查看thrift官方文档,具体修改逻辑参考
- 实现具体业务需求
- 将消费者模型升级为多线程4.0
- 将匹配机制完善5.0,等待时间越长,阈值越大
三、知识点总结(根据git仓库history总结)
构建match.thrift接口(match.thrift版本)
- 查询thrift官方文档https://github.com/apache/thrift/blob/master/tutorial/tutorial.thrift根据项目需求按照thrift文档语法要求定义命名空间,用户信息,接口服务内容
通过match.thrift接口生成服务端(match_server:1.0版本)
- 查询thrift官方文档https://thrift.apache.org/tutorial/cpp.html根据项目需求生成服务端代码
- 端口:端口是一个16位的二进制数,其范围从0~65535。同一个端口只能由一个进程监听,当在一个端口号启动了一个服务,另一个进程将无法访问这个端口号。服务端的端口号和客户端的端口号要相同才能够连接
通过match.thrift接口生成客户端(match_client:1.0版本)
- 查询thrift官方文档https://thrift.apache.org/tutorial/py.html根据项目需求生成客户端代码,调用服务端函数尝试能否连接
完成match.thrift客户端(match_client:2.0 finish版本)
- python 从终端接收输入:
from sys import stdin
改进match.thrift服务端(match_server:2.0版本)
- 多线程thread:一个程序是一个进程,一个进程中至少有一个线程。如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待。创建线程代价较小,但能有效提升cpu利用率。在本次项目中,我们需要输入用户信息和用户匹配是同时进行的,而不是输入用户信息结束才开始匹配,或匹配结束才能输入用户信息,所以我们需要开多线程编程。
- 生产者消费者模型:假如有两个线程A和B,A线程生产数据(类似本项目终端输入用户信息)并将信息加入缓冲区,B线程从缓冲区中取出数据进行操作(类似本项目中取出用户信息匹配),则A为生产者B为消费者。在多线程开发中,如果生产者生产数据的速度很快,而消费者消费数据的速度很慢,那么生产者就必须等待消费者消费完数据才能够继续生产数据,因为生产过多的数据可能会导致存储不足;同理如果消费者的速度大于生产者那么消费者就会经常处理等待状态,所以为了达到生产者和消费者生产数据和消费数据之间的平衡,那么就需要一个缓冲区用来存储生产者生产的数据,所以就引入了生产者-消费者模型。当缓冲区满的时候,生产者会进入休眠状态,当下次消费者开始消耗缓冲区的数据时,生产者才会被唤醒,开始往缓冲区中添加数据;当缓冲区空的时候,消费者也会进入休眠状态,直到生产者往缓冲区中添加数据时才会被唤醒
– 在本项目头文件中加入#include <thread>
引入多线程 - 消息队列message_queue:在生产者消费者模型中我们提到了缓冲区,缓冲区的实现就是由队列来实现,当生产者生产数据后将信息入队,消费者获取信息后信息出队。消息队列提供了异步通信协议,也就是说,消息的发送者和接收者不需要同时与消息队列交互,消息会保存在队列中,直到接收者使用它
– 在本项目中手动实现消息队列,在头文件中加入#include <queue>
,定义一个结构体将互斥锁mutex,队列queue和条件变量condition加入结构体即可 - 互斥锁mutex:保证共享数据操作的完整性,保证在任一时刻只能有一个线程访问对象。锁有两个操作。一个P操作(上锁),一个V操作(解锁)。P和V都是原子操作,就是在执行P和V操作时,不会被插队。锁一般使用信号量来实现的,mutex其实就是信号量=1。互斥量就是同一时间能够分给一个人,即S=1。S=10表示可以将信号量分给10个人来用。如果一共有20个人那么只能有10个人用,剩下10个人需要等待。
– 在本项目中有两个操作添加用户和删除用户,信息都是存在消息队列当中,如果不上锁,这两个操作同时执行可能导致在消息队列当中信息错乱。在本项目头文件中加入#include <mutex>
引入互斥锁 - 条件变量condition_variable:条件变量一般和互斥锁搭配使用,条件变量用于在多线程环境中等待特定事件发生。
– 在本项目中如果消息队列为空则等待,如果有添加用户和删除用户的操作则将消息队列唤醒
完成save.thrift服务端(implement save_client版本)
- 上传数据到服务器需要输入服务端的用户名和密码,密码可以用md5值加密
- 求一个字符串的md5值:终端输入命令
md5sum
,输入原密码回车然后Ctrl+d
7.管道/环境变量/其余linux常用命令
7.1 管道
概念:
管道是一种命令行工具,类似于文件重定向,它可以将一个命令的标准输出(stdout)重定向到另一个命令的标准输入(stdin)。
要点:
- 仅处理标准输出:管道命令只处理标准输出(stdout),会忽略标准错误输出(stderr)。
- 命令兼容性:管道右边的命令必须能够接收标准输入(stdin)。
- 串联多个命令:可以将多个管道命令连续使用,形成命令链。
与文件重定向的区别:
- 命令与文件:文件重定向通常是将命令的输出重定向到文件,或从文件读取输入。
- 命令间的通信:管道则是在命令之间进行数据传输。左侧命令的标准输出变成右侧命令的标准输入。
举例:
- 统计Python文件行数:
使用以下命令统计当前目录下所有 Python 文件的总行数:find . -name '*.py' | xargs cat | wc -l
find . -name '*.py'
查找所有 Python 文件。xargs cat
将找到的文件内容输出。wc -l
统计输出内容的行数。
7.2 环境变量
概念:
Linux 系统使用许多环境变量来记录配置信息。环境变量类似于全局变量,可被各个进程访问。通过修改环境变量,我们可以方便地修改系统配置。
查看环境变量:
-
列出所有环境变量:
env
:显示当前用户的环境变量。set
:显示当前 shell 的变量,包括用户的变量。export
:显示当前导出成用户变量的 shell 变量。
-
输出特定环境变量的值:
echo $PATH
修改环境变量:
-
环境变量的定义、修改、删除操作可以参考Shell—变量这一节的内容。
-
持久化修改:为了将对环境变量的修改应用到未来所有环境下,可以将修改命令放到
~/.bashrc
文件中。修改完~/.bashrc
后,执行source ~/.bashrc
来将修改应用到当前的 bash 环境下。
为何放到 ~/.bashrc
:
- 每次启动 bash,都会先执行
~/.bashrc
。 - 每次 SSH 登陆远程服务器,都会启动一个 bash 命令行给我们。
- 每次 tmux 新开一个 pane,都会启动一个 bash 命令行给我们。
- 因此,未来所有新开的环境都会加载我们修改的内容。
常见环境变量:
- HOME:用户的家目录。
- PATH:可执行文件(命令)的存储路径。路径之间用
:
分隔。路径按从左到右的顺序优先。 - LD_LIBRARY_PATH:指定动态链接库(
.so
文件)的路径,路径列表用:
分隔。 - C_INCLUDE_PATH:C 语言头文件路径,路径列表用
:
分隔。 - CPLUS_INCLUDE_PATH:C++ 头文件路径,路径列表用
:
分隔。 - PYTHONPATH:Python 导入包的路径,路径列表用
:
分隔。 - JAVA_HOME:JDK 的安装目录。
- CLASSPATH:存放 Java 导入类的路径,路径列表用
:
分隔。
7.3 其余linux常用文件管理命令
系统状况
top
:查看所有进程的信息(类似于Linux的任务管理器),包括:- 输入
shift + M
:按使用内存排序。 - 输入
shift + P
:按使用CPU排序。 - 输入
q
:退出。
- 输入
df -h
:查看硬盘使用情况。free -h
:查看内存使用情况。du -sh
:查看当前目录占用的硬盘空间。ps aux
:查看所有进程。- 找到特定进程:
ps aux | grep filename
- 找到特定进程:
kill -9 pid
:杀死编号为pid的进程。- 传递特定信号:
kill -s SIGTERM pid
。
- 传递特定信号:
netstat -nt
:查看所有网络连接。w
:列出当前登录的用户。ping www.baidu.com
:检查网络连接。
文件权限
chmod
:修改文件权限,包括:chmod +x xxx
:给xxx添加可执行权限。chmod -x xxx
:去掉xxx的可执行权限。chmod 777 xxx
:将xxx的权限改为777。- 递归修改:
chmod 777 xxx -R
。
文件检索
find /path/to/directory/ -name '*.py'
:搜索特定路径下的所有*.py文件。grep xxx
:从stdin中读入数据,输出包含xxx的行。wc
:统计行数、单词数、字节数,支持stdin输入和命令行文件列表,包括:wc -l
:统计行数。wc -w
:统计单词数。wc -c
:统计字节数。
tree
:展示目录的文件结构,包括:tree /path/to/directory/
:展示特定目录。- 展示隐藏文件:
tree -a
。
ag xxx
:搜索当前目录下所有文件中的xxx字符串。cut
:分割一行内容,支持stdin输入,如:echo $PATH | cut -d ':' -f 3,5
:输出PATH用’:'分割后的第3、5列数据。echo $PATH | cut -c 3-5
:输出PATH的第3-5个字符。
sort
:按字典序排序每行内容。xargs
:将stdin中的数据分割成命令行参数,如:find . -name '*.py' | xargs cat | wc -l
:统计当前目录下所有Python文件的总行数。
查看文件内容
more
和less
:浏览文件内容,支持翻页和退出。head -3 xxx
:展示xxx的前3行内容。tail -3 xxx
:展示xxx的末尾3行内容。
用户相关
history
:展示当前用户的历史操作,内容存放在~/.bash_history
中。
工具
md5sum
:计算md5哈希值。time command
:统计command命令的执行时间。ipython3
:交互式Python3环境。! echo hello world
:在ipython3环境中可以直接在前面加!号来运行shell命令。
watch -n 0.1 command
:每0.1秒执行一次command命令。tar
:用于压缩和解压缩文件。tar -zcvf xxx.tar.gz /path/to/file/*
:压缩tar -zxvf xxx.tar.gz
:解压缩
diff xxx yyy
:比较文件xxx和yyy的不同。
安装软件
sudo command
:以root身份执行command命令。apt-get install xxx
:安装软件。pip install xxx --user --upgrade
:安装Python包。
8.云服务器租赁
8.1 概述
云平台的作用:
- 存放我们的docker容器,让计算跑在云端。
- 获得公网IP地址,让每个人可以访问到我们的服务。
任选一个云平台即可,推荐配置:
- 2核 2GB(后期可以动态扩容,前期配置低一些没关系)
- 网络带宽采用按量付费,最大带宽拉满即可(费用取决于用量,与最大带宽无关)
- 系统版本:ubuntu 20.04 LTS(推荐用统一版本,避免后期出现配置不兼容的问题)
8.2 腾讯云租赁
- 在腾讯云上注册并实名验证,然后点击
云产品
->云服务器
->新建
,然后按以下配置进行调整: - 建议一次性多租几年,有优惠。
8.3 租赁成功后,进行服务器配置
-
创建工作用户并赋予sudo权限
- 使用任意装有ssh的Terminal都可以登录到新服务器:
ssh ubuntu@xxx.xxx.xxx.xxx
- 创建用户acs:
adduser acs
:创建用户acs。sudo passwd acs
: 设置密码。usermod -aG sudo acs
:给用户acs分配sudo权限。
- 使用任意装有ssh的Terminal都可以登录到新服务器:
-
配置免密登录方式
- 在Terminal配置acs用户的别名和免密登录(参考4.SSH远程服务器登录/SCP服务器间传输文件)。
-
配置新服务器的工作环境
- 传输Terminal的配置到新服务器上:
scp .bashrc .vimrc .tmux.conf server_name:
(将server_name替换成自己配置的别名)。
- 传输Terminal的配置到新服务器上:
-
安装tmux和docker (建议创建用户后优先配置docker!)
- 登录自己的服务器,然后安装tmux:
sudo apt-get update
sudo apt-get install tmux
- 打开tmux(建议:所有工作都在tmux里进行,以防止意外关闭终端后工作进度丢失)。
- 在tmux中根据docker安装教程安装docker。
- 登录自己的服务器,然后安装tmux:
-
安装docker的时候可以将一些命令替换,使用清华源:
-
清华镜像地址:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-
储存库:
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/ \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
-
清华源update地址
9.docker配置
9.1 将当前用户添加到docker用户组
- 为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入安装中自动创建的docker用户组:
sudo usermod -aG docker $USER
newgrp docker
- 注意:执行此操作后,需要退出服务器再重新登录,才能省去sudo权限。
使用腾讯云的docker pull
出现问题:Error response from daemon: Head "https://registry-1.docker.io/v2/library/ubuntu/manifests/20.04": Get "https://auth.docker.io/token?scope=repository%3Alibrary%2Fubuntu%3Apull&service=registry.docker.io": net/http: TLS handshake timeout
解决方法:
1. sudo vim /etc/resolv.conf
2. 添加这两行:
nameserver 8.8.8.8
nameserver 8.8.4.4
3. sudo systemctl stop docker.socket
4. sudo systemctl restart docker
9.2 镜像(Images)
docker pull ubuntu:20.04
:拉取一个镜像。docker images
:列出本地所有镜像。docker image rm ubuntu:20.04
或docker rmi ubuntu:20.04
:删除镜像ubuntu:20.04。docker [container] commit CONTAINER IMAGE_NAME:TAG
:创建某个container的镜像。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从本地文件ubuntu_20_04.tar中加载出来。
9.3 容器(Container)
docker [container] create -it ubuntu:20.04
:利用镜像ubuntu:20.04创建一个容器。docker ps -a
:查看本地的所有容器。docker [container] start CONTAINER
:启动容器。docker [container] stop CONTAINER
:停止容器。docker [container] restart CONTAINER
:重启容器。docker [container] run -itd ubuntu:20.04
:创建并启动一个容器。docker [container] attach CONTAINER
:进入容器(按Ctrl-p再按Ctrl-q可以挂起容器)。docker [container] exec CONTAINER COMMAND
:在容器中执行命令。docker [container] rm CONTAINER
:删除容器。docker container prune
:删除所有已停止的容器。docker export -o xxx.tar CONTAINER
:将容器CONTAINER导出到本地文件xxx.tar中。docker import xxx.tar image_name:tag
:将本地文件xxx.tar导入成镜像,并将镜像命名为image_name:tag。docker export/import
与docker save/load
的区别:export/import会丢弃历史记录和元数据信息,仅保存容器当时的快照状态;save/load会保存完整记录,体积更大。
docker top CONTAINER
:查看某个容器内的所有进程。docker stats
:查看所有容器的统计信息,包括CPU、内存、存储、网络等信息。docker cp xxx CONTAINER:xxx
或docker cp CONTAINER:xxx xxx
:在本地和容器间复制文件。docker rename CONTAINER1 CONTAINER2
:重命名容器。docker update CONTAINER --memory 500MB
:修改容器限制。
新建容器中可能没有ssh,使用下面的方法来在容器中下载ssh并启动:
sudo apt-get install ssh
sudo apt-get update
sudo /etc/init.d/ssh start
9.4 实战
- 进入AC Terminal,然后:
scp /var/lib/acwing/docker/images/docker_lesson_1_0.tar server_name:
将镜像上传到自己租的云端服务器。ssh server_name
登录自己的云端服务器。docker load -i docker_lesson_1_0.tar
将镜像加载到本地。docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0
创建并运行docker_lesson:1.0镜像。docker attach my_docker_server
进入创建的docker容器。passwd
设置root密码。
- 去云平台控制台中修改安全组配置,放行端口20000。
- 返回AC Terminal,通过ssh登录自己的docker容器:
ssh root@xxx.xxx.xxx.xxx -p 20000
(将xxx.xxx.xxx.xxx替换成自己租的服务器的IP地址)。
- 可以仿照8.3的内容,创建工作账户acs。
- 最后,参考4.SSH远程服务器登录/SCP服务器间传输文件给docker容器的别名和免密登录。
如果有所帮助请给个免费的赞吧~有人看才是支撑我写下去的动力!
声明:
本文仅用作学习记录和交流,整合资料来源:https://www.acwing.com/