目录
Shell脚本是一种用Shell语言编写的脚本程序,它可以在Unix/Linux系统上运行。Shell脚本通常以.sh为文件扩展名,是一种方便的自动化工具,可以用来完成各种系统管理和任务自动化的工作。
?Linux 系统中的Shell是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。 常见的Shell解释器程序有很多种,使用不同的Shell时,其内部指令、命令行提示符等方面会存在一些区别。通过/etc/shells文件可以了解当前系统所支持的Shell 脚本种类。
查看本机的shell信息:
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
linux中常见的shell:
脚本执行逻辑:
执行方式:
① 使用绝对或者相对路径执行(需要加执行权限)
[root@localhost ~]# vim ping.sh
[root@localhost ~]# chmod +x ping.sh #添加执行权限
#!/bin/bash
ping -c1 192.168.190.100
[root@localhost ~]# /root/ping.sh #绝对路径执行
[root@localhost ~]# ./ping.sh #相对路径执行
② 直接使用解释器(不需要加执行权限)
[root@localhost ~]# chmod -x ping.sh
[root@localhost ~]# bash ping.sh
③ source和 . (不需要加执行权限)
[root@localhost ~]# source ping.sh
[root@localhost ~]# . ping.sh
三种执行方式对当前环境影响:
[root@localhost ~]# vim cd.sh
#!/bin/bash
cd /opt
ls
[root@localhost ~]# chmod +x cd.sh
[root@localhost ~]# /root/cd.sh
rh
[root@localhost ~]# pwd
/root
[root@localhost ~]# ./cd.sh
rh #使用子shell执行,不切环境
[root@localhost ~]# pwd
/root
[root@localhost ~]# bash cd.sh
rh
[root@localhost ~]# pwd
/root #使用子shell执行,不切环境
[root@localhost ~]# source cd.sh
rh
[root@localhost opt]# pwd
/opt #使用本shell执行,切环境
[root@localhost ~]# . cd.sh
rh
[root@localhost opt]# pwd
/opt #使用本shell执行,切环境
① 命令错误
默认后续的命令还会继续执行,用bash -n无法检查出来 ,可以使用bash -x进行观察
[root@localhost ~]# vim 1.sh
#!/bin/bash
mkdi 1 #错误命令
echo 1 #正确命令
[root@localhost ~]# bash 1.sh
1.sh:行1: mkdi: 未找到命令
1 #错误命令不影响后续命令
② 语法错误
会导致后续的命令不继续执行,可以用bash -n检查错误,提示的出错行数不一定是准确的
[root@localhost ~]# vim 2.sh
#!/bin/bash
if [ 1 -eq 1 ];then
echo t
else
echo f
#fi
[root@localhost ~]# bash 2.sh
2.sh:行7: 语法错误: 未预期的文件结尾
③ 逻辑错误
只能使用bash -x进行
注:
bash -n:脚本名称 (不在当前目录下加绝对路径),检查语法错误
bash -x:脚本名称 (不在当前目录下加绝对路径),逻辑错误
④?set -e,set -u
?在 脚本的前面输入set -e一旦出错立即停止
[root@localhost ~]# vim 3.sh
#!/bin/bash
set -e
cd /op
[root@localhost ~]# bash 3.sh
3.sh: 第 3 行:cd: /op: 没有那个文件或目录
另外:set -u变量不存在不让执行
重定向是一种功能,它允许用户更改命令的标准输入(stdin)和标准输出(stdout)的默认行为。这通常用于将命令的结果发送到不同的目的地,而不是仅仅显示在终端控制台上。
类型 | 设备文件 | 文件描述编号 | 默认设备 |
---|---|---|---|
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stderr | 2 | 显示器 |
交互式硬件设备:
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | 1> | 将输出结果保存到指定的文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 标准错误输出结果追加到指定的文件尾部 | |
混合输出 | &>无论对错都可以重定向 | 将标准输出、标准错误的内容保存到同一个文件中 |
案例:
不能将正确和错误一起显示出来?
[root@centos7 ~]#ls /data /xxx 1> /data/all.log 2>&1?????
先将正确的重定向文件中,再将错误的重定向文件中
[root@centos7 ~]#ls /data /xxx 2> /data/all.log 1>&2?????
先将错误的重定向文件中,再将正确的重定向文件中
[root@centos7 ~]#ls /data /xxx &> /data/all.log???????????? ? 不解释
[root@centos7 ~]#ls /data /xxx >& /data/all.log???????????? ? 同上
[root@centos7 ~]#ls /data /xxx ??2>&1 1> /data/all.log?? 开始没有定义1,所以不符合要求?
可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件并用作命令的标准输入。?
[root@localhost ~]# cat > test << EOF #EOF不区分大小写
> 1
> 2
> EOF
[root@localhost ~]# cat test
1
2
案例:修改密码
[root@localhost ~]# passwd fql << EOF
> 123456
> 123456
> EOF
更改用户 fql 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
“|”,将前面命令的结果当作后面命令的参数执行,管道符左边的命令一定要有标准输出,右边的命令一定可以接收标准输入。当右边无法接收标准输入,可以使用xargs命令代为接收。
[root@localhost ~]# cat /etc/passwd | wc -l
41
[root@localhost ~]# echo --help | xargs cat
用法:cat [选项]... [文件]...
将[文件]或标准输入组合输出到标准输出。
……
定义变量:name=fql
引用变量:$name 或 ${name}
调用变量:echo $name 或 echo ${name}
取消变量:unset name
双引号" " #弱引用,可以识别变量,可以避免空格错误
[root@localhost ~]# a=1
[root@localhost ~]# echo "$a"
1
[root@localhost ~]# a=1 2
bash: 2: 未找到命令...
[root@localhost ~]# a="1 2";echo $a
1 2
单引号' ' #强引用,不能识别变量
[root@localhost ~]# a=1
[root@localhost ~]# echo '$a'
$a
反撇号` ` #调用命令的执行结果,等于$()
[root@localhost ~]# time=`date`;echo $time
2024年 01月 24日 星期三 16:16:19 CST
大括号{ } #定义变量名的范围
[root@localhost ~]# a=1;b=2
[root@localhost ~]# echo ${a}b
1b
格式:变量名+=变量值
[root@localhost ~]# a=1
[root@localhost ~]# a+=2;echo $a
12
从键盘输入的内容变成变量,交互式命令
[root@localhost ~]# read -p "现在的时间是:" time
现在的时间是:16点
[root@localhost ~]# echo $time
16点
[root@localhost ~]# vim 1.sh
#!/bin/bash
read -p "你的名字:" name
echo "你的名字是:$name"
[root@localhost ~]# bash 1.sh
你的名字:lisi
你的名字是:lisi
默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用。可以通过内部命令export将指定的变量为全局变量,使用户定义的变量在所子shell环境中可以继续使用。
方法:
格式1:定义好变量情况下 export 变量名
格式2:为定义变量情况下 export 变量名=变量值
[root@localhost ~]# a=1
[root@localhost ~]# echo $a
1
[root@localhost ~]# bash #切换到子shell
[root@localhost ~]# echo $a #子shell无法识别变量
[root@localhost ~]#
[root@localhost ~]# pstree -p | grep -v grep | grep bash
|-sshd(1097)-+-sshd(1520)---bash(1583)---bash(37606) #37606为新打开的子shell
[root@localhost ~]# export a #定义全局变量
[root@localhost ~]# bash
[root@localhost ~]# echo $a #子shell可以识别变量
1
[root@localhost ~]# pstree -p | grep -v grep | grep bash
|-sshd(1097)-+-sshd(1520)---bash(1583)---bash(37654) #37654为新打开的子shell
expr只能进行整数的运算,格式:expr 变量1 运算符 变量2 [运算符 变量3]
运算符:
[root@localhost ~]# expr a+b
a+b
[root@localhost ~]# expr $a + $b
3
[root@localhost ~]# expr $a - $b
-1
[root@localhost ~]# expr $a \* $b
2
let 变量名=算术表达式
[root@localhost ~]# a=1;b=2
[root@localhost ~]# let c=a+b;echo $c
3
((变量名=算术表达式))
[root@localhost ~]# a=1;b=2
[root@localhost ~]# ((c = a+b));echo $c
3
变量名=$[算术表达式]
[root@localhost ~]# a=1;b=2
[root@localhost ~]# c=$[c=a+b];echo $c
3
变量=$(expr arg1 + arg2 ...)
[root@localhost ~]# c=$(expr $a + $b);echo $c
3
变量=`expr arg1 + arg2 ...`
[root@localhost ~]# c=`expr $a + $b`;echo $c
3
echo 算术表达式 | bc
[root@localhost ~]# echo $a+$b | bc
3
$RANDOM
是一个特殊的环境变量,用于生成一个随机整数。每次访问$RANDOM
时,它会返回一个0到32767(2^15-1)之间的随机整数,这个值是通过使用伪随机数生成器来生成的。
[root@localhost ~]# echo $[RANDOM] #随机生成0-32767
17922
[root@localhost ~]# echo $[RANDOM%35] #随机生成0-34
1
[root@localhost ~]# echo $[RANDOM%35+1] #随机生成1-35
7
?随机生成颜色:
[root@localhost ~]# echo -e "\E[1;30mhello\E[0m"
hello
#指定颜色,30-36共7种颜色
[root@localhost ~]# echo -e "\E[1;$[RANDOM%7+31]mhello\E[0m"
hello
#随机颜色
环境变量大体可以分为两类:全局环境变量、局部环境变量。前者变量名通常使用大写字母,后者变量名通常使用小写字母。可通过下述env、printenv命令查看当前所有的全局环境变量。
常用的环境变量:
?特点:
/etc/profile如果修改此文件会作用于所有用户
~/.bash_profile 用户独立的配置文件,修改这个文件只作用于当前用户
只读变量是一种特殊类型的变量,其值不能被修改或重写。一旦将变量声明为只读,就无法再对其进行赋值操作。?变量值不允许修改(重新赋值)的情况,无法使用unsets删除,最快方法重启。
[root@localhost ~]# a=1
[root@localhost ~]# readonly a
[root@localhost ~]# echo $a
1
[root@localhost ~]# a=2
bash: a: 只读变量
[root@localhost ~]# unset a
bash: unset: a: 无法反设定: 只读 variable
位置变量也称为位置参数,使用$1、$2、$3、…、$9 表示
[root@localhost ~]# vim 1.sh
#!/bin/bash
echo "$1" 位置1
echo "$2" 位置2
echo "${10}" 位置10,不使用括号,只能识别第一个参数
[root@localhost ~]# bash 1.sh {1..20}
1
2
10
存在一些预定义变量(也称为状态变量),它们提供了有关系统和正在发生的操作的信息。这些变量不需要事先声明,而是由操作系统自动提供。
[root@localhost ~]# vim 1.sh
#!/bin/bash
echo "$*"
echo "$@"
echo "$?"
echo "$#"
echo "$0"
echo "$$"
echo "$!"
[root@localhost ~]# bash 1.sh {1..10}
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
0
10
1.sh
38866
注:?
?当使用“$0”预定义变量时,如果执行的是软链接文件,则输出的是当前执行的软链接文件名
[root@localhost ~]# ln -s 1.sh a
[root@localhost ~]# ll a
lrwxrwxrwx. 1 root root 4 1月 24 18:47 a -> 1.sh
[root@localhost ~]# bash a
a