Shell

交互式(Interactive):用户每输入一条命令就立即执行。
批处理(Batch):由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多的命令。

条件测试语句:
文件测试语句;
逻辑测试语句;
整数值比较语句;
字符串比较语句。
image.png
文件测试所用的参数

运算符 作用
-d 测试文件是否为目录类型
-e 测试文件是否存在
-f 判断是否为一般文件
-r 测试当前用户是否有权限读取
-w 测试当前用户是否有权限写入
-x 测试当前用户是否有权限执行

通过Shell解释器的内设$?变量显示上一条命令执行后的返回值。如果返回值为0,则目录存在;如果返回值为非零的值,则意味着目录不存在
$# 代表参数个数
$* 代表所有参数

[root@linux ~]# [ -d /etc/ ] [root@linux ~]# echo $? 0 [root@linux ~]# [ -d /etc/123 ] [root@linux ~]# echo $? 1

在Shell终端中逻辑“与”的运算符号是&&,它表示当前面的命令执行成功后才会执行它后面的命令
除了逻辑“与”外,还有逻辑“或”,它在Linux系统中的运算符号为||,表示当前面的命令执行失败后才会执行它后面的命令。
第三种逻辑语句是“非”,在Linux系统中的运算符号是一个叹号(!),它表示把条件测试中的判断结果取相反值

下面这个示例的执行顺序是,先判断当前登录用户的USER变量名称是否等于root,然后用逻辑运算符“非”进行取反操作,效果就变成了判断当前登录的用户是否为非管理员用户了。最后若条件成立则会根据逻辑“与”运算符输出user字样;或条件不满足则会通过逻辑“或”运算符输出root字样,而如果前面的&&不成立才会执行后面的||符号。

[root@linux ~]# [ $?USER = root ] && echo “user” || echo “root” root

整数比较运算符

运算符 作用
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-lt 是否小于
-le 是否等于或小于
-ge 是否大于或等于

字符串比较运算符

运算符 作用
= 比较字符串内容是否相同
!= 比较字符串内容是否不同
-z 判断字符串内容是否为空

if 条件选择

image.png
/dev/null是一个被称作Linux黑洞的文件,把输出信息重定向到这个文件等同于删除数据(类似于没有回收功能的垃圾箱)
[root@linux ~]# cat chkhost.sh
#!/bin/bash
ping -c 3 -W 3 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo on-line
else
echo off-line
fi
[root@linux ~]# bash chkhost.sh 172.20.10.1
on-line

for 循环语句

image.png

在脚本中使用read命令读取用户输入的密码值,然后赋值给PASSWD变量,并通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。在执行该脚本后,会自动使用从列表文件users.txt中获取到所有的用户名称,然后逐一使用“id 用户名”命令查看用户的信息,并使用$?判断这条命令是否执行成功,也就是判断该用户是否已经存在。

  1. [root@linuxprobe ~]# vim Example.sh
  2. #!/bin/bash
  3. read -p "Enter The Users Password : " PASSWD
  4. for UNAME in `cat users.txt`
  5. do
  6. id $UNAME &> /dev/null
  7. if [ $? -eq 0 ]
  8. then
  9. echo "Already exists"
  10. else
  11. useradd $UNAME &> /dev/null
  12. echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null
  13. if [ $? -eq 0 ]
  14. then
  15. echo "$UNAME , Create success"
  16. else
  17. echo "$UNAME , Create failure"
  18. fi
  19. fi
  20. done

双分支if条件语句与for循环语句相结合,让脚本从主机列表文件ipadds.txt中自动读取IP地址(用来表示主机)并将其赋值给HLIST变量,从而通过判断ping命令执行后的返回值来逐个测试主机是否在线。脚本中出现的$(命令)是一种完全类似于第3章的转义字符中反引号命令的Shell操作符,效果同样是执行括号或双引号括起来的字符串中的命令。

  1. [root@linuxprobe ~]# vim CheckHosts.sh
  2. #!/bin/bash
  3. HLIST=$(cat ~/ipadds.txt)
  4. for IP in $HLIST
  5. do
  6. ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
  7. if [ $? -eq 0 ] ; then
  8. echo "Host $IP is On-line."
  9. else
  10. echo "Host $IP is Off-line."
  11. fi
  12. done
  13. [root@linuxprobe ~]# ./CheckHosts.sh
  14. Host 192.168.10.10 is On-line.
  15. Host 192.168.10.11 is Off-line.
  16. Host 192.168.10.12 is Off-line.

判断本C类网段存活主机

  1. [root@linuxprobe ~]# cat ch.sh
  2. #!/bin/bash
  3. HOST=`ifconfig | grep 255.255.255 | cut -d " " -f 10 | cut -d "." -f 1,2,3`
  4. for sub in {1..255}
  5. do
  6. ping -c 3 $HOST.$sub &>/dev/null
  7. if [ $? -eq 0 ] ; then
  8. echo $HOST.$sub
  9. fi
  10. done

while 条件循环语句

  1. while条件循环语句是一种让脚本根据某些条件来重复执行命令的语句,它的循环结构往往在执行前并不确定最终执行的次数,完全不同于for循环语句中有目标、有范围的使用场景。while循环语句通过判断条件测试的真假来决定是否继续执行命令,若条件为真就继续执行,为假就结束循环。

image.png

该脚本使用$RANDOM变量来调取出一个随机的数值(范围为0~32767),将这个随机数对1000进行取余操作,并使用expr命令取得其结果,再用这个数值与用户通过read命令输入的数值进行比较判断。这个判断语句分为三种情况,分别是判断用户输入的数值是等于、大于还是小于使用expr命令取得的数值。当前,现在这些内容不是重点,我们当前要关注的是while条件循环语句中的条件测试始终为true,因此判断语句会无限执行下去,直到用户输入的数值等于expr命令取得的数值后,这两者相等之后才运行exit 0命令,终止脚本的执行。

  1. [root@linuxprobe ~]# vim Guess.sh
  2. #!/bin/bash
  3. PRICE=$(expr $RANDOM % 1000)
  4. TIMES=0
  5. echo "商品实际价格为0-999之间,猜猜看是多少?"
  6. while true
  7. do
  8. read -p "请输入您猜测的价格数目:" INT
  9. let TIMES++
  10. if [ $INT -eq $PRICE ] ; then
  11. echo "恭喜您答对了,实际价格是 $PRICE"
  12. echo "您总共猜g $TIMES 次"
  13. exit 0
  14. elif [ $INT -gt $PRICE ] ; then
  15. echo "太高了!"
  16. else
  17. echo "太低了!"
  18. fi
  19. done

case 条件测试语句

  1. case语句是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;而如果数据不在所列出的范围内,则会去执行星号(*)中所定义的默认命令。

image.png

  1. [root@linuxprobe ~]# vim Checkkeys.sh
  2. #!/bin/bash
  3. read -p "请输入一个字符,并按Enter键确认:" KEY
  4. case "$KEY" in
  5. [a-z]|[A-Z])
  6. echo "您输入的是 字母。"
  7. ;;
  8. [0-9])
  9. echo "您输入的是 数字。"
  10. ;;
  11. *)
  12. echo "您输入的是 空格、功能键或其他控制字符。"
  13. esac
  14. [root@linuxprobe ~]# bash Checkkeys.sh
  15. 请输入一个字符,并按Enter键确认:6
  16. 您输入的是 数字。
  17. [root@linuxprobe ~]# bash Checkkeys.sh
  18. 请输入一个字符,并按Enter键确认:p
  19. 您输入的是 字母。
  20. [root@linuxprobe ~]# bash Checkkeys.sh
  21. 请输入一个字符,并按Enter键确认:^[[15~
  22. 您输入的是 空格、功能键或其他控制字符。

计划任务

一次性计划任务:今晚11点30分重启网站服务。
长期性计划任务:每周一的凌晨3点25分把/home/wwwroot目录打包备份为backup.tar.gz。

  1. 创建一次性任务计划
  2. [root@linuxprobe ~]# at 11:05
  3. at> systemctl restart network
  4. at> <EOT>
  5. job 1 at Mon Jun 25 11:05:00 2018
  6. [root@linuxprobe ~]# at -l
  7. 1 Mon Jun 25 11:05:00 2018 a root
  8. 删除一次性计划任务
  9. [root@linuxprobe ~]# echo "echo hello" | at 11:09
  10. job 2 at Mon Jun 25 11:09:00 2018
  11. [root@linuxprobe ~]# echo "echo hello" | at 11:09
  12. job 3 at Mon Jun 25 11:09:00 2018
  13. [root@linuxprobe ~]# at -l
  14. 2 Mon Jun 25 11:09:00 2018 a root
  15. 3 Mon Jun 25 11:09:00 2018 a root
  16. [root@linuxprobe ~]# atrm 2
  17. [root@linuxprobe ~]# at -l
  18. 3 Mon Jun 25 11:09:00 2018 a root

周期性任务

  1. 创建、编辑计划任务的命令为“crontab -e”,查看当前计划任务的命令为“crontab -l”,删除某条计划任务的命令为“crontab -r”。另外,如果您是以管理员的身份登录的系统,还可以在crontab命令中加上-u参数来编辑他人的计划任务,用逗号(,)来分别表示多个时间段,例如“8,9,12”表示8月、9月和12月。还可以用减号(-)来表示一段连续的时间周期(例如字段“日”的取值为“12-15”,则表示每月的1215日)。以及用除号(/)表示执行任务的间隔时间(例如“*/2”表示每隔2分钟执行一次任务),在crond服务的计划任务参数中,所有命令一定要用绝对路径的方式来写,如果不知道绝对路径,请用whereis命令进行查询。<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/157775/1587470246723-afbd425b-c4e8-45fc-aac0-ca594e919edb.png#align=left&display=inline&height=70&margin=%5Bobject%20Object%5D&name=image.png&originHeight=70&originWidth=407&size=10520&status=done&style=none&width=407)
字段 说明
取值为0~59的整数
取值为0~23的任意整数
取值为1~31的任意整数
取值为1~12的任意整数
星期 取值为0~7的任意整数,其中0与7均为星期日
命令 要执行的命令或程序脚本
  1. [root@linuxprobe ~]# whereis rm
  2. rm: /usr/bin/rm /usr/share/man/man1/rm.1.gz /usr/share/man/man1p/rm.1p.gz
  3. [root@linuxprobe ~]# crontab -e
  4. crontab: installing new crontab
  5. [root@linuxprobe ~]# crontab -l
  6. 25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
  7. 0 1 * * 1-5 /usr/bin/rm -rf /tmp/*

watch

  1. 以周期性的方式执行给定的指令,指令输出以全屏方式显示。
  1. Usage:
  2. watch [options] command
  3. Options:
  4. -c, --color interpret ANSI color and style sequences
  5. -d 高亮显示变化部分
  6. -e, --errexit exit if command has a non-zero exit
  7. -g, --chgexit exit when output from command changes
  8. -n, --interval <secs> seconds to wait between updates
  9. -p, --precise attempt run command in precise intervals
  10. -t, --no-title turn off header
  11. -x, --exec pass command to exec instead of "sh -c"
  12. -h, --help display this help and exit
  13. -v, --version output version information and exit
  14. For more details see watch(1).

暂停与恢复任务

kali@kali:~$ ping -c 400 localhost > ping_results.txt ^Z

[1]+ Stopped ping -c 400 localhost > ping_results.txt

kali@kali:~$ find / -name sbd.exe

^Z

[2]+ Stopped find / -name sbd.exe

kali@kali:~$ jobs

[1]- Stopped ping -c 400 localhost > ping_results.txt

[2]+ Stopped find / -name sbd.exe

kali@kali:~$ fg %1

ping -c 400 localhost > ping_results.txt

^C

kali@kali:~$ jobs

[2]+ Stopped find / -name sbd.exe

kali@kali:~$ fg

find / -name sbd.exe

/usr/share/windows-resources/sbd/sbd.exe