Shell脚本基础
文章目录
一、Shell是什么
Shell是一个命令行解释器,它能够通过接收 应用程序/用户 的命令,去调用操作系统内核,从而完成程序指令。Shell是用户操作Linux系统的指令,同时,Shell还是一个功能相当强大的编程语言,具有易编写,易调试,灵活性强的特点。
二、Shell基本语法
1.变量
-
全局变量:
- $HOME:当前用户的home目录
- $PWD: 当前工作目录名称, 相当于pwd
- $SHELL:当前Shell解析器
- $USER:当前用户名称
- $PATH:系统环境变量
[tang@aliyun module]$ echo $HOME
/home/tang
[tang@aliyun module]$ echo $PWD
/opt/module
[tang@aliyun module]$ echo $SHELL
/bin/bash
[tang@aliyun module]$ echo $USER
tang
[tang@aliyun bin]$ $PATH
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/module/jdk1.8.0_291/bin:/opt/module/hadoop-3.1.3/bin
-
自定义变量:
- (1)定义变量:变量=值 (没有空格)
- (2)撤销变量:unset 变量
- (3)声明静态变量:readonly变量,注意:不能unset
- (4)自定义全局变量,加上 export
[root@aliyun bin]$ A=1
[root@aliyun bin]$ echo $A
1
[tang@aliyun bin]$ readonly B=2
[tang@aliyun bin]$ echo $B
2
[tang@aliyun bin]$ unset B
bash: unset: B: cannot unset: readonly variable
-
特殊变量:
- (1)$#:获取所有输入参数个数,常用于循环
- (2)$*: 代表命令行中所有的参数,把所有的参数看成一个整体("$*"为整体)
- (3)$@:也代表命令行中所有的参数,把每个参数区分对待("$@"也为个体)
- (4)$?:最后一次执行的命令的返回状态,如果正确返回0,否则非0
- (5)$n:$0为当前文件名,$1,$2…$9,${10},${11}…依次为传递到脚本的参数
[tang@aliyun myshell]$ vim params.txt
[tang@aliyun myshell]$ cat params.txt
#!/bin/bash
echo $#
echo $*
echo $@
echo $?
echo $1
[tang@aliyun myshell]$ bash params.txt han tang zhonghua
3
han tang zhonghua
han tang zhonghua
0
han
2.流程控制
条件判断
(1) [ condition ] (注意condition前后要有空格, 非空为true, 空为false)
[tang@aliyun myshell]$ [ ]
[tang@aliyun myshell]$ echo $?
1
[tang@aliyun myshell]$ [ tang ]
[tang@aliyun myshell]$ echo $?
0
(2)常用判断条件
1:字符串比较
= 是否相等
( = 前后都有空格)
-z 字符串长度是否为零
2:整数比较
-lt 小于(less than);
-le 小于等于(less equal);
-eq 等于(equal);
-gt 大于(greater than);
-ge 大于等于(greater equal);
-ne 不等于(Not equal)
3:按照文件权限进行判断
-r 有读的权限(read);
-w 有写的权限(write);
-x 有执行的权限(execute)
4:按照文件类型进行判断
-e 文件存在(existence);
-f 文件存在并且是一个常规的文件(file);
-d 文件存在并是一个目录(directory)
[tang@aliyun data]$ [ tang = tang ]
[tang@aliyun data]$ echo $?
0
[tang@aliyun data]$ [ -z tang ]
[tang@aliyun data]$ echo $?
0
[tang@aliyun data]$ [ 1 -lt 2 ]
[tang@aliyun data]$ echo $?
0
[tang@aliyun data]$ [ 1 -gt 2 ]
[tang@aliyun data]$ echo $?
1
[tang@aliyun data]$ ll
total 8
-rw-r--r-- 1 root root 4 Jul 7 12:16 han.txt
-rw-r--r-- 1 tang tang 5 Jul 7 12:17 tang.txt
[tang@aliyun data]$ [ -r tang.txt ]
[tang@aliyun data]$ echo $?
0
[tang@aliyun data]$ [ -w han.txt ]
[tang@aliyun data]$ echo $?
1
[tang@aliyun data]$ [ -e zhonghua.txt ]
[tang@aliyun data]$ echo $?
1
[tang@aliyun data]$ [ -f tang.txt ]
[tang@aliyun data]$ echo $?
0
[tang@aliyun data]$
if判断
-
基本语法:
- if [ 条件判断式 ]; then
- 程序
- fi
- 或者
- if [ 条件判断式 ]
- then
- 程序
- fi 注意事项:
- (1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
- (2)if后要有空格
# 输入一个字符串,如果是han,则输出 "强汉",如果是tang,
# 则输出 "盛唐",如果是其它,输出 "中华复兴"。
[tang@aliyun myshell]$ cat if.sh
#!/bin/bash
if [ $1 = "han" ]
then
echo "强汉"
elif [ $1 = "tang" ]
then
echo "盛唐"
else
echo "中华复兴"
fi
[tang@aliyun myshell]$ bash if.sh han
强汉
[tang@aliyun myshell]$ bash if.sh tang
盛唐
[tang@aliyun myshell]$ bash if.sh now
中华复兴
case判断
-
基本语法:
- case $变量名 in
- “值1”)
- 如果变量的值等于值1,则执行程序1
- ;;
- “值2”)
- 如果变量的值等于值2,则执行程序2
- ;;
- *)
- 如果变量的值都不是以上的值,则执行此程序
- ;;
- esac 注意事项:
- (1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
- (2)双分号“;;”表示命令序列结束,相当于java中的break
- (3)最后的“*)”表示默认模式,相当于java中的default。
# 输入一个字符串,如果是han,则输出 "强汉",如果是tang,
# 则输出 "盛唐",如果是其它,输出 "中华复兴"。
[tang@iZwz945acgf8n138r7qd7pZ myshell]$ cat case.sh
#!/bin/bash
case $1 in
"han")
echo "强汉"
;;
"tang")
echo "盛唐"
;;
*)
echo "中华复兴"
;;
esac
[tang@aliyun myshell]$ bash case.sh han
强汉
[tang@aliyun myshell]$ bash case.sh tang
盛唐
[tang@aliyun myshell]$ bash case.sh now
中华复兴
for循环
-
1. 语法1:
- for (( 初始值;循环控制条件;变量变化 ))
- do
- 程序
- done
# 从1加到100
[tang@aliyun myshell]$ cat for1.sh
#!/bin/bash
sum=0
for ((i=i; i<=100; i=i+1))
do
sum=$[$sum+$i]
done
echo $sum
[tang@aliyun myshell]$ bash for1.sh
5050
-
2. 语法2:
- for 变量 in 值1 值2 …
- do
- 程序
- done
# 打印所有输入参数
[tang@aliyun myshell]$ cat for2.sh
#!/bin/bash
for i in $*
do
echo $i
done
[tang@aliyun myshell]$ bash for2.sh han tang zhonghua
han
tang
zhonghua
while循环
-
基本语法:
- while [ 条件判断式 ]
- do
- 程序
- done 注意事项:
- while和条件判断式之间要空格
# 从1加到100
[tang@aliyun myshell]$ cat while.sh
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo $sum
[tang@aliyun myshell]$ bash while.sh
5050
3.函数
系统函数
-
1. basename:
- basename [string / pathname] [suffix]
- basename命令删掉所有的前缀包括最后一个(‘/’)字符后,将字符串显示出来
- suffix为后缀,若指定suffix,会将 pathname或者string 中的suffix去掉
[tang@aliyun myshell]$ basename basename.sh
basename.sh
[tang@aliyun myshell]$ basename basename.sh .sh
basename
-
2. dirname:
- dirname 文件绝对路径
- 从给定的包含绝对路径的文件名中去除文件名(非目录的部分),
- 然后返回剩下的路径(目录的部分)。
[tang@aliyun myshell]$ dirname /home/tang/myshell/test.txt
/home/tang/myshell
自定义函数
-
基本语法:
- [ function ] funname[( )]
- {
- Action;
- [return int;]
- }
- funname 经验技巧:
- (1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。
-
(2)函数返回值,只能通过 $? 获得,可以显示加return返回,如果不加,
将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
# 计算两个输入参数的和
[tang@aliyun myshell]$ cat function.sh
#!/bin/bash
function sum()
{
sum=$[ $1 + $2 ]
echo $sum
}
sum $1 $2
[tang@aliyun myshell]$ bash function.sh 1 2
3
三.shell工具
grep
grep 是一个文本过滤工具,通常和管道联合使用快速查询关键字。
egrp 支持扩展正则
options部分
- -v 显示不被pattern匹配到的行
- -o 仅显示匹配到的字符串
- -n 显示匹配的行号
- -i 忽略字符大小写
- -A n 显示后n行
- -B n 显示前n行
- -C n 显示上下n行
- -r 递归查找
sed
-
简介:
- sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。 基本语法:
- sed [选项参数] ‘command’ filename
- 选项参数:
- -e:直接在指令列模式上进行sed的动作编辑(多个sed操作)
- command:
- a :新增,a的后面可以接字串,在下一行出现
- d:删除
- s:查找并替换
# 准备数据
[tang@aliyun myshell]$ cat sed.txt # 准备数据
shell linux java
is is is
yyds nb dl
[tang@aliyun myshell]$ sed '3a my my my' sed.txt # 每一列is下面添加my
shell linux java
is is is
my my my
yyds nb dl
[tang@aliyun myshell]$ sed '/is/d' sed.txt # 删除所有包含is的列
shell linux java
yyds nb dl
[tang@aliyun myshell]$ sed 's/is/always/g' sed.txt # 将所有is替换为always
shell linux java
always always always
yyds nb dl
[tang@aliyun myshell]$ sed -e '2d' -e 's/java/hadoop/' sed.txt # 将第2行删除并替换java为hadoop
shell linux hadoop
is is is
yyds nb dl
awk
-
简介:
- awk一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。 基本语法:
- awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
- pattern:
- 表示AWK在数据中查找的内容,就是匹配模式,正则匹配
- action:
- 在找到匹配内容时所执行的一系列命令,如print输出
- 选项参数:
- F:指定输入文件折分隔符,默认为空格
- v:赋值一个用户定义变量
- awk的内置变量:
- FILENAME:文件名称
- NR:已读的记录数(行数)
- NF:浏览记录的域的个数(切割后,列的个数)
[tang@aliyun myshell]$ cat passwd # 准备数据
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
root:x:3:4:adm:/var/adm:/sbin/nologin
[tang@aliyun myshell]$ awk -F : '/^root/ {print $7}' passwd # 索passwd文件以root关键字开头的所有行,并输出该行的第7列。
/bin/bash
/sbin/nologin
[tang@aliyun myshell]$ awk -F : '/^root/ {print $1","$7}' passwd # 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
root,/bin/bash
root,/sbin/nologin
[tang@aliyun myshell]$ awk -F : 'BEGIN{print "learn"} {print $1","$7} END{print "shell"}' passwd # 只显示passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名"learn",在最后一行添加"shell"。
learn
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
root,/sbin/nologin
shell
[tang@aliyun myshell]$ awk -F : -v i=1 '{print $3+i}' passwd # 将passwd文件中的用户id增加数值1并输出(id为第三列)
1
2
3
4
[tang@aliyun myshell]$ awk -F : '{print FILENAME","NR","NF}' passwd # 统计passwd文件名,每行的行号,每行的列数
passwd,1,7
passwd,2,7
passwd,3,7
passwd,4,7
[tang@aliyun myshell]$ ifconfig eth0 | grep inet | awk -F " " '{print $2}' # 切割ip
172.19.99.251
[tang@aliyun myshell]$ cat sed.txt
shell linux java
is is is
yyds nb dl
[tang@aliyun myshell]$ awk '/^$/ {print NR}' sed.txt # 查询sed.txt中空行所在的行号
2
cut
-
简介:
- cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出 基本语法:
- cut [选项参数] filename
- 选项参数:
- -d:分隔符,按照指定分隔符分割列,默认分隔符是制表符
- -f:列号,提取第几列
- 选项参数:
- -d:分隔符,按照指定分隔符分割列,默认分隔符是制表符
- -f:列号,提取第几列 注意事项:
- the delimiter must be a single character,分隔符为单字符
[tang@aliyun myshell]$ cat cut.txt # 准备数据
shell linux java
is is is
yyds nb dl
[tang@aliyun myshell]$ cut -d " " -f 1 cut.txt # 切割第一列
shell
is
yyds
[tang@aliyun myshell]$ cut -d " " -f 2- cut.txt # 切割2,3列
linux java
is is
nb dl
[tang@aliyun myshell]$ grep shell cut.txt | cut -d " " -f 1 #cut.txt中切割出shell
shell
[tang@aliyun myshell]$ echo $PATH | cut -d : -f 2-
/usr/local/bin:/usr/sbin:/usr/bin:/opt/module/jdk1.8.0_291/bin:/opt/module/hadoop-3.1.3/bin
[tang@aliyun myshell]$ ifconfig eth0 | grep inet | cut -d " " -f 10 # 切割ifconfig中的ip
172.19.99.251
read
-
简介:
- read可以获取用户键盘录入的数据,并使用到后续程序中 基本语法:
- read(选项)(参数)
- 选项:
- -p:指定读取值时的提示符;
- -t:指定读取值时等待的时间(秒)
- 参数:
- 变量:指定读取值的变量名
# 提示5秒内,读取控制台输入的名称
[tang@aliyun myshell]$ cat read.sh
#!/bin/bash
read -t 5 -p "请输入您要说的话:" INPUT
echo $INPUT
[tang@aliyun myshell]$ bash read.sh
请输入您要说的话:强汉盛唐
强汉盛唐
[tang@iZwz945acgf8n138r7qd7pZ myshell]$
sort
-
简介:
- sort命令是在Linux里非常有用,它能够对文件进行排序,并将排序结果标准输出。 基本语法:
- sort(选项)(参数)
- 参数:
- 指定待排序的文件列表
- 选项:
- -n:依照数值的大小排序(数字/字母都可)
- -r:以相反的顺序来排序
- -t:设置排序时所用的分隔字符
- -k:指定需要排序的列
[tang@aliyun myshell]$ cat sort.txt # 准备数据
han:40:5.4
tang:20:8.2
zhonghua:50:2.3
[tang@aliyun myshell]$ sort -t ":" -nrk 3 sort.txt # 按照“:”分割后的第三列倒序排序。
tang:20:8.2
han:40:5.4
zhonghua:50:2.3
[tang@aliyun myshell]$ sort -t ":" -nrk 1 sort.txt # 字母也可以排序哦
tang:20:8.2
han:40:5.4
zhonghua:50:2.3
四.常用命令
- ps :
ps -ef:查看所有进程信息,主要是端口号
ps -ef | grep -v grep | grep -i HiveMetastore | awk "{print $2} :获取指定进程端口号 - jps :
jps:查看所有java进程(显示格式:端口号 进程名)
jps -ml:显示格式:端口号 执行程序全类名 - date :
date -d ‘-1 day’:系统时间前一 天/月/年/时…
date -d + %F:yyyy-MM-dd 日期格式 - sed :
sed -i ‘s/替换前内容/替换后内容/g’ 替换文件路径 : 全文替换 - nohup >/dev/null 2>&1 & :
nohup 输出日志的启动命令 >/dev/null 2>&1 & :nuhup 即no hang up(不挂起)可以让后台不挂起执行, & 让命令在后台执行,终端退出后命令仍旧执行(其实和nohup效果一样) >/dev/null 2>&1 不管什么类型都输出黑洞。加起来就能实现后台运行程序, 退出不中止,不保存日志。 - dirname basename
dirname 文件路径 :获取文件的完整目录
basename 文件路径 [文件后缀] :获取文件名(加上第二个参数则去掉指定后缀)
五.零散知识
- ’ ’ 、“ ” 和 ` `:
(1)单引号不取变量值
(2)双引号取变量值
(3)反引号`,执行引号中命令
(4)双引号内部嵌套单引号,取出变量值
(5)单引号内部嵌套双引号,不取出变量值 - 换行:
linux命令行中,直接换行会被解析成执行命令,在本行命令末使用 空格 + \ 可以避过解析为执行
六.便捷工具
-
sshpass
使用 ssh 远程连接服务器的时候,总是需要输入密码,比较麻烦,使用 sshpass可以命令行或脚本上,显式输入密码,不需要额外啊输入密码
#1.安装/解压 略 #2.编译安装软件 tangshengcai@MacBook-Pro ~ % ./configure tangshengcai@MacBook-Pro ~ % make && make install #3.一步登录 tangshengcai@MacBook-Pro ~ % sshpass -p "用户密码" ssh -v -o 'ProxyCommand=ncat --proxy-type socks5 --proxy 跳板机ip:端口 --proxy-auth "跳板机用户名:密码" %h %p' 用户名@远程机器ip
下载链接: https://sourceforge.net/projects/sshpass/files/latest/download
总结
Shell易理解易上手,而经过多年的发展,shell命令已经丰富多样,博主会将常用到的Shell命令或者脚本信息,陆陆续续的更新到文件博文上面,记录下来,方便速记查阅。