Linux基础命令
常用终端命令
快捷键
- 取消命令,并且换行:Ctrl + c
- 清空本行命令:Ctrl + u
- Tab 可以补全命令和文件名,如果补全不了快速按两下 Tab 键,可以显示备选选项
- 复制文本Ctrl + Ins
- 粘贴文本Shift + Ins
- 退出服务:Ctrl + d
文件处理
- 列出当前目录下所有文件,蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件
1
ls
常用参数
-l:列出长数据串,包含文件的属性与权限数据等
-a:列出全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用)
-d:仅列出目录本身,而不是列出目录的文件数据 - 显示当前路径
1
pwd
- 进入XXX目录下
1
2
3
4
5cd XXX
#返回上层目录
cd ..
#返回上一次目录
cd - - 将XXX文件复制成YYY,XXX和YYY可以是一个路径,比如…/dir_c/a.txt,表示上层目录下的dir_c文件夹下的文件a.txt
1
cp XXX YYY
常用参数
-i:覆盖前询问(使前面的 -n 选项失效)
-n:不要覆盖已存在的文件(使前面的 -i 选项失效) - 创建目录XXX
1
mkdir XXX
常用参数
-p:此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多个目录
-v:每次创建新目录都显示信息 - 删除文件,支持简单的正则表达式*通配符
1
2
3
4#删除普通文件
rm XXX
#删除文件夹
rm XXX -r常用参数
-f:忽略不存在的文件,从不给出提示
-r:指示rm将参数中列出的全部目录和子目录均递归地删除
-v:详细显示进行的步骤 - 将XXX文件移动到YYY,和cp命令一样,XXX和YYY可以是一个路径;重命名也是用这个命令
1
mv XXX YYY
常用参数
-b:若需覆盖文件,则覆盖前先行备份
-f:force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖
-i:若目标文件 (destination) 已经存在时,就会询问是否覆盖 - 创建一个文件
1
touch XXX
- 展示文件XXX中的内容
1
cat XXX
- 查看"当前工作目录"的完整路径。
1
pwd
文件检索
which 可执行文件名称:搜索某个系统命令的位置,并且返回第一个搜索结果。find /path/to/directory/ -name '*.py':搜索某个文件路径下的所有*.py文件grep xxx:从stdin中读入若干行数据,如果某行中包含xxx,则输出该行;否则忽略该行。wc:统计行数、单词数、字节数常用参数
-l:统计行数
-w:统计单词数
-c:统计字节数tree:展示当前目录的文件结构1
2tree /path/to/directory/ # 展示某个目录的文件结构
tree -a # 展示隐藏文件ag xxx:搜索当前目录下的所有文件,检索xxx字符串cut:分割一行内容1
2
3
4echo $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:将每行内容按字典序从小到大排序xargs:将stdin中的数据用空格或回车分割成命令行参数1
2# 管道
find . -name '*.py' | xargs cat | wc -l # 统计当前目录下所有python文件的总行数
文件权限设置
- 改变linux系统文件或目录的访问权限
1
2
3
4#增加文件所有用户组可执行权限
chmod a+x test.log
#删除所有用户的可执行权限
chmod a-x test.log常用参数
<权限范围>+<权限设置> 使权限范围内的目录或者文件具有指定的权限
<权限范围>-<权限设置> 删除权限范围的目录或者文件的指定权限
<权限范围>=<权限设置> 设置权限范围内的目录或者文件的权限为指定的值- 权限范围:
- u :目录或者文件的当前的用户
- g :目录或者文件的当前的群组
- o :除了目录或者文件的当前用户或群组之外的用户或者群组
- a :所有的用户及群组
- 权限代号:
- r:读权限,用数字4表示
- w:写权限,用数字2表示
- x:执行权限,用数字1表示
- -:删除权限,用数字0表示
- 权限范围:
系统状况
top:查看所有进程的信息(Linux的任务管理器)- 打开后,输入
M:按使用内存排序 - 打开后,输入
P:按使用CPU排序 - 打开后,输入
q:退出
- 打开后,输入
df -h:查看硬盘使用情况free -h:查看内存使用情况du -sh:查看当前目录占用的硬盘空间ps aux:查看所有进程kill -9 pid:杀死编号为pid的进程- 传递某个具体的信号:
kill -s SIGTERM pid
- 传递某个具体的信号:
netstat -nt:查看所有网络连接w:列出当前登陆的用户ping www.baidu.com:检查是否连网
查看文件内容
more:浏览文件内容- Enter:下一行
- Space:下一页
- b:上一页
- q:退出
less:与more类似,功能更全- Enter:下一行
- y:上一行
- Page Down:下一页
- Page Up:上一页
- q:退出
head -3 xxx:展示xxx的前3行内容tail -3 xxx:展示xxx末尾3行内容
apt命令
其他操作
- 压缩和打包文件。
1
2
3
4tar [必要参数] [选择参数] [文件]
tar -cvf test.tar test.log # 仅打包,不压缩!
tar -zcvf test.tar.gz test.log # 打包后,以 gzip 压缩
tar -zcvf test.tar.bz2 test.log # 打包后,以 bzip2 压缩 - 解压文件
1
tar -zxvf test.tar.gz
md5sum:计算md5哈希值time command:统计command命令的执行时间ipython3:交互式python3环境。可以当做计算器,或者批量管理文件。watch -n 0.1 command:每0.1秒执行一次command命令adduser jezer:创建用户jezerusermod -aG sudo jezer:给用户jezer分配sudo权限passwd:修改密码
tumx
tmux:新建一个session,其中包含一个window,window中包含一个pane,pane里打开了一个shell对话框。- 按下Ctrl + B后手指松开:进入tmux命令模式
- 按下Ctrl + B后手指松开,然后按%:将当前pane左右平分成两个pane。
- 按下Ctrl + B后手指松开,然后按"(注意是双引号"):将当前pane上下平分成两个pane。
- Ctrl + D:关闭当前pane;如果当前window的所有pane均已关闭,则自动关闭window;如果当前session的所有window均已关闭,则自动关闭session。
- 按下Ctrl + B后手指松开,然后按方向键:选择相邻的pane。
- 按住Ctrl + B的同时按方向键,可以调整pane之间分割线的位置。
- 按下Ctrl + B后手指松开,然后按z:将当前pane全屏/取消全屏。
- 按下Ctrl + B后手指松开,然后按d:挂起当前session。
tmux a:打开之前挂起的session。- 按下Ctrl + B后手指松开,然后按s:选择其它session。
↑:选择上一项 session/window/pane
↓:选择下一项 session/window/pane
→:展开当前项 session/window
←:闭合当前项 session/window
ESC:退出选择 - 按下Ctrl + B后手指松开,然后按c:在当前session中创建一个新的window。
- 按下Ctrl + B后手指松开,然后按w:选择其他window。
- 按下Ctrl + B后手指松开,然后按PageUp:翻阅当前pane内的内容。
- 在tmux中选中文本时,需要按住shift键。(仅支持Windows和Linux,不支持Mac,不过该操作并不是必须的,因此影响不大)
- tmux中复制/粘贴文本的通用方式:
(1) 按下Ctrl + B后松开手指,然后按[
(2) 用鼠标选中文本,被选中的文本会被自动复制到tmux的剪贴板
(3) 按下Ctrl + B后松开手指,然后按],会将剪贴板中的内容粘贴到光标处
vim
模式
- 一般命令模式(默认模式):类似于打游戏放技能,按不同字符,即可进行不同操作。可以复制、粘贴、删除文本等。
- 编辑模式: 在一般命令模式里按下i,会进入编辑模式。按下ESC会退出编辑模式,返回到一般命令模式。
- 命令行模式:在一般命令模式里按下:/?三个字母中的任意一个,会进入命令行模式。命令行在最下面。可以查找、替换、保存、退出、配置编辑器等。
操作
以下操作均在一般命令模式(默认模式)进行
i:进入编辑模式ESC:进入一般命令模式h或左箭头键:光标向左移动一个字符j或向下箭头:光标向下移动一个字符k或向上箭头:光标向上移动一个字符l或向右箭头:光标向右移动一个字符n<Space>:n表示数字,按下数字后再按空格,光标会向右移动这一行的n个字符0或功能键[Home]:光标移动到本行开头$或功能键[End]:光标移动到本行末尾G:光标移动到最后一行:n或nG:n为数字,光标移动到第n行gg:光标移动到第一行,相当于1Gn<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:将全文代码格式化:noh关闭查找关键词高亮Ctrl + q:当vim卡死时,可以取消当前正在执行的命令Ctrl + s:禁用编辑
异常处理
每次用vim编辑文件时,会自动创建一个.filename.swp的临时文件。
如果打开某个文件时,该文件的swp文件已存在,则会报错。此时解决办法有两种:
- 找到正在打开该文件的程序,并退出
- 直接删掉该swp文件即可
shell
概论
- Linux系统中一般默认使用bash,文件开头需要写
#! /bin/bash,指明bash为脚本解释器。 - 运行方式
- 作为可执行文件
1
2
3
4
5
6
7acs@9e0ebfcd82d7:~$ chmod +x test.sh # 使脚本具有可执行权限
acs@9e0ebfcd82d7:~$ ./test.sh # 当前路径下执行
Hello World! # 脚本输出
acs@9e0ebfcd82d7:~$ /home/acs/test.sh # 绝对路径下执行
Hello World! # 脚本输出
acs@9e0ebfcd82d7:~$ ~/test.sh # 家目录路径下执行
Hello World! # 脚本输出 - 用解释器执行
1
2acs@9e0ebfcd82d7:~$ bash test.sh
Hello World! # 脚本输出
- 作为可执行文件
注释
- 单行注释
1
2# 这是一行注释
echo 'Hello World' # 这也是注释 - 多行注释(其中EOF可以换成其它任意字符串),不建议使用
变量
- 定义变量,不需要加
$符号,例如:注意1
2
3name1='jezer' # 单引号定义字符串
name2="jezer" # 双引号定义字符串
name3=jezer # 也可以不加引号,同样表示字符串=两侧不能有空格
定义变量的时候变量都是字符串,但当变量需要是整数时,会自动把变量转换成整数 - 使用变量,需要加上
$符号,或者${}符号。花括号是可选的,主要为了帮助解释器识别变量边界。1
2
3
4name=jezer
echo $name # 输出jezer
echo ${name} # 输出jezer
echo Hello, ${name} # 输出Hello, jezer - 使用
readonly或者declare可以将变量变为只读。1
2
3
4name=jezer
readonly name
declare -r name # 两种写法均可
name=abc # 会报错,因为此时name只读declare
declare [+/-][rxi][变量名称=设置值] 或 declare -f
参数说明:- +/- "-“可用来指定变量的属性,”+"则是取消变量所设的属性。
- -f 仅显示函数。
- r 将变量设置为只读。
- x 指定的变量会成为环境变量,可供shell以外的程序来使用。
- i [设置值]可以是数值,字符串或运算式。
unset可以删除变量。被声明为只读的变量无法被1
2
3name=jezer
unset name
echo $name # 输出空行unset删除- 自定义变量(局部变量)改成环境变量(全局变量):
1
2
3acs@9e0ebfcd82d7:~$ name=jezer # 定义变量
acs@9e0ebfcd82d7:~$ export name # 第一种方法
acs@9e0ebfcd82d7:~$ declare -x name # 第二种方法 - 环境变量改为自定义变量:
1
2acs@9e0ebfcd82d7:~$ export name=jezer # 定义环境变量
acs@9e0ebfcd82d7:~$ declare +x name # 改为自定义变量
字符串
- 字符串可以用单引号,也可以用双引号,也可以不用引号。字符串中,不加引号和双引号效果相同
- 单引号与双引号的区别:
- 单引号中的内容会原样输出,不会执行、不会取变量;
- 双引号中的内容可以执行、可以取变量;
1
2
3name=jezer # 不用引号
echo 'hello, $name \"hh\"' # 单引号字符串,输出 hello, $name \"hh\"
echo "hello, $name \"hh\"" # 双引号字符串,输出 hello, jezer "hh" - 获取字符串长度
1
2name="jezer"
echo ${#name} # 输出3 - 提取子串
1
2name="hello, jezer"
echo ${name:0:5} # 提取从0开始的5个字符
默认变量
- 文件参数变量
在执行shell脚本时,可以向脚本传递参数。$1是第一个参数,$2是第二个参数,以此类推。特殊的,$0是文件名(包含路径)。例如:
创建文件test.sh:然后执行该脚本:1
2
3
4
5
6
7
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4向脚本传递参数时,参数个数超过一位需要用大括号括起来。1
2
3
4
5
6
7acs@9e0ebfcd82d7:~$ chmod +x test.sh
acs@9e0ebfcd82d7:~$ ./test.sh 1 2 3 4
文件名:./test.sh
第一个参数:1
第二个参数:2
第三个参数:3
第四个参数:4 - 其它参数相关变量
| 参数 | 说明 |
|---|---|
| $# | 代表文件传入的参数个数,如上例中值为4 |
| $* | 由所有参数构成的用空格隔开的字符串,如上例中值为"$1 $2 $3 $4" |
| $@ | 每个参数分别用双引号括起来的字符串,如上例中值为"$1" “$2” “$3” “$4” |
| $$ | 脚本当前运行的进程ID |
| $? | 上一条命令的退出状态(注意不是stdout,而是exit code)。0表示正常退出,其他值表示错误 |
| $(command) | 返回command这条命令的stdout(可嵌套) |
| `command` | 返回command这条命令的stdout(不可嵌套) |
数组
- 数组中可以存放多个不同类型的值,只支持一维数组,初始化时不需要指明数组大小。
- 数组下标从0开始。
- 数组用小括号表示,元素之间用空格隔开。例如:也可以直接定义数组中某个元素的值:
1
array=(1 abc "def" jezer)
1
2
3
4array[0]=1
array[1]=abc
array[2]="def"
array[3]=jezer - 读取数组中某个元素的值
1
2
3
4
5array=(1 abc "def" jezer)
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]} - 读取整个数组
1
2
3array=(1 abc "def" jezer)
echo ${array[@]} # 第一种写法
echo ${array[*]} # 第二种写法 - 数组长度,类似于字符串
1
2
3array=(1 abc "def" jezer)
echo ${#array[@]} # 第一种写法
echo ${#array[*]} # 第二种写法 - 在读取整个数组时,未定义的部分就不会显示。比如定义了array[0]array[1]array[2]array[1000],利用echo ${array[@]}输出时,只会显示我们定义的数组那4个元素的值,其长度结果是4,而不是1000
expr命令
- expr命令用于求表达式的值,格式为:
expr 表达式 - 表达式说明:
- 用空格隔开每一项
- 用反斜杠放在shell特定的字符前面(发现表达式运行错误时,可以试试转义)
- 对包含空格和其他特殊字符的字符串要用引号括起来
- expr会在stdout中输出结果。如果为逻辑关系表达式,则结果为真,stdout为1,否则为0。
- expr的exit code:如果为逻辑关系表达式,则结果为真,exit code为0,否则为1。
- 字符串表达式
length STRING:返回STRING的长度index STRING CHARSET:CHARSET中任意单个字符在STRING中最前面的字符位置,下标从1开始。如果在STRING中完全不存在CHARSET中的字符,则返回0。substr STRING POSITION LENGTH:返回STRING字符串中从POSITION开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串。
1
2
3
4str="Hello World!"
echo `expr length "$str"` # ``不是单引号,表示执行该命令,输出12
echo `expr index "$str" aWd` # 输出7,下标从1开始
echo `expr substr "$str" 2 3` # 输出 ell - 整数表达式
expr支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。+ -加减运算。两端参数会转换为整数,如果转换失败则报错。* / %乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。()可以该表优先级,但需要用反斜杠转义
1
2
3
4
5
6
7
8a=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) - 逻辑关系表达式
|、&、<、<=、=、==、!=、>=、>
1
2
3
4
5
6
7
8
9
10
11
12a=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
read命令
read命令用于从标准输入中读取单行数据。当读到文件结束符时,exit code为1,否则为0。- 参数说明
- -p: 后面可以接提示信息
- -t:后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令
1 | acs@9e0ebfcd82d7:~$ read name # 读入name的值 |
echo命令
显示普通字符串
1
2echo "Hello AC Terminal"
echo Hello AC Terminal # 引号可以省略显示转义字符
1
2echo "\"Hello AC Terminal\"" # 注意只能使用双引号,如果使用单引号,则不转义
echo \"Hello AC Terminal\" # 也可以省略双引号显示变量
1
2name=jezer
echo "My name is $name" # 输出 My name is jezer显示换行
1
2echo -e "Hi\n" # -e 开启转义
echo "jezer"输出结果:
1
2
3Hi
jezer\\ \a \b \c \d \e \f \n \r \t \v这些是要在有 - e 的时候才能起作用, 其他时候的转义是不用- e也能转义的。显示不换行
1
2echo -e "Hi \c" # -e 开启转义 \c 不换行
echo "jezer"输出结果:
1
Hi jezer
显示结果定向至文件
1
echo "Hello World" > output.txt # 将内容以覆盖的方式输出到output.txt中
原样输出字符串,不进行转义或取变量(用单引号)
1
2name=jezer
echo '$name\"'输出结果
1
$name\"
显示命令的执行结果
1
echo `date`
输出结果:
1
Wed Sep 1 11:45:33 CST 2021
printf命令
printf命令用于格式化输出,类似于C/C++中的printf函数。默认不会在字符串末尾添加换行符。- 命令格式:
printf format-string [arguments...]
1 | printf "%10d.\n" 123 # 占10位,右对齐 |
输出结果
1 | 123. |
判断命令
test语句
逻辑运算符&&和||具有短路原则:
- expr1 && expr2:当expr1为假时,直接忽略expr2
- expr1 || expr2:当expr1为真时,直接忽略expr2
- 表达式的exit code为0,表示真;为非零,表示假。(与C/C++中的定义相反)
test命令
- 在命令行中输入man test,可以查看test命令的用法。
- test命令用于判断文件类型,以及对变量做比较。
- test命令用exit code返回结果,而不是使用stdout。0表示真,非0表示假。
1
2test 2 -lt 3 # 为真,返回值为0
echo $? # 输出上个命令的返回值,输出01
2
3
4
5
6acs@9e0ebfcd82d7:~$ ls # 列出当前目录下的所有文件
homework output.txt test.sh tmp
acs@9e0ebfcd82d7:~$ test -e test.sh && echo "exist" || echo "Not exist"
exist # test.sh 文件存在
acs@9e0ebfcd82d7:~$ test -e test2.sh && echo "exist" || echo "Not exist"
Not exist # testh2.sh 文件不存在文件类型判断
1
test -e filename # 判断文件是否存在
测试参数 代表意义 -e 文件是否存在 -f 是否为文件 -d 是否为目录 文件权限判断
1
test -r filename # 判断文件是否可读
测试参数 代表意义 -r 文件是否可读 -w 文件是否可写 -x 文件是否可执行 -s 是否为非空文件 整数间的比较
1
test $a -eq $b # a是否等于b
测试参数 代表意义 -eq a是否等于b -ne a是否不等于b -gt a是大于b -lt a是小于b -ge a是大于等于b -le a是小于等于b 字符串比较
测试参数 代表意义 test -z STRING 判断STRING是否为空,如果为空,返回true test -n STRING 判断STRING是否为非空空,如果非空,返回true test str1 == str2 判断str1是否等于str2 test str1 != str2 判断str1是否不等于str2 多重条件判定
1
test -r filename -a -x filename
测试参数 代表意义 -a 两条件是否同时成立 -o 两条件是否至少一个成立 ! 取反。如 test ! -x file,当file不可执行时,返回true 判断符号[]
- []与test用法几乎一模一样,更常用于if语句中。另外[[]]是[]的加强版,支持的特性更多。
- []内的每一项都要用空格隔开
- 中括号内的变量,最好用双引号括起来
- 中括号内的常数,最好用单或双引号括起来
1
2[ 2 -lt 3 ] # 为真,返回值为0
echo $? # 输出上个命令的返回值,输出01
2
3name="hello jezer"
[ $name == "hello jezer" ] # 错误,等价于 [ hello jezer == "hello jezer" ],参数太多
[ "$name" == "hello jezer" ] # 正确
if语句
单层if
1
2
3
4
5
6if condition
then
语句1
语句2
...
fi1
2
3
4
5
6a=3
b=4
if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
then
echo ${a}在范围内
fi单层if-else
1
2
3
4
5
6
7
8
9
10if condition
then
语句1
语句2
...
else
语句1
语句2
...
fi1
2
3
4
5
6
7
8
9a=3
b=4
if ! [ "$a" -lt "$b" ]
then
echo ${a}不小于${b}
else
echo ${a}小于${b}
fi多层if-elif-elif-else
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19if condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
else
语句1
语句2
...
fi1
2
3
4
5
6
7
8
9
10
11
12
13a=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 其他
ficase…esac形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17case $变量名称 in
值1)
语句1
语句2
...
;; # 类似于C/C++中的break
值2)
语句1
语句2
...
;;
*) # 类似于C/C++中的default
语句1
语句2
...
;;
esac1
2
3
4
5
6
7
8
9
10
11
12
13
14
15a=4
case $a in
1)
echo ${a}等于1
;;
2)
echo ${a}等于2
;;
3)
echo ${a}等于3
;;
*)
echo 其他
;;
esac
循环语句
for…in…do…done
1
2
3
4
5
6for var in val1 val2 val3
do
语句1
语句2
...
done输出a 2 cc,每个元素一行:
1
2
3
4for i in a 2 cc
do
echo $i
done输出当前路径下的所有文件名,每个文件名一行:
1
2
3
4for file in `ls`
do
echo $file
done输出1-10
1
2
3
4for i in $(seq 1 10)
do
echo $i
done{1…10} 或者 {a…z}
1
2
3
4for i in {a..z}
do
echo $i
done
for ((…;…;…)) do…done
1
2
3
4
5for ((expression; condition; expression))
do
语句1
语句2
done1
2
3
4
5# 输出1-10,每个数占一行:
for ((i=1; i<=10; i++))
do
echo $i
donewhile…do…done循环
1
2
3
4
5
6while condition
do
语句1
语句2
...
done1
2
3
4
5# 文件结束符为Ctrl+d,输入文件结束符后read指令返回false。
while read name
do
echo $name
doneuntil…do…done循环
1
2
3
4
5
6until condition
do
语句1
语句2
...
done1
2
3
4
5# 当用户输入yes或者YES时结束,否则一直等待读入。
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " word
donebreak命令
- 跳出当前一层循环,注意与C/C++不同的是:break不能跳出case语句。
1
2
3
4
5
6
7
8
9
10
11
12
13
14while read name
do
for ((i=1;i<=10;i++))
do
case $i in
8)
break
;;
*)
echo $i
;;
esac
done
done- 该示例每读入非EOF的字符串,会输出一遍1-7。
continue命令
1
2
3
4
5
6
7
8for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done该程序输出1-10中的所有奇数。
死循环的处理方式
- 如果Terminal可以打开该程序,则输入
Ctrl+c即可。 - 否则可以直接关闭进程:
- 使用
top命令找到进程的PID - 输入
kill -9 PID即可关掉此进程
- 使用
- 如果Terminal可以打开该程序,则输入
函数
bash中的函数类似于C/C++中的函数,但return的返回值与C/C++不同,返回的是exit code,取值为0-255,0表示正常结束。- 如果想获取函数的输出结果,可以通过
echo输出到stdout中,然后通过$(function_name)来获取stdout中的结果。 - 函数的
return值可以通过$?来获取。
1 | [function] func_name() { # function关键字可以省略 |
1 | # 不获取 return值和stdout值 |
输出结果:
1 | Hello jezer |
1 | # 获取 return值和stdout值 |
输出结果:
1 | output = Hello jezer |
1 | # 函数的输入参数 |
输出结果:
1 | 55 |
1 | # 函数内的局部变量 |
输出结果:
1 | jezer |
exit命令
- exit命令用来退出当前shell进程,并返回一个退出状态;使用$?可以接收这个退出状态。
- exit命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
- exit退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
1 | if [ $# -ne 1 ] # 如果传入参数个数等于1,则正常退出;否则非正常退出。 |
1 | acs@9e0ebfcd82d7:~$ chmod +x test.sh |
文件重定向
重定向命令列表
命令 说明 command > file 将stdout重定向到file中 command < file 将stdin重定向到file中 command >> file 将stdout以追加方式重定向到file中 command n> file 将文件描述符n重定向到file中 command n>> file 将文件描述符n以追加方式重定向到file中 输入和输出重定向
1
2
3
4
5
6echo -e "Hello \c" > output.txt # 将stdout重定向到output.txt中
echo "World" >> output.txt # 将字符串追加到output.txt中
read str < output.txt # 从output.txt中读取字符串
echo $str # 输出结果:Hello World同时重定向stdin和stdout
- 创建bash脚本
1
2
3read a
read b
echo $(expr "$a" + "$b")- 创建input.txt,里面的内容为
1
23
4- 执行命令
1
2
3
4acs@9e0ebfcd82d7:~$ chmod +x test.sh # 添加可执行权限
acs@9e0ebfcd82d7:~$ ./test.sh < input.txt > output.txt # 从input.txt中读取内容,将输出写入output.txt中
acs@9e0ebfcd82d7:~$ cat output.txt # 查看output.txt中的内容
7
引入外部脚本
1 | . filename # 注意点和文件名之间有一个空格 |
ssh
远程登录服务器
1
2
3
4# 远程登录服务器
ssh user@hostname
# 默认登录端口号为22。如果想登录某一特定端口:
ssh user@hostname -p 22配置文件,创建文件
~/.ssh/config,然后在文件中输入:1
2
3
4
5
6
7
8Host myserver1
HostName IP地址或域名
User 用户名
Port 20002
Host myserver2
HostName IP地址或域名
User 用户名之后再使用服务器时,可以直接使用别名myserver1、myserver2。
创建密钥:
1
ssh-keygen
然后一直回车即可。
执行结束后,~/.ssh/目录下会多两个文件:- id_rsa:私钥
- id_rsa.pub:公钥
复制密钥:
1
ssh-copy-id myserver
执行命令:
1
ssh user@hostname command
1
2# 单引号中的$i可以求值
ssh myserver 'for ((i = 0; i < 10; i ++ )) do echo $i; done'1
2# 双引号中的$i不可以求值
ssh myserver "for ((i = 0; i < 10; i ++ )) do echo $i; done"双引号是在本地服务器进行转义了,所以传过去命令不是echo $a,而是echo 1,单引号传过去的是echo $a
scp传文件
1
2
3
4
5
6
7
8
9
10# 将source路径下的文件复制到destination中
scp source destination
# 一次复制多个文件
scp source1 source2 destination
# 复制文件夹
scp -r ~/tmp myserver:/home/acs/
# 指定服务器的端口号
scp -P 22 source1 source2 destination
# 使用scp配置其他服务器的vim和tmux
scp ~/.vimrc ~/.tmux.conf myserver:scp的-r -P等参数尽量加在source和destination之前配置新服务器的工作环境
将AC Terminal的配置传到新服务器上:1
scp .bashrc .vimrc .tmux.conf server_name: # server_name需要换成自己配置的别名
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 commit -m "给自己看的备注信息":将暂存区的内容提交到当前分支git status:查看仓库状态git log:查看当前分支的所有版本git push -u (第一次需要-u以后不需要):将当前分支推送到远程仓库git clone git@git.acwing.com:xxx/XXX.git:将远程仓库XXX下载到当前目录下git branch:查看所有分支和当前所处分支
- 查看命令
git diff XX:查看XX文件相对于暂存区修改了哪些内容git status:查看仓库状态git log:查看当前分支的所有版本git log --pretty=oneline:用一行来显示git reflog:查看HEAD指针的移动历史(包括被回滚的版本)git branch:查看所有分支和当前所处分支git pull:将远程仓库的当前分支与本地仓库的当前分支合并
- 删除命令
git rm --cached XX:将文件从仓库索引目录中删掉,不希望管理这个文件git restore --staged xx:将xx从暂存区里移除git checkout — XX或git restore XX:将XX文件尚未加入暂存区的修改全部撤销
- 代码回滚
git reset --hard HEAD^或git reset --hard HEAD~:将代码库回滚到上一个版本git reset --hard HEAD^^:往上回滚两次,以此类推git reset --hard HEAD~100:往上回滚100个版本git reset --hard 版本号:回滚到某一特定版本(7位)
- 远程仓库
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 push --set-upstream origin branch_name:设置本地的branch_name分支对应远程仓库的branch_name分支git push -d origin branch_name:删除远程仓库的branch_name分支git checkout -t 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 branch branch_name:创建新分支git branch:查看所有分支和当前所处分支git checkout -b branch_name:创建并切换到branch_name这个分支git checkout branch_name:切换到branch_name这个分支git merge branch_name:将分支branch_name合并到当前分支上git branch -d branch_name:删除本地仓库的branch_name分支git push --set-upstream origin branch_name:设置本地的branch_name分支对应远程仓库的branch_name分支git push -d origin branch_name:删除远程仓库的branch_name分支git checkout -t 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分支对应
- stash暂存
git stash:将工作区和暂存区中尚未提交的修改存入栈中git stash apply:将栈顶存储的修改恢复到当前分支,但不删除栈顶元素git stash drop:删除栈顶存储的修改git stash pop:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素git stash list:查看栈中所有元素
docker
- 为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入安装中自动创建的docker用户组(可以参考官方文档):
1
sudo usermod -aG docker $USER
- 镜像(images)
docker pull ubuntu:20.04:拉取一个镜像docker images:列出本地所有镜像docker image rm ubuntu:20.04或docker rmi ubuntu:20.04:删除镜像ubuntu:20.04docker [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中加载出来
- 容器(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 [contaienr] run -itd ubuntu:20.04:创建并启动一个容器docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0:创建并运行docker_lesson:1.0镜像,端口转发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:tagdocker 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:修改容器限制docker
- 增加容器的映射端口:80与443
- 登录容器,关闭所有运行中的任务
- 登录运行容器的服务器,然后执行:
1
2
3
4
5
6docker commit CONTAINER_NAME IMAGE_NAME:TAG # 将容器保存成镜像,将CONTAINER_NAME替换成容器名称,IMAGE_NAME:TAG为保存后的镜像名称
docker stop CONTAINER_NAME # 关闭容器
docker rm CONTAINER_NAME # 删除容器
# 使用保存的镜像重新创建容器
docker run -p 20000:22 -p 8000:8000 -p 80:80 -p 443:443 --name CONTAINER_NAME -itd IMAGE_NAME:TAG - 去云服务器控制台,在安全组配置中开放80和443端口。




