Linux基础学习(tmux,vim,shell,ssh,git,云服务器)

Linux基础学习

参考:AcWing–Linux基础课
水平有限,希望和各位同学相互学习,有错误的地方可以批评指正。

Day01-常用文件管理命令

  • / 根目录

  • bin 存储可视性文件的命令

  • etc 服务器配置

  • var 网站日志

  • lib 安装包 头文件

  • home 所有用户的家目录

    • 用户的目录
  • proc 进程相关的信息

1.绝对路径

从根目录开始描述的路径

2.相对路径

当前的路径开始去描述路径

识别方法:绝对路径开头是斜杠,相对路径不是

3.目录

./ 当前目录

…/ 上级目录

~/ 家目录 home文件夹里

cd /:切换到系统根目录

cd ~:切换到用户主目录

cd -: 切换到上一个操作所在目录

一些命令

ls -a可以显示隐藏文件。隐藏文件以.开头

touch 创建文件。如果文件不存在,可以创建一个空白文件;如果文件已经存在,可以修改文件的末次修改日期。

mkdir创建一个新的目录,新建目录的名称 不能与当前目录中 已有的目录或文件同名

cp将给出的文件或目录复制到另一个 文件或目录中

mv可以用来 移动 文件 或 目录,也可以给 文件或目录重命名

ctrl c: 取消命令,并且换行
ctrl u: 清空本行命令
tab键:可以补全命令和文件名,如果补全不了快速按两下tab键,可以显示备选选项
ls: 列出当前目录下所有文件,蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件
pwd: 显示当前路径
cd XXX: 进入XXX目录下, cd .. 返回上层目录
cp XXX YYY: 将XXX文件复制成YYY,XXX和YYY可以是一个路径,比如../dir_c/a.txt,表示上层目录下的dir_c文件夹下的文件a.txt
mkdir XXX: 创建目录XXX
rm XXX: 删除普通文件;  rm XXX -r: 删除文件夹
mv XXX YYY: 将XXX文件移动到YYY,和cp命令一样,XXX和YYY可以是一个路径;重命名也是用这个命令
touch XXX: 创建一个文件
cat XXX: 展示文件XXX中的内容
复制文本
    windows/Linux下:Ctrl + insert,Mac下:command + c
粘贴文本
    windows/Linux下:Shift + insert,Mac下:command + v

Day02-tmux和vim

tmux

  • 支持分屏
  • 让进程不会因为断开连接而直接中断

top命令-显示每个进程当前的运行状况,可以理解为任务管理器

一个tmux可以开很多session(会话)

一个session可以开很多window(窗口)

一个window可以开很多pane(小窗口)

直接输入tmux可以新开一个session,session里包含了一个window

一些tmux的操作

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 a:打开之前挂起的session。
按下ctrl + a后手指松开,然后按s:选择其它session。
 方向键 —— 上:选择上一项 session/window/pane
 方向键 —— 下:选择下一项 session/window/pane
 方向键 —— 右:展开当前项 session/window
 方向键 —— 左:闭合当前项 session/window
按下Ctrl + a后手指松开,然后按c:在当前session中创建一个新的window。
按下Ctrl + a后手指松开,然后按w:选择其他window,操作方法与(12)完全相同。
按下Ctrl + a后手指松开,然后按PageUp:翻阅当前pane内的内容。
鼠标滚轮:翻阅当前pane内的内容。
在tmux中选中文本时,需要按住shift键。(仅支持Windows和Linux,不支持Mac,不过该操作并不是必须的,因此影响不大)
tmux中复制/粘贴文本的通用方式:
   按下Ctrl + a后松开手指,然后按[
   用鼠标选中文本,被选中的文本会被自动复制到tmux的剪贴板
   按下Ctrl + a后松开手指,然后按],会将剪贴板中的内容粘贴到光标处
ctrl+a z:切换全屏

vim

  • 命令行模式下的文本编辑器。
  • 根据文件扩展名自动判别编程语言。支持代码缩进、代码高亮等功能。
  • 使用方式:vim filename
    • 如果已有该文件,则打开它。
    • 如果没有该文件,则打开个一个新的文件,并命名为filename

一些vim的操作

i:进入编辑模式
ESC:进入一般命令模式
h 或 左箭头键:光标向左移动一个字符
j 或 向下箭头:光标向下移动一个字符
k 或 向上箭头:光标向上移动一个字符
l 或 向右箭头:光标向右移动一个字符
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为数字,在第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:将全文代码格式化
ggvG: 全选
:noh 关闭查找关键词高亮
Ctrl + q:当vim卡死时,可以取消当前正在执行的命令
异常处理:
 每次用vim编辑文件时,会自动创建一个.filename.swp的临时文件。
 如果打开某个文件时,该文件的swp文件已存在,则会报错。此时解决办法有两种:
     (1) 找到正在打开该文件的程序,并退出
     (2) 直接删掉该swp文件即可

Day03-shell语法

1.概论
  • shell是我们通过命令行与操作系统沟通的语言。
  • shell脚本可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。
  • Linux系统中一般默认使用bash。文件开头需要写#! /bin/bash,指明bash为脚本解释器。

最简单的shell程序

#! /bin/bash
echo "Hello World!"  //  echo可以理解成C++里的cout

执行

bash test.sh

r 表示读

w 表示写

x 表示执行

给文件添加可执行的权限(以文件名test.sh为例)

chmod +x test.sh

检查文件的权限的命令

ls -l test.sh
2.注释
  • 单行注释

    每行中#之后的内容均是注释。

    # 这是一行注释
    echo "Hello World"  #  这也是注释
    
  • 多行注释

:<<EOF
第一行
第二行
第三行
EOF

其中EOF可以换成其它任意字符串。例如:

:<<abc
第一行注释
第二行注释
第三行注释
abc

:<<!
第一行注释
第二行注释
第三行注释
!
3.变量
  • 定义变量

可以单引号可以双引号可以不加引号

  • 把变量变为只读
#! /bin/bash
name=yjl

readonly name  #  将命令变为只读命令
declare -r name  #  将命令变为只读命令
        
name=acb
  • 删除变量
#! /bin/bash
name=yjl
unset name
echo ${name}  #  输出空行

变量类型

  • 自定义变量(局部变量)

子进程不能访问的变量

  • 环境变量(全局变量)

子进程可以访问的变量

局部变量改成全局变量:

name=yjl  #  定义变量
export name  #  第一种方法
declare -x name  #  第二种方法

全局变量改为局部变量:

export name=yjl  #  定义全局变量
declare +x name  #  改为局部变量

字符串

字符串可以用单引号,也可以用双引号,也可以不用引号。

单引号与双引号的区别:

  • 单引号中的内容会原样输出,不会执行、不会取变量;
  • 双引号中的内容可以执行、可以取变量;
name=yjl  # 不用引号
echo 'hello, $name \"hh\"'  #  单引号字符串,输出 hello, $name \"hh\"
echo "hello, $name \"hh\""  #  双引号字符串,输出 hello, yjl "hh"

获取字符串长度

name=yjl
echo ${#name}  #  输出长度为3

提取字串

name="yjlyjl"
echo ${name:0,4}  #  输出为yjly
4.默认变量

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

"$0"是文件名(包括路径)

"$1"是第一个参数

"$2"是第二个参数

以此类推

创建文件test.sh

#! /bin/bash

echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
#  向脚本传递参数时,参数个数超过一位需要用大括号括起来
#  例如echo ${10}

执行

./test.sh 1 2 3 4
文件名:./test.sh
第一个参数:1
第二个参数:2
第三个参数:3
第四个参数:4

exit code

以C++程序为例,return 0是exit code.

standout

以C++程序为例,cout << a << "\n"是standout标准输出.

参数说明
$#代表文件传入的参数个数
$*由所有参数构成的用空格隔开的字符串
$@每个参数分别用双引号括起来的字符串
$$脚本当前运行的进程ID
$?上一条命令的退出状态(注意不是stdout,而是exit code)。0表示正常退出,其他值表示错误
$(command)返回command这条命令的stdout(可嵌套)
command返回command这条命令的stdout(不可嵌套)
5.数组

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

定义
数组用小括号表示,元素之间用空格隔开。例如:

array=(1 abc "def" yjl)

也可以直接定义数组中某个元素的值:

array[0]=1
array[1]=abc
array[2]="def"
array[3]=yjl

读取数组中某个元素的值

${array[index]}

例如

array=(1 abc "def" yjl)
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]}

读取整个数组

${array[@]}  # 第一种写法
${array[*]}  # 第二种写法

读取数组长度

${#array[@]}  # 第一种写法
${#array[*]}  # 第二种写法
6.expr命令

用于求表达式的值

格式为expr 表达式

说明

  • 用空格隔开每一项
  • 用反斜杠放在shell特定的字符前面
  • 对包含空格喝其他特殊字符的字符串要用引号括起来
  • expr会在stdout中输出结果

字符串表达式

str="Hello World!"

echo `expr length "$str"`  # ``不是单引号,表示执行该命令,输出12
echo `expr index "$str" aWd`  # 输出7,下标从1开始
echo `expr substr "$str" 2 3`  # 输出 ell

整数表达式

a=3
b=4

echo `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)

逻辑表达式

a=3
b=4

echo `expr $a \> $b`  # 输出0,>需要转义
echo `expr $a '<' $b`  # 输出1,也可以将特殊字符用引号引起来
echo `expr $a '>=' $b`  # 输出0
echo `expr $a \<\= $b`  # 输出1

c=0
d=5

echo `expr $c \& $d`  # 输出0
echo `expr $a \& $b`  # 输出3
echo `expr $c \| $d`  # 输出5
echo `expr $a \| $b`  # 输出3
7.read命令

该命令用于从标准输入中读取单行数据

  • -p 后面可以接提示信息
  • -t 后面跟秒数,定义等待时间,超过时间忽略输入命令

-t-p 的顺序不影响实际效果

read -p "Please input your name: " -t 30 name  
# 读入name的值,等待时间30秒
8.echo命令

用于输出字符串

命令格式

echo STRING

显示普通字符串

echo "Hello AC Terminal"
echo Hello AC Terminal  # 引号可以省略

显示转义字符

echo "\"Hello AC Terminal\""  # 注意只能使用双引号,如果使用单引号,则不转义
echo \"Hello AC Terminal\"  # 也可以省略双引号

显示变量

name=yjl
echo "My name is $name"  # 输出 My name is yjl

显示换行

echo -e "Hi\n"  # -e 开启转义
echo "acwing"

输出结果

Hi

acwing

显示不换行

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

输出结果

Hi acwing

显示结果定向至文件

echo "Hello World" > output.txt  # 将内容以覆盖的方式输出到output.txt中

原样输出字符串

name=acwing
echo '$name\"'

输出结果

$name\"

显示命令的执行结果

echo `date`

输出结果

Tue Jul 9 14:35:38 CST 2024
9.printf命令

用于格式化输出,类似于C/C++中的printf函数

示例

printf "%10d.\n" 123  # 占10位,右对齐
printf "%-10.2f.\n" 123.123321  # 占10位,保留2位小数,左对齐
printf "My name is %s\n" "yxc"  # 格式化输出字符串
printf "%d * %d = %d\n"  2 3 `expr 2 \* 3` # 表达式的值作为参数
10.test命令与判断符号[]

expr与逻辑运算符&&||

表达式的exit code为0,表示真;非0,表示假

test命令用于判断文件类型,以及对变量做比较。

表达式的exit code为0,表示真;非0,表示假

例如

test 2 -lt 3  #  为真,返回值为0
echo $?  #  输出上个命令的返回值,输出0
  • 文件类型判断

test -e filename # 判断文件是否存在

测试参数代表意义
-e文件是否存在
-f是否为文件
-d是否为目录
  • 文件权限判断

test -r filename # 判断文件是否可读

测试参数表达意义
-r文件是否可读
-w文件是否可写
-x文件是否可执行
-s文件是否为空文件
  • 整数间的比较

test $a -eq $b # a是否等于b

测试参数代表意义
-eqa是否等于b
-nea是否不等于b
-gta是否大于b
-lta是否小于b
-gea是否大于等于b
-lea是否小于等于b

-eq :equal(相等)

-ne :not equal(不等)

-gt :greater than(大于)

-ge :greater than or equal(大于或等于)

-lt :less than(小于)

-le :less than or equal(小于或等于)

注意:在shell中这些符号只能用于整数的比较,不能用于字符串。

判断符号[]

[]test用法几乎一模一样,更常用于if语句中。

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

例如

[ 2 -lt 3 ]  # 为真,返回值为0

注意:

  • []内的每一项都要用空格隔开
  • 中括号内的变量,最好用双引号括起来
  • 中括号内的常数,最好用单或双引号括起来
11.判断语句

if...then形式,类似于C/C++中的if-else语句

  • 单层if

格式

if condition
then
    语句1
    语句2
    ...
fi

示例

a=3
b=4

if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
then
    echo ${a}在范围内  #  输出结果:3在范围内
fi
  • 单层if-else

格式

if condition
then
	语句1
	语句2
	...
else
	语句1
	语句2
	...
fi

示例

a=3
b=4

if ! [ "$a" -lt "$b" ]
then
    echo ${a}不小于${b}
else
    echo ${a}小于${b}
fi
#  输出结果:3小于4
  • 多层if-elif-else

格式

if condition
then
    语句1
    语句2
    ...
elif condition
then
    语句1
    语句2
    ...
elif condition
then
    语句1
    语句2
else
    语句1
    语句2
    ...
fi

示例

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 其他
fi
#  输出结果:其他

shell脚本的等号间不能有空格

  • case…esac形式

类似于C/C++中的switch语句

格式

case $变量名称 in
    值1)
        语句1
        语句2
        ...
        ;;  # 类似于C/C++中的break
    值2)
        语句1
        语句2
        ...
        ;;
    *)  # 类似于C/C++中的default
        语句1
        语句2
        ...
        ;;
esac

示例

a=4

case $a in
    1)
        echo ${a}等于1
        ;;  
    2)
        echo ${a}等于2
        ;;  
    3)                                                
        echo ${a}等于3
        ;;  
    *)
        echo 其他
        ;;  
esac
#  输出结果:其他
12.循环语句

for…in…do…done

格式:

for var in val1 val2 val3
do
    语句1
    语句2
    ...
done

示例一:

for i in a 2 cc
do
	echo $i
done
#  输出a 2 cc,每个元素一行

示例二:

for file in 'ls'
do
	echo $file
done
#  输出当前路径下的所有文件名,每个文件名一行

示例三:

for i in $(seq 1 10)
do
    echo $i
done
#  输出1-10

示例四:

for i in {a..z}
do
    echo $i
done
#  从a输出到z
#  1..10也可以

for ((…;…;…)) do…done

格式:

for ((expression; condition; expression))
do
    语句1
    语句2
done

示例:

for ((i=1; i<=10; i++))
do
    echo $i
done

while…do…done循环

格式:

while condition
do
    语句1
    语句2
    ...
done

示例

i=1

while [ $i -ne 5 ]
do
   echo $i
   i=$((i+1))
done
#  打印了1到4

until…do…done循环

当条件为真时结束

格式:

until condition
do
    语句1
    语句2
    ...
done

示例:

当输入yes或者YES时结束,否则一直等待输入

until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
    read -p "Please input yes/YES to stop this program: " word
done

break命令

跳出当前一层循环。

break不能跳出case语句

示例

while read name
do
	for((i=1;i<=10;i++))
	do
		case $i in
			8)
				break;
				;;
			*)
				echo $i
				;;
		esac
	done
done

该示例每读入非EOF的字符串,会输出一遍1-7。

该程序可以输入Ctrl+d文件结束符来结束,也可以直接用Ctrl+c杀掉该进程。

continue命令

跳出当前循环。

示例:

for ((i=1;i<=10;i++))
do
    if [ `expr $i % 2` -eq 0 ]
    then
        continue
    fi
    echo $i
done
#  输出1-10的所有奇数
12.函数

类似于C/C++中的函数

return的返回值与C/C++不同,返回的是exit code,取值为0-255,0表示正常结束.

shell偏向面向过程的语言

#! /bin/bash

func() {
    name=yjl
    echo "Hello $name"
}

func
#  输出结果:Hello yjl

获取 return值和stdout
不写return时,默认return 0

func() {
    name=yxc
    echo "Hello $name"

    return 123
}

output=$(func)
ret=$?

echo "output = $output"
echo "return = $ret"

输出结果

output = Hello yxc
return = 123

想获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(function_name)来获取stdout中的结果。

函数的return值可以通过$?来获取。

函数的传入参数

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

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

# /bin/bash

func() {
    if [ $1 -le 0 ] 
    then
        echo 0
        return 0
    fi  

    sum=$(func $(expr $1 - 1))
    echo $(expr $sum + $1)
}

echo $(func 10)  #  输出:55

为什么只输出55不输出其他的值,只要在echo函数后面有$,这个$就会截获掉stdout里的值,使得echo找不到stdout里的数据从而不能输出,在递归往回调用的过程中上一层的echo会被这一层的sum=$(func $(expr $1 - 1))中的第一个$捕获从而没有输出,而最后一层的echo会被函数外的echo $(func 10)$捕获因此是函数外的echo输出的55。

函数内的局部变量

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

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

格式

local 变量名=变量值

例如

#! /bin/bash
func() {
	local name=yjl
	echo $name  #  这里能输出yjl
}
func

echo $name  #  这里无法输出
13.exit命令

exit命令用来退出当前shell进程,并返回一个退出状态

使用$?可以接收这个退出状态

exit退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。

returnexit的共同之处都是返回exit code,区别是return结束当前函数,exit结束整个shell脚本

#! /bin/bash

if [ $# -ne 1 ]  #  如果传入参数个数等于1,则正常退出;否则非正常退出。
then
    echo "arguments not valid"
    exit 1
else
    echo "arguments valid"
    exit 0
fi
14.文件重定向
命令说明
command > file将stdout重定向到file中
command < file将stdin重定向到file中
command >> file将stdout以追加方式重定向到file中

输入和输出重定向

acs@b04c1ca68eb7:~$ echo -e "Hello \c" > output.txt
acs@b04c1ca68eb7:~$ echo "World" >> output.txt 
acs@b04c1ca68eb7:~$ read str < output.txt 
acs@b04c1ca68eb7:~$ echo $str
Hello World

str保存到 output.txt 文件中,而不是显示在屏幕上。

同时重定向stdin和stdout

acs@b04c1ca68eb7:~$ chmod +x test.sh 
acs@b04c1ca68eb7:~$ ./test.sh < input.txt > output.txt
acs@b04c1ca68eb7:~$ cat output.txt 
7

input.txt 文件的内容作为 test.sh 脚本的输入。

test.sh 脚本的输出保存到 output.txt 文件中,而不是显示在屏幕上。

15.引入外部脚本

类似于C/C++中的include操作

语法格式

. filename
或者
source filename

引入的文件可以添加路径,比如使用绝对路径source /home/acs/test1.sh

小技巧:如何将服务器中的文件整体复制出来?
1.退出tmux
2.cat filename:展示filename的文件内容
3.鼠标选中文本开头的若干字符
4.用滚轮滑到文件结尾
5.按住Shift,同时鼠标点击文件结尾,此时会选中文件所有内容
6.Windows/Linux下,按Ctrl + insert可以复制全文;Mac下,按Command + c可以复制全文。

实现斐波那契数列

a[0]=1
a[1]=1

for ((i = 2; i <= n; i ++ ))
do
    x=$(expr $i - 1)
    y=$(expr $i - 2)
    a[$i]=$(expr ${a[$x]} + ${a[$y]})
done

echo ${a[$n]}

在上述代码中,我个人的理解是:$()代表命令替换,在上述代码中即替换了计算的命令;${}代表引用变量,在上述代码中直接引用了一个变量的值。

判断一个文件是否为普通文件

if [ -f "$1" ]
then
    echo "regular file"
fi

-f用于检查文件是否为普通文件

$1是脚本运行时传递给脚本的第一个参数

-f "$1"检查通过脚本运行时传递的第一个参数指定的文件是否存在,并且是不是一个普通文件。

读入参数

标准读入读取用read

接受传入参数用$1 $2

第m个全排列

#! /bin/bash

read n
read m

for ((i=1;i<=n;i++))
do
    st[$i]=0
done

dfs() {
    if [ $1 -eq $n ]
    then
        m=`expr $m - 1`
        if [ $m -eq 0 ]
        then
            echo ${path[@]}  #  `@`用于引用数组`path`所有的元素
            return 0
        fi
        return 1
    fi

    local j=0
    for ((j=1;j<=n;j++))
    do
        if [ ${st[$j]} -eq 0 ]
        then
            path[$1]=$j
            st[$j]=1

            if dfs `expr $1 + 1`
            then
                return 0
            fi
            st[$j]=0
        fi
    done

    return 1
}

dfs 0

文件重定向

#! /bin/bash

input_file=$1  #  接收传入的第一个参数
output_file=$2

read n < $input_file  #  加上`$`获取input_file的值


sum=0

for ((i = 1; i <= n; i ++ ))
do
    sqr=`expr $i \* $i`
    sum=`expr $sum + $sqr`
done

echo $sum > $output_file

shell适用于处理文件,自动化运维,自动化处理,处理服务器

处理字符串,处理具体内容用python

处理大量运算用C++

Day04-SSH

free -h 是一个在Linux和类Unix操作系统中常用的命令,用于显示系统中内存的使用情况,包括物理内存和交换空间

SSH支持自动化操作

.vimrc.tmux.conf复制到新服务器的家目录下,这个服务器就基本配置好了

Web开发的常用框架BootStrap

完成一些步骤后,登录到服务器

ssh myserver

scp传文件

格式:

scp source destination

source路径下的文件复制到destination

一次复制多个

scp source1 source2 destination

复制文件夹:

scp -r ~/tmp myserver:homework/

将本地家目录中的tmp文件夹复制到myserver服务器中的~/homework/目录下。

scp -r myserver:homework .

myserver服务器中的~/homework/文件夹复制到本地的当前路径下。

使用scp配置其他服务器的vim和tmux

scp ~/.vimrc ~/.tmux.conf myserver:

Day05-GIT

托管代码

工作区 -> 暂存区 -> 版本库

基本概念

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

常用命令

  1. git config --global user.name XXX:设置全局用户名

  2. git config --global user.email XXX@XXX.com:设置全局邮箱

  3. git init:将当前目录配置成仓库

  4. git add XXX:将XXX添加到暂存区

  5. git add .:将所有待加入暂存区的文件加入暂存区

  6. git rm --cached XXX:将文件从版本库中移除文件。执行命令后,Git将不再跟踪这个文件,但是在本地该文件仍然存在

  7. git commit -m "给自己看的备注":将暂存区的内容提交到当前分支

  8. git status:查看仓库当前状态

  9. git diff XXX:查看XXX文件相对于暂存区改动了什么内容

  10. git log:查看当前分支的所有版本

  11. git reflog:查看HEAD指针的移动历史

  12. git reset --hard HEAD^或者git reset --hard HEAD~:将代码回滚到上一个版本

    • git reset --hard HEAD^^:回滚两个版本,以此类推
    • git reset --hard HEAD~100:往上回滚100个版本
    • git reset --hard 版本号:回滚到特定版本。版本号是哈希值的前七位
  13. git checkout - XXgit restore XX:将XX文件尚未加入暂存区的修改全部撤销

  14. git add XXX,可以修改两个文件,但暂存区里就放一个文件,然后git commit -m上传到版本库。commit的时候不一定要将所有的修改的上传到版本库

  15. 文件加入到暂存区,后面在本地删除了,也可以将删除这一步加入到暂存区。执行git add XXX,其中的add是将文件的修改加入到暂存区,文件的修改可以是删除。

  16. git restore --staged XXX将XXX文件的修改从文件暂存区里拿出来,比如上一步删去了XXX并且保存到了暂存区,执行此命令可以撤销保存到了暂存区这一步操作。

  17. git restore XXX修改可以回滚,误删也可以回滚

  18. 密钥在根目录下的.ssh文件,再cat id_rsa.pub文件,复制文件里的全部内容就是密钥

  19. 在本地删掉了文件,可以使用git clone XXXXXX为SSH克隆地址。有分支,但是没有引用记录,git reflog中没有内容


多分枝GIT

  1. git checkout -b dev转换到一个新的名为dev的分支
  2. git branch查看所有分支与当前分支
  3. git commit -m "XXX"上传代码到版本库,备注"XXX".commit可以理解为持久化
  4. git checkout XXX,回到之前的目录,目录名为XXX
  5. git merge branch_name:将分支branch_name合并到当前分支上
  6. git branch -d branch_name:删除本地仓库的branch_name分支
  7. 两个不同的分支如果需要合并,用git merge XXX合并会有冲突,需要手动解决。
  8. git push -u(只有第一次需要-u):将当前分支推送到远程仓库
  9. git push origin XXX:将XXX分支推送到远程仓库。
  10. 如果仓库里的东西改动了,需要将仓库里的东西同步到本地的bash,执行git pull操作
  11. 本地和云端是相对独立的。
  12. git remote add origin git@git.acwing.com:xxx/XXX.git:将本地仓库关联到远程仓库
  13. git push --set-upstream origin XXX,向云端上传一个分支,如果云端没有这个分支则创建一个分支
  14. git push -d origin branch_name:删除远程仓库的branch_name分支
  15. git branch --set-upstream-to=origin/branch_name1 branch_name2:将远程的branch_name1分支与本地的branch_name2分支对应
  16. git pull:将云端的内容拉下来
  17. git push -d origin XXX:将云端的XXX分支删掉。-d是指删除的意思。
  18. 将本地同步到云端,执行git push
  19. 想要将云端的XXX分支合并到当前分支,执行git pull origin XXX
  20. git stash:将工作区和暂存区中尚未提交的修改存入栈中
  21. git stash list:看栈里的所有内容
  22. git stash pop:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素
  23. git checkout -b dev:创建一个名为dev的分支
  24. git push --set-upstream origin dev:该命令用于将本地分支推送到远程仓库并设置其作为上游分支以便简化后续的推送和拉取操作。
  25. 新服务器设置公钥:执行ssh-keygen命令,然后一直回车。打开根目录下的.ssh文件夹,cat id_rsa.pub复制其中的内容,然后添加到git中的SSH密钥
  26. 另外的小伙伴可以通过clone将仓库复制到本地,但是只有master一个分支
  27. 小伙伴创建一个分支,然后绑定在云端。git checkout -b dev,创建了一个名为dev的分支,git branch --set-upstream-to=origin/branch_name1 branch_name2,该命令将本地分支 branch_name2 的上游设置为远程仓库 origin 中的 branch_name1 分支,branch_name1是云端的名字,branch_name2是本地的名字
  28. 两个人同时将一个远程仓库设置成本地仓库的上游,一方修改,将结果git push上去,另一方如果想git push将发生冲突,这时候可以git pull,将远程仓库中的内容拉取下来,然后再解决冲突。
  29. rm project -rf:表示强制地递归地删除名为project的目录以及子文件。
  30. git pull,git add,git commit,git push个人开发基本上就四个命令。

Day06-thrift

游戏匹配服务

服务器分为三个部分

  1. game
    • 一般用python
  2. match_system
    • 一般用C++语言,效率高
  3. save_server
  • 定义接口
  • server
  • client

开发定义接口时可以定义一个额外信息。

using namespace std自己写代码的时候可以加,和别人合作时不要加。

能力有限,这一节跳过。

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

管道

概念 :类似于文件重定向,可以将前一个命令的stdout重定向到下一个命令的stdin

注意:

  1. 管道命令仅处理stdout,会忽略stderr
  2. 管道右边的命令必须能接受stdin
  3. 多个管道命令可以串联。

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

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

管道左右两边均为命令,左边有stdout,右边有stdin。

find . -name '*.py' | xargs cat | wc -l:统计当前目录下所有python文件的总行数。其中,namefind命令的一个选项,用于指定要搜索的文件名模式。|是管道操作符,它将前一个命令的输出作为下一个命令的输入。wc 是“word count”的缩写,用于统计文本的行数、单词数或字节数。-l 选项告诉wc只统计行数。

管道比较常用,完成一个任务可以把它拆解成多个步骤,每个步骤都是一个完整的独立的命令,这时可以将这么命令由管道连接起来。

环境变量

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

列出当前环境下的所有环境变量

  • env # 显示当前用户的变量
  • set # 显示当前shell的变量,包括当前用户的变量
  • export # 显示当前导出成用户变量的shell变量

输出某个环境变量的值:

echo $PATH

修改环境变量

为了将对环境变量的修改应用到未来所有环境下,可以将修改命令放到~/.bashrc文件中。修改完~/.bashrc文件后,执行source ~/.bashrc,来将修改应用到当前的bash环境下。

常见的环境变量

HOME:用户的家目录。
PATH:可执行文件(命令)的存储路径。路径与路径之间用:分隔。当某个可执行文件同时出现在多个路径中时,会选择从左到右数第一个路径中的执行。下列所有存储路径的环境变量,均采用从左到右的优先顺序。
LD_LIBRARY_PATH:用于指定动态链接库(.so文件)的路径,其内容是以冒号分隔的路径列表。
C_INCLUDE_PATH:C语言的头文件路径,内容是以冒号分隔的路径列表。
CPLUS_INCLUDE_PATH:CPP的头文件路径,内容是以冒号分隔的路径列表。
PYTHONPATH:Python导入包的路径,内容是以冒号分隔的路径列表。
JAVA_HOME:jdk的安装目录。
CLASSPATH:存放Java导入类的路径,内容是以冒号分隔的路径列表。

常用命令

常见命令

  1. top:查看所有进程的信息

    • 打开后,输入M:按使用内存排序
    • 打开后,输入P:按使用CPU排序
    • 打开后,输入q:退出
  2. df -h:查看硬盘使用情况

  3. free -h:查看内存的使用情况

  4. du -sh:查看当前目录占用的硬盘空间

  5. ps aux:查看所有进程

  6. kill -9 pid:杀死编号为pid的进程。传递某个具体的信号:kill -s SIGTERM pid

  7. netstat -nt:查看所有网络连接

  8. w:列出当前登陆的用户

  9. ping www.baidu.com:检查是否连网

文件权限

文件权限有十位。

第一位表示是不是文件夹

后面三个为一组。分别表示自己、同组的人、其他人。

  • chmod:修改文件权限
  • chmod +x xxx:给xxx添加可执行权限
  • chmod -x xxx:去掉xxx的可执行权限
  • chmod 777 xxx:将xxx的权限改成777。三组,每一个数字可以看成一个二进制数字
  • chmod 777 xxx -R:递归修改整个文件夹的权限

文件检索

  1. find /path/to/directory/ -name '*.py':搜索某个文件路径下的所有*.py文件

  2. grep xxx:从stdin中读入若干行数据,如果某行中包含xxx,则输出该行,并且把XXX标记出来;否则忽略该行。

  3. wc:统计行数、单词数、字节数,可以接受标准读入中的内容

    • 既可以从stdin中直接读入内容;也可以在命令行参数中传入文件名列表;

    • wc -l:统计行数

    • wc -w:统计单词数

    • wc -c:统计字节数

  4. ag xxx:搜索当前目录下的所有文件,检索xxx字符串,会标出所在文件的所在行

  5. 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个字符

  6. sort:将每行内容按字典序排序

    • 可以从stdin中读取多行数据

    • 可以从命令行参数中读取文件名列表

  7. xargs:将stdin中的数据用空格或回车分割成命令行参数

  8. find . -name '*.py' | xargs cat | wc -l:统计当前目录下所有python文件的总行数

文件检索

  1. more:浏览文件内容

    • 回车:下一行
    • 空格:下一页
    • b:上一页
    • q:退出
  2. less:与more类似,功能更全

    • 回车:下一行
    • y:上一行
    • Page Down:下一页
    • Page Up:上一页
    • q:退出
  3. head -3 xxx:展示xxx的前3行内容
    同时支持从stdin读入内容

  4. tail -3 xxx:展示xxx末尾3行内容
    同时支持从stdin读入内容

history:展示当前用户的历史操作。内容存放在~/.bash_history

工具

  1. md5sum:计算md5哈希值

    • 可以从stdin读入内容
    • 也可以在命令行参数中传入文件名列表;
  2. time command:统计command命令的执行时间

  3. ipython3:交互式python3环境。可以当做计算器,或者批量管理文件。

  4. ! echo "Hello World":!表示执行shell脚本

  5. watch -n 0.1 command:每0.1秒执行一次command命令

  6. tar:压缩文件

    • tar -zcvf xxx.tar.gz /path/to/file/*:压缩
    • tar -zxvf xxx.tar.gz:解压缩
  7. diff xxx yyy:查找文件xxx与yyy的不同点

安装软件

  1. sudo command:以root身份执行command命令
  2. apt-get install xxx:安装软件
  3. pip install xxx --user --upgrade:安装python

作业笔记

  1. find . -name '*.cpp' | wc -l > ans.txt

    .表示当前目录,寻找当前目录下名称以.cpp为结尾的文件,通过管道传给wc -l命令,统计有几行,然后通过文件重定向写入ans.txt

  2. 如何将所有python文件输出

    find . -name '*.py' | xargs cat

  3. 统计py文件包含thrift字符串的总行数

find . -name '*.py' | xargs cat | grep thrift | wc -l > ans2.txt

  1. 删除当前目录下的所有py文件

find . -name '*.py' | xargs rm

  1. cat scores.txt | cut -d ' ' -f 1 > names.txt

    获取scores.txt文件,cut指的是一个用来剪切文本一部分的命令,-d ' '告诉cut用空格作为字符分隔符,-f 1告诉cnt仅提取每个分割后的字段序列中的第一个字段

  2. 取出第一个字段,排序后写入name.txt

    cat scores.txt cut -d ' ' -f 1 | sort > name

  3. 将scores.txt文件的前5行写入top.txt,后4行写入bottom.txt

    head -5 scores.txt > top.txt

    tail -4 scores.txt > bottom.txt

  4. md5sum scores.txt | cut -c 1-32 > ans.txt

    计算scores.txt文件的md5sum,将结果写入ans.txt。注意:ans.txt文件中只包含长度为32的md5sum

  5. ipython3可以进入python的环境,可以计算很大的数字

    python的环境下,可以在shell语句前加一个!,便可以使其执行shell命令

Day08-租云服务器及配环境

推荐:1vCPU 2GB 租服务器只要关系这两个

镜像选Ubuntu

推荐租ECS,可定制化。

阿里云,腾讯云,华为云。

端口

HTTP(80):如果有网站,则为访问网站的端口

HTTPS(443):加密端口 HTTP+证书

SSH(22):SSH登录


登录自己的服务器

租到的服务器默认用户是root

登录执行ssh root@公网IP

查看CPU配置cat /proc/cpuinfo .

root用户权限太大,一般开发建议创建一个新用户,给这个用户分配一个sudo权限

创建用户

  • adduser yjl
  • usermod -aG sudo yjl:分配sudo权限

配置免密登录

在根目录下.ssh文件夹中找到config文件,新增加用户信息

Host server1
  HostName 47.96.153.121                          
  User yjl

配置完成后登录,只需要执行ssh server1即可

给毛坯服务器配环境

执行sudo apt-get updatesudo apt-get install tmux

再返回到AC Terminal,执行scp .bashrc .vimrc .tmux.conf server1:命令。

装docker

由于国内docker被封了,所以只能翻墙

使用翻墙软件,节点选择在美国。参考这篇博客,执行命令进行下载。

PS:如果出现permission denied则为权限不足,在命令前加入sudo

下载完成后配置国内镜像

我自己的是Ubuntu,执行以下命令

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xwba9jvt.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

这样就配置完成了

执行sudo docker pull nginx进行测试,如果没有配置国内镜像,则执行命令的速度很慢,配置成功后速度将变快。

执行docker --version,检查下载的版本。

安装一些命令

安装tree命令,sudo apt-get install tree

安装pythonsudo apt-get install ipython3

租的服务器可以重装系统。

租服务器,后面在服务器装入docker,docker容易迁移,是未来主要的工作场所。

docker

为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入安装中自动创建的docker用户组。执行命令sudo usermod -aG docker $USER

镜像(images)

docker -> image(镜像) -> container(容器)

相同的镜像生成的容器都一样,每一个容器都是完全独立的云端服务器

迁移的时候是容器生成镜像,生成的镜像可以下载下来的,是一个压缩包,可以传到其他服务器上,然后将这个镜像压缩包加载到docker里面,用镜像生成新的容器。

  1. docker pull ubuntu:20.04:拉取一个镜像,每个镜像都是:名称.版本号
  2. docker images:列出本地 Docker 主机上存储的所有 Docker 镜像
  3. sudo docker rmi ubuntu:20.04:用于删除本地 Docker 主机上指定的 Docker 镜像
  4. docker [container] commit CONTAINER IMAGE_NAME:TAG:创建某个container的镜像
  5. docker save -o ubuntu_20_04.tar ubuntu:20.04:将镜像ubuntu:20.04导出到本地文件ubuntu_20_04.tar中,ubuntu_20_04.tar中加载出来,压缩包有了之后给其添加可读命令,执行sudo chmod +r ubuntu_20_04.tar
  6. docker load -i ubuntu_20_04.tar:将镜像ubuntu:20.04从本地文件ubuntu_20_04.tar中加载出来。如果只有一台服务器,可以这样操作:将本地的镜像删除,然后再执行load命令,即可重新恢复原来的镜像。

容器(container)

  1. docker [container] create -it ubuntu:20.04:利用镜像ubuntu:20.04创建一个容器。

  2. docker ps -a:查看本地的所有容器,如果不加-a,则只会列出运行中的容器。

  3. docker [container] start CONTAINER:启动容器

  4. docker [container] stop CONTAINER:停止容器

  5. docker [container] restart CONTAINER:重启容器

  6. docker [contaienr] run -itd ubuntu:20.04:创建并启动一个容器

  7. docker [container] attach CONTAINER:进入容器先按Ctrl + p,再按Ctrl + q可以挂起容器。如果直接按Ctrl + D会将容器关掉。进入一个容器默认来到root,一个容器可以理解成一个新的服务器。只能进入一个创建并且在运行的容器。命令中的CONTAINER是容器的NAMES

  8. docker [container] exec CONTAINER COMMAND:在容器中执行命令。例如sudo docker exec lucid_faraday ls

  9. docker [container] rm CONTAINER:删除容器。不能删除一个正在运行的容器。

  10. docker container prune:删除所有已停止的容器

  11. docker export -o xxx.tar CONTAINER:将容器CONTAINER导出到本地文件xxx.tar中

  12. docker import xxx.tar image_name:tag:将本地文件xxx.tar导入成镜像,并将镜像命名为image_name:tag

  13. docker export/importdocker save/load的区别:

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

  15. docker stats:查看所有容器的统计信息,包括CPU、内存、存储、网络等信息

  16. docker cp xxx CONTAINER:xxxdocker cp CONTAINER:xxx xxx表示目录。在本地和容器间复制文件

  17. docker rename CONTAINER1 CONTAINER2:重命名容器

  18. docker update CONTAINER --memory 500MB:修改容器限制

docker可以理解成服务器里的虚拟机。

将自己搭建的服务器配置成统一的风格

配置统一的docker环境。

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密码

注意:root用户只能修改密码,不能设置密码。

docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0会做一下几件事

  1. 使用名为 docker_lesson 且标签为 1.0 的 Docker 镜像启动一个新的容器。
  2. 将宿主机的端口 20000 映射到容器的端口 22,这样你就可以通过宿主机的 20000 端口来访问容器内的 SSH 服务。
  3. 将新启动的容器命名为 my_docker_server
  4. 以交互式、后台运行的方式启动容器,并分配一个伪终端。

sudo ssh root@localhost -p 20000:通过 SSH登录到名为 localhost 的主机上,并且指定了端口号为 20000 的 SSH 服务

如果要登录自己服务器的20000端口,要在云服务器的ECS界面将端口放开,在控制台里点自己服务器,将20000端口放行,目的输入20000,源选择0.0.0.0/0,这个表示所有IP。

在阿里云如何开放端口,可以参考这篇文章[阿里云开放端口教程]

可以在任意地方登录自己在云服务器上搭建的云服务器,ssh root@XXX -p 20000XXX代表公网IP。在docker的环境下搭建服务器方便迁移,如果不使用docker,在各个平台的服务器中可以做到迁移,但是跨平台就不方便了。

可以添加用户yjladduser yjlusermod -aG sudo yjl.

在自己搭建的这个服务器下,可以在这个服务器继续装docker,可以说是无线套娃。

返回自己最初的服务器,实现免密登录。

.ssh/config下继续写入

Host server1
    HostName 47.96.153.121
    User yjl 

Host server2
    HostName 47.96.153.121
    User yjl 
    Port 20000

注意:自己搭建的这个要加上端口

执行ssh-copy-id server2,随后只需要执行ssh server2,即可登录自己创建的服务器。

安装一些东西,apt-get install sudoapt-get install tmux

配置一下环境,将源服务器中的一些文件传到新搭建的服务器上,scp .bashrc .vimrc .tmux.conf server2:

通过以上的步骤可以让所有服务器变成和源服务器统一的风格。
网络等信息
16. docker cp xxx CONTAINER:xxxdocker cp CONTAINER:xxx xxx表示目录。在本地和容器间复制文件
17. docker rename CONTAINER1 CONTAINER2:重命名容器
18. docker update CONTAINER --memory 500MB:修改容器限制

docker可以理解成服务器里的虚拟机。

将自己搭建的服务器配置成统一的风格

配置统一的docker环境。

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密码

注意:root用户只能修改密码,不能设置密码。

docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0会做一下几件事

  1. 使用名为 docker_lesson 且标签为 1.0 的 Docker 镜像启动一个新的容器。
  2. 将宿主机的端口 20000 映射到容器的端口 22,这样你就可以通过宿主机的 20000 端口来访问容器内的 SSH 服务。
  3. 将新启动的容器命名为 my_docker_server
  4. 以交互式、后台运行的方式启动容器,并分配一个伪终端。

sudo ssh root@localhost -p 20000:通过 SSH登录到名为 localhost 的主机上,并且指定了端口号为 20000 的 SSH 服务

如果要登录自己服务器的20000端口,要在云服务器的ECS界面将端口放开,在控制台里点自己服务器,将20000端口放行,目的输入20000,源选择0.0.0.0/0,这个表示所有IP。

在阿里云如何开放端口,可以参考这篇文章[阿里云开放端口教程]

可以在任意地方登录自己在云服务器上搭建的云服务器,ssh root@XXX -p 20000XXX代表公网IP。在docker的环境下搭建服务器方便迁移,如果不使用docker,在各个平台的服务器中可以做到迁移,但是跨平台就不方便了。

可以添加用户yjladduser yjlusermod -aG sudo yjl.

在自己搭建的这个服务器下,可以在这个服务器继续装docker,可以说是无线套娃。

返回自己最初的服务器,实现免密登录。

.ssh/config下继续写入

Host server1
    HostName 47.96.153.121
    User yjl 

Host server2
    HostName 47.96.153.121
    User yjl 
    Port 20000

注意:自己搭建的这个要加上端口

执行ssh-copy-id server2,随后只需要执行ssh server2,即可登录自己创建的服务器。

安装一些东西,apt-get install sudoapt-get install tmux

配置一下环境,将源服务器中的一些文件传到新搭建的服务器上,scp .bashrc .vimrc .tmux.conf server2:

通过以上的步骤可以让所有服务器变成和源服务器统一的风格。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值