Shell是什么?
- shell不仅是命令行,也可以是GUI
- shell是操作系统和用户交互的“接口”
- 一般来说,shell是unix shell,也可以认为是CLI
命令是什么?
- 命令本质是一个程序
- 这些程序具有发起系统调用(system call)的能力
- 编写shell脚本,就是编排这些程序的执行
- shell语法解析器负责一行一行的解析shell命令
常用的shell解释器
- bash
- sh
- zsh
- cmd
- powerShell
- Wsl(window subsystem of linux )
常见bash命令有哪些
-
文件新建
- touch 新建文件
- mkdir 新建目录
-
文件删除
-
rmdir 删除文件夹
-
rm
- rm ./single-file 删除单个文件
- rm -r ./a-dir 递归删除(删除目录)
- rm -rf ./a-dir-with-file 递归强制删除
-
-
文件移动
-
mv
- mv ./source/a.txt ./target
- mv -f ./source/a.txt ./target 移动并强制覆盖同名文件
- mv -n ./source/a.txt ./target 移动并不覆盖同名文件
- mv -n ./source/a.txt ./source/b.txt 重命名
-
cp
- cp ./source/a.txt ./target 复制
- cp -R ./source/ ./target/ 递归复制(复制目录)
-
-
文件查看
- cat
cat ./package.json查看文件 - head
head -n ~/.logs/service-a.log查看文件的前10行 - tail
tail -n ~/.logs/service-a.log查看文件的后10行
- cat
-
文件编辑
-
nano
nano是Linux上最简单的文本编辑器,操作简单,功能也比较初级
-
vi / vim
vi是一款功能强大的编辑器,vim是vi的加强版
-
-
进程相关
-
ps
- ps 查看当前登录用户的进程
- ps -ax 查看所有进程
-
lsof
- lsof 查看所有网络相关文件
- lsof -p 2333 查看pid=2333的进程打开的文件
-
top 显示实时的进程状态
-
kill
- kill pid 杀死进程
- kill -9 pid 强杀进程
kill命令实际上并不是真的去杀死进程,本质是想进程发送信号。例如 kill -s SIGUSR1 34534 实际上可以调用node应用,因为node会在SIGUSR1进入调试模式。
优雅退出的原理就是监听SIGTERM信号,并递归退出子进程。
kill -9 发送SIGKILL信号,容易导致进程没有完成自己的清理工作就已经退出,出现僵尸进程。
-
-
其他
-
grep 对结果的每一行进行筛选
lsof -i | grep LISTEN找到所有被监听的端口,当不知道哪些端口被占用时,可以使用
-
awk 对结果列的筛选
- docker rm (docker ps -a | awk 'NR>1 {print 1}') 删除所有docker容器
-
bash编程基础
全局变量
COURSE=ENGINEERING
export COURSE=ENGINEERING
可以不用export =两边不能有空格
局部变量
local COURSE=ENGINEERING
函数内部才有用
环境变量
$PATH:指定命令的搜索路径
$HOME:指定用户的主工作目录(即用户登录Linux系统时候的默认目录)
$HISTSIZE:指保存历史命令记录的条数
$LOGNAME:指当前用户的登录名
$HOSTNAME:指主机的名称
$SHELL:指当前用户用的哪种Shell
$LANG/$LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量
$MAIL:指当前用户的邮箱存放目录
变量基本类型
#String
ASTRING=abcdefg
ASTRING="hello"
#Number 不能直接使用数字 否则会被认为是字符串
ANUMBER=$[1 + 1]
ANUMBER=$(( 1 + 1 ))
#Array
AARRAY=(what's the day today)
AARRAY=(1 2 3 4 5)
AARRAY[1]=0
## zsh下标起始为1 bash下标起始为0
运算
组合
ASTRING=world
ANUMBER=2
#####
STR="Hello $ASTRING"
echo $STR
# Hello world
SEQ=(1 $ANUMBER 3 4)
echo $SEQ
# 1 2 3 4
数学运算符
ANUMBER=$(1 + 2)
ANUMBER=$(1 - 2)
ANUMBER=$(1 * 2)
ANUMBER=$(1 / 2)
条件语句
if then
if condition1
then
command1
elif condition2
then
command2
else
commandN
if
case
case $VAR in
condition1)
command1
;;
condition2)
echo command2
;;
*)
echo command3
;;
esac
比较符
-z var #检查变量var是否为空
-d file #检查file是否存在并是一个目录
-e file #检查file是否存在
-f file #检查file是否存在并为一个文件
-r file #检查file是否存在并可读
-s file #检查file是否存在并非空
-w file #检查file是否存在并可写
-x file #检查file是否存在并可执行
-O file #检查file是否存在并属于当前用户
-G file #检查file是否存在并默认组与当前用户相同
file1 -nt file2 #检查file1是否比file2新
file1 -ot file2 #检查file1是否比file2旧
举个例子
## 判断是否是一个文件
if [ -f "./file"]
then echo "it's a file"
else echo "it's a dir"
fi
for循环
for index in 1 2 3 4 5;do
echo "index="$index
done
for ((i=0; i<5; i++));do
echo $i
done
while循环
while(($i<=10));do
echo $i
done
函数
函数的定义
function custom_echo() {
local prefix="input is"
# $n 表示传入的第n个实参
# 此处判断是否有参数$1传入
if [ -z $1 ];then
echo "no input"
else
echo "$prefix $1"
fi
return 0
}
函数的调用与返回值
custom_echo #unkonw
custom_echo abc #input is abc
custom_echo abc #input is abc
echo $? #0
shell状态码,是shell运行每个命令都使用状态码(exit status)来告诉shell它完成了处理。退出状态码是一个0-255之间的整数值,在命令执行结束时由命令传入给shell。可以在命令执行结束后,立即使用$?捕获。
其他特殊变量
$# #传递到脚本或函数的参数个数
$* #以一个单字符串显示所有向脚本传递的参数
$$ #脚本运行的当前进程id
$! #后台运行的最后一个进程的id号
$@ #与$*相同,但是使用时加引号,并在引号中返回每个参数
$- #显示shell使用的当前选项,与set命令功能相同
$? #显示最后命令的退出状态码。0表示没有错误,其他任何值表示有错误
重定向
什么是重定向?
- 重定向,全程是I/O重定向,默认情况下,bash程序从终端接收输入,并在终端打印输出(标准输入、标准输出)
- 如果你想改变输入的来源,或是输出的目的地,那么就需要使用"重定向"
怎么使用
只需要记住四个符号
command > file #将输出重定向到file
command < file #将输入重定向到file
command << file #将输入重定向到file的部分内容
command >> file #将输出以追加的方式重定向到file
ls > ./ls.log #将ls命令的输出记录在./ls.log文件中(重复会被覆盖)
ls >> ./ls.log #将不会被覆盖,而是在末尾追加
交互式程序
- echo / read
echo "xxx" #打印并换行
echo -n "xxx" #打印且不换行
read var #读取输入,存入变量var
read -n 1 var #读取输入的第1个字符,存入变量var
举例:
echo -n "What's your first name?";\
read firstName;\
echo -n "What's your second name?";\
read secondName;\
echo "$firstName $secondName";
编写一个bash命令,每次输入文件夹名称,直到退出
function cdAndLs() {
cd $1;
ls;
}
function getPackageName() {
echo -n "input packageName...";\
read packageName;\
return 0;
}
getPackageName;
echo $packageName;
while [ -d $packageName ];do
cdAndLs $packageName;
getPackageName;
done;
echo "this is a file;"