小白的Shell入门基础超细详解(配操作步骤及注释)

Shell脚本概述

简述

  • Shell脚本是将要执行的命令按顺序保存到一个文本文件里
  • 需要给该文件可执行的权限
  • 可结合各自Shell控制语句以完成更复杂的操作
  • Shell是一个特殊的应用程序,它介于系统内核与用户之间,充当"命令解释器"的角色,也称命令“翻译官”。

Shell的作用与应用场景

  • Shell的作用
    • 负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果
  • 用户登录后默认使用Shell程序,一般为/bin/bash。不同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
  • 示意简图

在这里插入图片描述

  • 应用场景
    • 重复性操作
    • 交互性任务
    • 批量事务处理
    • 服务运行状态监控
    • 定时任务执行
    • …等等

Shell编程规范

  • Shell脚本使用VIM文本编辑器
  • 每行一条Linux命令,按执行顺序依次编写
  • Shell脚本的构成
    • 1.脚本申明(解释器):若第一行为"#!/bin/bash",表示此行以下的代码语句是通过/bin/bash程序来执行,#!/bin/bash为默认解释器。还有其他类型的解释器,例如:#!/usr/bin/python、#!/usr/bin/expect等等
    • 2.注释信息:以"#"开头的语句表示为注释信息,被注释的语句在运行脚本时不会被执行
    • 3.可执行语句:比如echo命令,用于输出" "之间的字符串

编写脚本代码

[root@localhost ~]#vim first.sh           【建议Shell的脚本文件都以".sh"命名】

#!/bin/bash                          【脚本申明】
# this is my first shell-script.     【注释信息】
cd /boot                             【可执行语句】
echo "当前所在路径为:"
pwd
echo "以vml为开头的文件为:"
ls -lh vml*

Shell脚本的执行

  • 方法一:指定路径的命令,要求文件必须有x(可执行)权限
[root@localhost ~]#chmod +x first.sh     【给该文件添加可执行的权限】
[root@localhost ~]#/root/first.sh        【绝对路径】
当前所在路径为:
/boot
以vml为开头的文件为:
-rwxr-xr-x. 1 root root 5.7M 32 14:07 vmlinuz-0-rescue-bdc4e5db1462496d9b55de5af2f6778a
-rwxr-xr-x. 1 root root 5.7M 823 2017 vmlinuz-3.10.0-693.el7.x86_64
[root@localhost ~]#./first.sh           【相对路径】
当前所在路径为:
/boot
以vml为开头的文件为:
-rwxr-xr-x. 1 root root 5.7M 32 14:07 vmlinuz-0-rescue-bdc4e5db1462496d9b55de5af2f6778a
-rwxr-xr-x. 1 root root 5.7M 823 2017 vmlinuz-3.10.0-693.el7.x86_64
[root@localhost ~]#
  • 方法二:指定Shell来解释脚本,不要求必须有x权限
[root@localhost ~]#chmod -x first.sh 
[root@localhost ~]#ll
总用量 32
-rw-------. 1 root root 1729 32 14:08 anaconda-ks.cfg
-rwxr-xr-x. 1 root root  231 32 17:01 bianliang.sh
-rw-r--r--. 1 root root  141 32 14:26 first.sh
......省略......
-rw-r--r--. 1 root root    0 32 15:07 info.txt

drwxr-xr-x. 2 root root    6 32 14:09 桌面
[root@localhost ~]#sh first.sh       【sh脚本路径】
当前所在路径为:
/boot
以vml为开头的文件为:
-rwxr-xr-x. 1 root root 5.7M 32 14:07 vmlinuz-0-rescue-bdc4e5db1462496d9b55de5af2f6778a
-rwxr-xr-x. 1 root root 5.7M 823 2017 vmlinuz-3.10.0-693.el7.x86_64
[root@localhost ~]#. first.sh       【"."或者"source"脚本路径】
当前所在路径为:
/boot
以vml为开头的文件为:
-rwxr-xr-x. 1 root root 5.7M 32 14:07 vmlinuz-0-rescue-bdc4e5db1462496d9b55de5af2f6778a
-rwxr-xr-x. 1 root root 5.7M 823 2017 vmlinuz-3.10.0-693.el7.x86_64
[root@localhost boot]#

重定向与交互硬件设备

交互硬件设备

  • 标准输入:从该设备接收用户输入的数据
  • 标准输出:通过该设备向用户输出数据
  • 标准错误:通过该设备报告执行出错信息
类型 设备文件 文件描述编号 默认设备
标准输入 /dev/stdin 0 键盘
标准输出 /dev/stdout 1 显示器
标准错误 /dev/stderr 2 显示器

重定向操作

类型 操作符 用途说明
重定向输入 < 从指定的文件读取数据,而不是从键盘输入
重定向输出 >
>>
将输出的结果保存到指定的文件(覆盖原有内容)
将输出的结果追加到指定的文件尾部
标准错误输出 2>
2>>
将输出的结果保存到指定的文件(覆盖原有内容)
将错误的信息追加到指定的文件中
混合输出 &>
2>&1
将标准输出、标准错误的内容保存到同一个文件中
将标准错误输出重定向到标准输出
例如 ls -lh > log.txt 2>&1
其实等同于ls -lh &> long.txt
本来1→屏幕(1指向屏幕)
执行>log后,1→log.txt(1指向log.txt)
执行2>&1后,2→1(2指向1,而1指向了log.txt,因此2也等同于指向了log.txt)
[root@localhost boot]#echo "111222" >passwd.txt      【将echo输出的结果"111222"覆盖保存到pass.txt文件中】
[root@localhost boot]#passwd --stdin qz <passwd.txt  【从pass.txt文件中读取密码数据并使用stdin(标准键盘)输入到passwd qz里】
更改用户 qz 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost boot]#

Shell脚本变量

变量的作用与类型

  • 变量的作用
    • 用来存放系统和用户需要使用的特定参数(值)
      变量名:使用固定的名称,由系统预设或用户定义
      变量值:能够根据用户设置、系统环境的变化而变化
  • 变量的类型
    • 自定义变量:由用户自己定义、修改和使用
    • 特殊变量:环境变量,只读变量,位置变量,预定义变量
      环境变量:由系统维护,用户设置工作环境
      位置变量:通过命令行给脚本程序传递参数
      预定义变量:Bash中内置的一类变量,不能直接修改

自定义变量

定义一个新的变量

  • 变量名以字母或下划线开头,区分大小写,推荐全大写
  • 定义变量格式:变量名=变量值。"="两边没有空格
  • 查看变量值格式:echo &变量名;echo &变量名 $变量名;echo &{变量名}xx
  • 变量命名规则:必须以字母或下划线开头,且区分大小写
[root@localhost ~]#A=1111           
[root@localhost ~]#echo $A
1111
[root@localhost ~]#_B="q z"        【有空格时需用双引号或单引号】
[root@localhost ~]#echo $_B
q z
[root@localhost ~]#_B=q z
bash: z: 未找到命令...
[root@localhost ~]#11=11            【不能以数字开头】
bash: 11=11: 未找到命令...
[root@localhost ~]#echo $_A          
q z
[root@localhost ~]#echo $A $_A      【同时查询多个变量值时需用空格间隔】
1111 q z
[root@localhost ~]#_11=11           【可以用_+数字作为开头】
[root@localhost ~]#echo $_11
11
[root@localhost ~]#echo ${_11}qq    【用{}圈起来后则在变量值后面追加】
11qq
[root@localhost ~]#echo $_11 qqq   
11 qqq

赋值时使用引号

  • 双引号:允许通过$符号引用其他变量值
  • 单引号:禁止引用其他变量值,$视为普通字符
  • 反撇号:命令替换,提取命令执行后的输出结果和$()作用相同
[root@localhost ~]#echo "$A"""允许通过$符号引用其他变量值】
1111
[root@localhost ~]#echo '$A''':禁止引用其他变量值,$视为普通字符】
$A
[root@localhost ~]#which ls
alias ls='ls --color=auto'
	/usr/bin/ls
[root@localhost ~]# echo `which ls`      【``提取命令执行后的输出结果】
alias ls='ls --color=auto' /usr/bin/ls
[root@localhost ~]# echo $(which ls)     【$(...)提取命令执行后的输出结果,与``作用相同】
alias ls='ls --color=auto' /usr/bin/ls

从键盘输入内容为变量赋值

  • 方法一
    • read -p “提示信息” 变量名
    • echo $变量名
  • 方法二
    • echo -n “提示信息”。-n 不换行输出
    • read 变量名
    • echo $变量名
[root@localhost ~]#read -p "请输入你的地址:" name  【根据提示即可获取相关的变量名】
请输入你的地址:nanjing
[root@localhost ~]#echo $name 
nanjing
[root@localhost ~]#vim read.sh                  【也可以通过脚本编写获取相关变量名】
#!/bin/bash                    
echo -n '输入你的IP地址:'                         【不加"-n"上下两行内容将会换行显示】
read myip                                       【将"myip"设置为变量名】
echo $myip                                      【通过echo输出变量名】 
~ 
:wq   
[root@localhost ~]#chmod +x read.sh 
[root@localhost ~]#./read.sh 
输入你的IP地址:11.11.11.11
11.11.11.11
[root@localhost ~]#echo $myip             【这里echo查询不出结果是因为这个脚本是不是在当前shell环境中执行,而是在脚本的shell环境
                                            中执行的查询操作。所以在脚本中echo查询能够获取到相关信息,在当前sheel中则获取不到】

[root@localhost ~]#source read.sh         【source或.则可在当期shell环境中进行相关信息查询】
输入你的IP地址:111.111.111.111
111.111.111.111
[root@localhost ~]#echo $myip 
111.111.111.111
[root@localhost ~]#vim read.sh 

#!/bin/bash
echo  '输入你的IP地址:'
read myip
echo $myip
:wq
[root@localhost ~]#./read.sh    
输入你的IP地址:     
1.1.1.1
1.1.1.1
【这里在脚本echo后面没有加"-n"则换行输出,即执行完一条命令则另起一行】
        

变量作用范围

  • 默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为“局部变量”,当进入子程序或新的子Shell环境时,局部变量将无法再使用
  • 可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用
  • 可使用pstree命令查看Shell环境
  • 输入bash命令则进入子Shell环境,按Ctrl+D或exit命令退出子Shell环境
  • 格式一:export 变量名;格式二:export 变量名=变量值
[root@localhost ~]#echo $A
1111
[root@localhost ~]#bash                          【进入子Shell环境】
[root@localhost ~]# pstree                       【查看Shell环境】
systemd─┬─ModemManager───2*[{
    
    ModemManager}]
        ├─NetworkManager───2*[{
    
    NetworkManager}]
        ├─VGAuthService
        ........
        ├─smartd
        ├─sshd───sshd───bash───bash───pstree     【Shell状态】
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{
    
    tuned}]
        ├─upowerd───2*[{
    
    upowerd}]
        ├─vmtoolsd───{
    
    vmtoolsd}
        ├─wpa_supplicant
        └─xdg-permission-───2*[{
    
    xdg-permission-}]
[root@localhost ~]# echo $A                      【子Shell环境中echo不到相关信息】

[root@localhost ~]# exit                         【Ctrl+D或exit命令退出子Shell环境】
[root@localhost ~]#echo $A
1111
[root@localhost ~]#export A _11                  【导出为全局变量】
[root@localhost ~]#bash                          
[root@localhost ~]# echo "$A $_11"
1111 11

整数变量的运算

常用运算符

  • 加法运算:+
  • 减法运算:-
  • 乘法运算:*
  • 除法运算:/
  • 求模(取余)运算:%
[root@localhost ~]#expr 10 \* 5
50
[root@localhost ~]#expr 10 \* 5.5
expr: 非整数参数
[root@localhost ~]#expr 10 / 5
2
[root@localhost ~]#expr 10 % 3
1

常用的运算表达式

  • i=$(expr 10 * 5)
  • i=$((10*5))
  • i=$[10*5]
  • let i=10*5
  • i++ 相当于i=$ [$i+1]
  • i-- 相当于i=$ [$i-1]
  • i+=2相当于i=$ [$i+2]
[root@localhost ~]#i=`expr 10 \* 5`          【将此运算的结果赋值给"i"[root@localhost ~]#echo $i
50
[root@localhost ~]#o=$(expr 10 \* 5)         【将此运算的结果赋值给"o"[root@localhost ~]#echo $o
50
[root@localhost ~]#y=$((10*4))               【将此运算的结果赋值给"y"[root@localhost ~]#echo $y
40
[root@localhost ~]#p=$[10*2]                 【将此运算的结果赋值给"p"[root@localhost ~]#echo $p
20
[root@localhost ~]#let c=10*6                【将此运算的结果赋值给"c"[root@localhost ~]#echo $c
60
[root@localhost ~]#let y++                   【在变量"y"上面+1[root@localhost ~]#echo $y
41
[root@localhost ~]#let p--                   【在变量"p"上面-1[root@localhost ~]#echo $p
19
[root@localhost ~]#let c+=5                  【在变量"c"上面+5[root@localhost ~]#echo $c
65
[root@localhost ~]#let c-=10                 【在变量"c"上面-10[root@localhost ~]#echo $c
55

浮点运算

  • bash不支持浮点运算,如需要进行浮点运算则需要借助bc或者awk工具进行处理
  • bc工具
[root@localhost opt]# h=$(echo "6.2+2.22"|bc)
[root@localhost opt]# echo $h
8.42
[root@localhost opt]# h=$(echo "6.2-2.22"|bc)
[root@localhost opt]# echo $h
3.98
[root@localhost opt]# h=$(echo "6.2*2.22"|bc)
[root@localhost opt]# echo $h
13.76
[root@localhost opt]# h=$(echo "6.2/2.22"|bc)            【相除时如有小数需定义scale】
[root@localhost opt]# echo $h
2
[root@localhost opt]# h=$(echo "scale=10;6.2/2.22"|bc)   【scale=10代表显示小数点后10位,不足10位时将会以0补全】
[root@localhost opt]# echo $h
2.7927927927
[root@localhost opt]# f=$(echo "2.2/(2.2-1.1)*2+1.1"|bc) 【混合运算】
[root@localhost opt]# echo $f
5.1
  • awk工具
[root@localhost opt]# g=$(awk 'BEGIN{print 4.5+3.3}')
[root@localhost opt]# echo g
g
[root@localhost opt]# echo $g
7.8
[root@localhost opt]# g=$(awk 'BEGIN{print 4.5-3.3}')
[root@localhost opt]# echo $g
1.2
[root@localhost opt]# g=$(awk 'BEGIN{print 4.5*3.3}')
[root@localhost opt]# echo $g
14.85
[root@localhost opt]# g=$(awk 'BEGIN{print 4.5/3.3}')
[root@localhost opt]# echo $g
1.36364
[root@localhost opt]# g=$(awk 'BEGIN{print 100000000000000/3}')
[root@localhost opt]# echo $g
3.33333e+13                                                     【awk默认有效位6位】
[root@localhost opt]# f=$(awk 'BEGIN{print(4.5-3.4)*3+6}')
[root@localhost opt]# echo $f
9.3

特殊变量

环境变量

  • 环境变量由系统提前创建,用来设置用户的工作环境
    配置文件:/ect/profile、~/.bash_profile
  • 使用env命令可以查看到当前工作环境下的环境变量
    常见的环境变量:PWD、PATH、USER、SHELL、HOME
变量 说明
USER 用户名称
HOME 用户的宿主目录
LANG 语音和字符集
PWD 当前所在的工作目录
PATH 可执行程序的默认搜索路径
  • echo $PATH
    查看当前搜索路径
  • PATH="$PATH:/root"
    将/root目录添加到搜索路径
  • export PATH="$PATH:/root"
    输出为全局环境变量
root@localhost ~]#env
A=1111
XDG_SESSION_ID=30
HOSTNAME=localhost.localdomain
SELINUX_ROLE_REQUESTED=
_11=11
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.131.1 49208 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;........oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/
SSH_CONNECTION=192.168.131.1 49208 192.168.131.9 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:10.0
_=/usr/bin/env
  • 环境变量的全局配置文件为/etc/profile,在此文件中定义的变量作用于所有用户。每个用户还有自己的独立配置文件(~/.bash_profile)可以用来长期变更或设置某个环境变量
[root@localhost ~]#vim /etc/.bash_profile 

# .bash_profile
......
......
export PATH
export HISTSIZE=100                           【修改root用户的历史命令记录数】
......
......
:wq
[root@localhost ~]#echo $HISTSIZE            【读取并执行文件中的设置】
100
[root@localhost ~]#source /etc/.bash_profile 
[root@localhost ~]#echo $HISTSIZE 
100

只读变量

  • 用于变量值不允许被修改的情况
[root@localhost ~]#qz=good
[root@localhost ~]#readonly qz                【设置qz变量为只读变量】
[root@localhost ~]#echo $qz
good
[root@localhost ~]#qz=bad                     【只读变量不可以被重新赋值】
-bash: qz: 只读变量
[root@localhost ~]#unset qz                   【只读变量不可以被删除,unset命令用于删除变量】
-bash: unset: qz: 无法反设定: 只读 variable     【重启则解除】
[root@localhost ~]#A=11QQ                        
[root@localhost ~]#echo $A
11QQ
[root@localhost ~]#unset A                    【unset命令用于删除变量A】
[root@localhost ~]#echo $A

位置变量

  • 表示为$n,n为1-9之间的数字
  • 当执行命令操作时,第一个字段表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量
  • $n:n为1-9之间的数字。$0代表命令本身,$1- 9 代 表 第 一 个 到 第 九 个 参 数 , 十 以 上 的 参 数 需 要 用 大 括 号 表 示 , 例 如 : 9代表第一个到第九个参数,十以上的参数需要用大括号{}表示,例如: 9{10}
[root@localhost ~]#vim hjbl.sh

#!/bin/bash
first=$1                              【定义参数一的变量名】
second=$2                             【定义参数二的变量名】

sum=$[$first+$second]                 【sum=参数一+参数二】
SUM=$(($1*$2))                        【SUM=参数一*参数二】
echo $sum                             
echo $SUM
:wq
[root@localhost ~]#./hjbl.sh 10 20    【参数一赋值10,参数二赋值2030
200
[root@localhost ~]#vim hjbl2.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $4
echo $5
echo $6
echo $7
echo $8
echo $9
echo $10           【参数十为两位数,但此处不用{
    
    }括起来】  
echo ${
    
    11}         【参数十一也为两位数,但此处用{
    
    }括起来】 
:wq 
[root@localhost ~]#chmod +x hjbl2.sh 
[root@localhost ~]#./hjbl2.sh 1212 20 30 40 50 60 70 80 90 100 110
./hjbl2.sh
1212
20
30
40
50
60
70
80
90
12120             【参数10为两位数但不用{
    
    }括起来则实际为参数1+参数0,所以显示结果为12120110               【参数11也为两位数但用{
    
    }括起来,则显示为赋值的110

预定义变量

  • $* 和 $@:表示命令或脚本要处理的参数
    • $*:把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4"
    • $@:把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表"$1" “$2” “$3” “$4”
    • $ * 和 @ 在不加双引号时表现一致,但是如果加了双引号,$*则会将所有参数作为一个整体
  • $#:表示命令或脚本要处理的参数的个数
  • $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,其他非0值则表示执行异常或出错
  • $0:当前执行的进程/程序名
  • return退出函数并返回的退出值 (0-255)


[root@localhost ~]#vim hjbl2.sh

#!/bin/bash
echo $0
echo $1
echo $2
......
echo $10
echo ${
    
    11}
echo $*
echo $@ 
[root@localhost ~]#./hjbl2.sh 1212 20 30 40 50 60 70 80 90 100 110
./hjbl2.sh
1212
20
......
12120
110
1212 20 30 40 50 60 70 80 90 100 110    【因为$*未加引号所以表示命令或脚本要处理的参数】
1212 20 30 40 50 60 70 80 90 100 110    【因为$@未加引号所以表示命令或脚本要处理的参数】

[root@localhost ~]#vim bl.sh

#!/bin/bash
echo "没加引号时..."
echo $*
echo $@

for a in $*
 do
echo $a
done

for b in $@
 do
echo $b
done

echo "加引号时..."
echo "$*"
echo "$@"

for c in "$*"
  do
echo $c
done

for d in "$@"
  do
echo $d
done
echo $#               【显示要处理的个数】

[root@localhost ~]#./bl.sh 100 200 300 400 500 600
没加引号时...
100 200 300 400 500 600  
100 200 300 400 500 600   
100                           
200
300
400
500
600
100
200
300
400
500
600
加引号时...
100 200 300 400 500 600    【因为加了引号所以$*把所有参数看成以空格分隔的一个字符串整体】
100 200 300 400 500 600    
100 200 300 400 500 600for执行"$*"所以还是显示所有参数都以空格分隔的一个字符串整体】
100for执行"$@"所以各个参数分隔成n份的参数列表显示,每个参数作为一个字符串返回】
200
300
400
500
600
6               【要处理的个数为6个】

[root@localhost ~]#echo $?            【表示前一条执行的脚本未异常】
0
[root@localhost ~]#./qzqz.sh 1 2 3 4
-bash: ./qzqz.sh: 没有那个文件或目录
[root@localhost ~]#echo $?            【非0值,则表示前一条执行的脚本出现异常】
127
[root@localhost ~]#10=10
bash: 10=10: 未找到命令...
[root@localhost ~]#echo $?            【同非0值,表示前一条执行的脚本出现异常】
127




猜你喜欢

转载自blog.csdn.net/TaKe___Easy/article/details/114292358
今日推荐