文章目录
-
- 父子shell
-
- 自定义变量.
- [source . 在当前shell执行, ./abc.sh在子shell执行](#source . 在当前shell执行, ./abc.sh在子shell执行)
- 常用shell
-
- 数值计算.
- 只读变量
- [unset 撤销变量, readonly不可.](#unset 撤销变量, readonly不可.)
- shell脚本文件读取参数
-
- [1 获取第一个参数](#1 获取第一个参数)
- [0 获取脚本文件名](#0 获取脚本文件名)
- [$# 获取输入参数的个数](# 获取输入参数的个数)
- [\* @ 获取所有参数](#* @ 获取所有参数)
- [? 获取脚本返回值 . 0正确 其他默认错误. 除非脚本有特殊return](#? 获取脚本返回值 . 0正确 其他默认错误. 除非脚本有特殊return)
- 查询变量
- [test [ 语句 ] 判断返回值](#test [ 语句 ] 判断返回值)
- 数值比较&&文件权限
- 流程控制.
- [read 读取控制台输入.](#read 读取控制台输入.)
- 内置函数
- 自定义函数
- 备份
-
- [编写执行备份的脚本文件 daily_archive.sh](#编写执行备份的脚本文件 daily_archive.sh)
- 加入定时任务
- 文本处理工具
shell命令解析器, 将shell命令解释称linux 内核可以理解的指令. redhat系列主流使用/bin/bash.
修改环境变量所在的文件, 环境变量未生效. source file 刷新一下就生效了.
source 是 Shell 环境中的一个内置指令,主要用于 在当前 Shell 会话中直接执行脚本文件,而不是创建子 Shell 运行。它的核心作用是 修改当前 Shell 的环境变量或状态。
. source 命令 都是在当前shell执行. 可以获取设置的局部变量.
父子shell
开子shell与不开子shell的区别就在于,环境变量的继承关系,如在子shell中设置的当前变量,父shell是不可见的。
[root@aaaccbb bin]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 413890 413889 0 09:55 pts/0 00:00:00 -bash
root 422690 413890 0 10:29 pts/0 00:00:00 ps -f
[root@aaaccbb bin]# bash # 进入子shell
[root@aaaccbb bin]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 413890 413889 0 09:55 pts/0 00:00:00 -bash
root 422740 413890 0 10:29 pts/0 00:00:00 bash
root 422796 422740 0 10:30 pts/0 00:00:00 ps -f
[root@aaaccbb bin]# exit
exit
[root@aaaccbb bin]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 413890 413889 0 09:55 pts/0 00:00:00 -bash
root 423031 413890 0 10:31 pts/0 00:00:00 ps -f
[root@aaaccbb bin]#
自定义变量.
# a = 2 #错误,不能有空格; a=2,正确
#a="hello world"
#a='hello word'
# echo $a #打印设置的局部环境变量
#export a #提升为全局变量.
#bash #进入子shell
#a='2333' #修改变量
#echo $a
2333
# exit #退出子shell
# echo $a #子shell变化, 其他shell看不到.
hello world
source . 在当前shell执行, ./abc.sh在子shell执行
[root@aaaccbb bin]# new_var='12333'
[root@aaaccbb bin]# echo $new_var
12333
[root@aaaccbb opt]# vi abc.sh
[root@aaaccbb opt]# . abc.sh
12333
[root@aaaccbb opt]# source abc.sh
12333
[root@aaaccbb opt]# chmod +x abc.sh
[root@aaaccbb opt]# ./abc.sh
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
echo $new_var
常用shell
数值计算.
数值计算要用 ((expr)) 或者 [expr ]
expr 也可, 一般不使用.
root@aaaccbb opt]# echo $((1+5))
6
[root@aaaccbb opt]# echo 1+5 # 默认作为字符串处理
1+5
[root@aaaccbb opt]#
[root@aaaccbb opt]# expr 1 + 2 #一般不用expr
3
[root@aaaccbb opt]# expr 2 * 5
expr: syntax error: unexpected argument 'abc.sh'
[root@aaaccbb opt]# expr 2 \* 5
10
[root@aaaccbb opt]#
[root@aaaccbb opt]# echo $[5*2]
10
[root@aaaccbb opt]# echo $((5*2))
10
[root@aaaccbb opt]#
只读变量
[root@aaaccbb opt]# readonly b=5
[root@aaaccbb opt]# b=10
-bash: b: readonly variable
[root@aaaccbb opt]#
unset 撤销变量, readonly不可.
[root@aaaccbb opt]# name='12 45'
[root@aaaccbb opt]# echo $name
12 45
[root@aaaccbb opt]# unset name
[root@aaaccbb opt]# echo $name
[root@aaaccbb opt]#
shell脚本文件读取参数
0 打印脚本文件名,1---$9,打印对应位置的参数, 但是必须使用双引号进行包裹,或者不用任何包裹. 使用单引号不能读取到值.
$1 获取第一个参数
绝对不能使用单引号进行包裹, 可以不进行任何包裹. 要进行字符串拼接 可以使用双引号进行包裹.
[root@aaaccbb opt]# ./hello.sh xiaoli
hello $1
hello xiaoli
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat hello.sh
#!/bin/bash
echo 'hello $1'
echo "hello $1"
$0 获取脚本文件名
[root@aaaccbb opt]# ./hello.sh
./hello.sh
[root@aaaccbb opt]# cat hello.sh
#!/bin/bash
echo "$0"
$# 获取输入参数的个数
[root@aaaccbb opt]# ./hello.sh 1 2 3 4 5 '6 7'
6
[root@aaaccbb opt]# cat hello.sh
#/bin/bash
echo "$0"
\* @ 获取所有参数
[root@aaaccbb opt]# ./abc.sh 1 2 3
------------$@---------------
1
2
3
------------$*---------------
1 2 3
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
echo '------------$@---------------'
for para in "$@"
do
echo $para
done
echo '------------$*---------------'
for para in "$*"
do
echo $para
done
"$*" 所有的参数作为整体. 没有双引号引起来的时候,也是数组.
$@ 无论是否双引号包裹, 都是数组.
$? 获取脚本返回值 . 0正确 其他默认错误. 除非脚本有特殊return
查询变量
语法1: 直接使用变量名查询$var_name
语法2:便用花括号${var_name}
区别: 花括号方式适合拼接字符串
[root@aaaccbb opt]# name=zhangsan
[root@aaaccbb opt]# echo $name123
[root@aaaccbb opt]# echo ${name}123
zhangsan123
[root@aaaccbb opt]#
test [ 语句 ] 判断返回值
[root@aaaccbb opt]# a=123
[root@aaaccbb opt]# test $a = 123
[root@aaaccbb opt]# echo $?
0
[root@aaaccbb opt]# test $a = 23
[root@aaaccbb opt]# echo $?
1
[root@aaaccbb opt]# [ a = 123 ]
[root@aaaccbb opt]# echo $?
1
[root@aaaccbb opt]# [ $a = 123 ]
[root@aaaccbb opt]# echo $?
0
[root@aaaccbb opt]#
数值比较&&文件权限
[root@aaaccbb opt]# [ 2 gt 12 ]
-bash: [: gt: binary operator expected
[root@aaaccbb opt]# [ 2 -gt 12 ]
[root@aaaccbb opt]# echo $?
1
[root@aaaccbb opt]# [ -r abc.sh ]
[root@aaaccbb opt]# echo $?
0
[root@aaaccbb opt]#
[root@aaaccbb opt]# [ -f abc.sh ]
[root@aaaccbb opt]# echo $?
0
[root@aaaccbb opt]# [ -d abc.sh ]
[root@aaaccbb opt]# echo $?
1
[root@aaaccbb opt]#
[root@aaaccbb opt]# [ $a -lt 20 ] && echo "$a < 20" || echo "$a >=20"
15 < 20
流程控制.
一行写多条语句要用;进行分割.
用if语句,就要用fi结尾.
if 使用
[root@aaaccbb opt]# if [ $a -ge 18 ] ;then echo OK ;fi
OK
[root@aaaccbb opt]# ./abc.sh
[root@aaaccbb opt]# ./abc.sh atguigu
welcome dddd
[root@aaaccbb opt]# ./abc.sh 1111
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
if [ "$1"x = "atguigu"x ]
then echo 'welcome dddd'
fi
[root@aaaccbb opt]# #添加上x,即使不输入, 也不会报错.
[root@aaaccbb opt]# ./abc.sh 20
audit
[root@aaaccbb opt]# ./abc.sh 16
yong
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
if [ $1 -ge 18 ]
then
echo "audit"
else
echo "yong"
fi
[root@aaaccbb opt]#
[root@aaaccbb opt]# ./abc.sh 14
yong
[root@aaaccbb opt]# ./abc.sh 40
audit
[root@aaaccbb opt]# ./abc.sh 60
old man
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
if [ $1 -lt 18 ]
then
echo "yong"
elif [ $1 -ge 60 ]
then
echo "old man"
else
echo "audit"
fi
[root@aaaccbb opt]#
两个同时作为 if 条件. 中间使用连接符进行拼接
-a 代表 and. -o 代表 or.
[root@aaaccbb opt]# if [ $a -ge 18 ] && [ $a -le 35 ] ; then echo OK; fi
[root@aaaccbb opt]# a=15
[root@aaaccbb opt]# if [ $a -ge 18 -a $a -le 35 ]; then echo ok; fi
[root@aaaccbb opt]# a=20
[root@aaaccbb opt]# if [ $a -ge 18 -a $a -le 35 ]; then echo ok; fi
ok
[root@aaaccbb opt]#
case 多分支语句

[root@aaaccbb opt]# ./abc.sh A
very good
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
case $1 in
"A")
echo 'very good'
;;
"B")
echo 'good'
;;
"C")
echo 'ok'
;;
*)
echo 'bad'
;;
esac
[root@aaaccbb opt]#
for
[root@aaaccbb opt]# ./abc.sh 4
10
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
# 数值计算要用(())
for (( i=0; i <= $1; i++ ))
do
sum=$[ $sum + $i ]
done
echo $sum
[root@aaaccbb opt]#
[root@aaaccbb opt]# for os in windows linux macos ; do echo $os; done;
windows
linux
macos
[root@aaaccbb opt]#
[root@aaaccbb opt]# for i in {1..100}; do sum=$[ $sum + $i] ; done; echo $sum;
5050
[root@aaaccbb opt]#
while
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
j=0
while [ $j -le $1 ]
do
sum2=$[ $sum2 + $j]
j=$[ $j + 1 ]
done
read 读取控制台输入.

[root@aaaccbb opt]# ./abc.sh
please input your name: gch
welecome gch
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
read -t 10 -p "please input your name: " name
echo "welecome $name"
[root@aaaccbb opt]#
内置函数
basename
basename 截取文件名(无论文件是否存在)
[root@aaaccbb opt]# basename ./abc.sh
abc.sh
[root@aaaccbb opt]# basename /opt/1111
1111
[root@aaaccbb opt]#
[root@aaaccbb opt]# basename ./abc.sh .sh
abc
[root@aaaccbb opt]# ./abc.sh
abc
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
echo $( basename $0 .sh)
[root@aaaccbb opt]#
通过帮助看一下就行了.
date
[root@aaaccbb opt]# ./abc.sh it
it_1755332964.log
abc
[root@aaaccbb opt]# vi abc.sh
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
echo "$1_$(date +%s).log"
echo $( basename $0 .sh)
[root@aaaccbb opt]#
dirname
返回的内容和执行的命令有关系. 并且文件必须存在.
[root@aaaccbb opt]# dirname ./abc.sh
.
[root@aaaccbb opt]# dir /opt/aaaa/abc.aoe
dir: cannot access '/opt/aaaa/abc.aoe': No such file or directory
[root@aaaccbb opt]# dir /opt/aaa.sh
dir: cannot access '/opt/aaa.sh': No such file or directory
[root@aaaccbb opt]# dir /opt/abc.sh
/opt/abc.sh
[root@aaaccbb opt]#
自定义函数

[root@aaaccbb opt]# ./abc.sh
input first number:1
input second number:3
sum is: 4
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
function sum(){
sum=$[ $1 + $2 ]
echo "sum is: $sum"
}
read -p "input first number:" a
read -p "input second number:" b
sum $a $b
[root@aaaccbb opt]#
获取函数返回值
默认返回值0-255之间, 要获取函数返回值, 需要通过下面的方式进行解决.
[root@aaaccbb opt]# cat abc.sh
#!/bin/bash
function sum(){
sum=$[ $1 + $2 ]
echo $sum
}
read -p "input first number:" a
read -p "input second number:" b
sumx=$(sum $a $b)
echo "sumx: $sumx"
echo $[ $sumx * $sumx]
[root@aaaccbb opt]# ./abc.sh
input first number:300
input second number:400
sumx: 700
490000
[root@aaaccbb opt]#
备份
传入要备份的文件目录, 通过定时任务备份到/root/archive/.
编写执行备份的脚本文件 daily_archive.sh
记得添加执行权限. chomod +x daily_archive.sh
[root@aaaccbb opt]# ./daily_archive.sh /uploadPath
DEST_PATH:/root/archive/archive_250817.tar.gz
SOURCE_DIR:/uploadPath
备份完成
[root@aaaccbb opt]# ls -alt /root/archive
总用量 594900
-rw-r--r-- 1 root root 609162386 8月 17 10:13 archive_250817.tar.gz
drwxr-xr-x 2 root root 4096 8月 17 10:13 .
dr-xr-x---. 12 root root 4096 8月 17 09:56 ..
[root@aaaccbb opt]#
[root@aaaccbb opt]#
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat daily_archive.sh
#!/bin/bash
# 判断参数数量是否为 1
if [ $# -ne 1 ]
then
echo "参数数量必须为1"
exit
fi
# 判断参数是否为文件夹
if [ -d $1 ]
then
echo
else
echo
echo "待归档路径必须为文件夹"
exit
fi
# 定义归档的文件名称
DIR_NAME=$( basename $1 )
DIR_PATH=$( cd $(dirname $1); pwd )
DEST_PATH="/root/archive/archive_$(date +%y%m%d).tar.gz"
SOURCE_DIR="${DIRPATH}/${DIR_NAME}"
echo "DEST_PATH:$DEST_PATH"
echo "SOURCE_DIR:$SOURCE_DIR"
# 进行归档
tar -czf $DEST_PATH -C $SOURCE_DIR .
if [ $? -eq 0 ]
then
echo
echo "备份完成"
else
echo "备份出错,请检查"
fi
exit
[root@aaaccbb opt]#
加入定时任务
[root@aaaccbb opt]# crontab -l
no crontab for root
[root@aaaccbb opt]# crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
[root@aaaccbb opt]#
0 11 * * * /opt/daily_archive.sh /uploadPath
文本处理工具
grep awk sed.
正则表达式入门.


[root@aaaccbb archive]# cat /etc/passwd | grep ^a
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@aaaccbb archive]# cat /etc/passwd | grep ^ad
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@aaaccbb archive]#
[root@aaaccbb archive]# cat /etc/passwd | grep bash$
root:x:0:0:root:/root:/bin/bash
nacos:x:1000:1000::/home/nacos:/bin/bash
[root@aaaccbb archive]#
# 完全匹配.
[root@aaaccbb opt]# cat /etc/passwd | grep ^adm:x:3:4:adm:/var/adm:/sbin/nologin$
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat daily_archive.sh | grep r..t
DEST_PATH="/root/archive/archive_$(date +%y%m%d).tar.gz"
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat /etc/passwd | grep ro*t
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
[root@aaaccbb opt]#
#.* 任意字符出现任意次 匹配任意字符串(包括空串)
[root@aaaccbb opt]# cat /etc/passwd | grep ^r.*bash$
root:x:0:0:root:/root:/bin/bash
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat /etc/passwd | grep ^r.*bash$
root:x:0:0:root:/root:/bin/bash
[root@aaaccbb opt]# cat /etc/passwd | grep ^r.*0.*bash$
root:x:0:0:root:/root:/bin/bash
[root@aaaccbb opt]# cat /etc/passwd | grep ^r.*1.*bash$
[root@aaaccbb opt]#
[root@aaaccbb opt]# cat /etc/passwd | grep r[a,o,c]ot
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@aaaccbb opt]#
特殊字符
/ 不需要转译. $必须转译\$ 并且必须使用''包裹.
[root@aaaccbb opt]# cat daily_archive.sh | grep '/\$'
SOURCE_DIR="${DIRPATH}/${DIR_NAME}"
[root@aaaccbb opt]#
正则匹配手机号.
开头1.
第二位为: 3,4,5,7,8
剩下9位随便.
{} 必须使用 -E, 指定使用了正则扩展.
[root@aaaccbb opt]# echo "15552535666" | grep -E ^1[345678][0-9]{9}
15552535666
[root@aaaccbb opt]# echo "15552535666" | grep ^1[345678][0-9]{9}
[root@aaaccbb opt]#
cut 对文本进行数据的剪切
cut的工作就是"剪",具体的说就是在文件中负责剪切数据用的。cut命令从文件的每一
行剪切字节、字符和字段并将这些字节、字符和字段输出。
[root@aaaccbb opt]# cat aaa.txt
shen guang
zhen dong
wo wo
lai lai
le le
[root@aaaccbb opt]#
[root@aaaccbb opt]# cut -d " " -f 1 aaa.txt
shen
zhen
wo
lai
le
[root@aaaccbb opt]#
[root@aaaccbb opt]# cut -d " " -f 2,3 aaa.txt
guang
dong
wo
lai
le
[root@aaaccbb opt]#
root@aaaccbb opt\]# cat /etc/passwd \| cut -d ":" -f 1,6-7 ##### 切割获取ip地址 [root@aaaccbb opt]# ifconfig eth0 | grep netmask inet 172.31.181.100 netmask 255.255.240.0 broadcast 172.31.191.255 [root@aaaccbb opt]# ifconfig eth0 | grep netmask | cut -d " " -f 10 172.31.181.100 [root@aaaccbb opt]# [root@aaaccbb opt]# ifconfig | grep netmask | cut -d " " -f 10 172.31.181.100 127.0.0.1 [root@aaaccbb opt]# ### awk   [root@aaaccbb opt]# cat /etc/passwd | grep ^root | cut -d ":" -f 7 /bin/bash [root@aaaccbb opt]# [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '/^root/print $7' awk: 命令行:1: /^root/print $7 awk: 命令行:1: ^ syntax error [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '/^root/{print $7}' /bin/bash [root@aaaccbb opt]# [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '/^root/{print $1,$7}' root /bin/bash [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '/^root/{print $1","$7}' root,/bin/bash [root@aaaccbb opt]# [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '{print $1","$7}' root,/bin/bash bin,/sbin/nologin daemon,/sbin/nologin [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" 'BEGIN{print "begin"} {print $1","$7} END{print "end"}' begin root,/bin/bash bin,/sbin/nologin end [root@aaaccbb opt]# cat /etc/passwd | awk -F ":" '{print $3+1}' 1 2 3 4 [root@aaaccbb opt]# cat /etc/passwd | awk -v i=4 -F ":" '{print $3+i}' 4 5 6 7 awk 提取ip地址 $x 空行不考虑. [root@aaaccbb opt]# ifconfig | awk '/netmask/ {print $2}' 172.31.181.100 127.0.0.1 [root@aaaccbb opt]# awk 内置变量. [root@aaaccbb opt]# awk -F ":" '{print "fileName:"FILENAME", row:"NR",column:"NF}' /etc/passwd fileName:/etc/passwd, row:1,column:7 [root@aaaccbb opt]# ifconfig | grep -n ^$ 9: 18: [root@aaaccbb opt]# [root@aaaccbb opt]# ifconfig | awk '/^$/{print NR}' 9 18 [root@aaaccbb opt]# ### 参考地址 [3天搞定Linux,1天搞定Shell,清华学神带你通关](https://www.bilibili.com/video/BV1WY4y1H7d3?spm_id_from=333.788.videopod.episodes&vd_source=36466300c658605b420cf080dc4109c2&p=89)