一文详解shell 脚本语言的基本结构,万字长文,建议收藏

2.1 shell脚本的用途

  • 自动化常用命令
  • 执行系统管理和故障排除
  • 创建简单的应用程序
  • 处理文本或文件

2.2 shell脚本基本结构

shell脚本编程:是基于过程式、解释执行的语言

编程语言的基本结构:

  • 各种系统命令的组合
  • 数据存储:变量、数组
  • 表达式:a + b
  • 控制语句:if

shell脚本:包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shebang机制

#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

2.3 创建shell脚本过程

第一步:使用文本编辑器来创建文本文件

第一行必须包括shell声明序列:#!

示例:

#!/bin/bash

添加注释,注释以#开头

第二步:加执行权限

给予执行权限,在命令行上指定脚本的绝对或相对路径

第三步:运行脚本

直接运行解释器,将脚本作为解释器程序的参数运行

2.4 脚本注释规范

  1. 第一行一般为调用使用的语言
  2. 程序名,避免更改文件名为无法找到正确的文件
  3. 版本号
  4. 更改后的时间
  5. 作者相关信息
  6. 该程序的作用,及注意事项
  7. 最后是各版本的更新简要说明

2.5 第一个脚本

#!SHEBANG
CONFIGURATION_VARIABLES
FUNCTION_DEFINITIONS
MAIN_CODE

shell脚本范例:

#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version:   1.1
# Date: 2017/06/01
# Author: wang
# Email: [email protected]
# Website: www.magedu.com
# Description: This is the first script
# Copyright: 2017 wang
# License: GPL
# ------------------------------------------
echo “hello world”

范例:

#!/bin/bash
#
#********************************************************************
2.6 脚本调试
检测脚本中的语法错误
调试执行
2.7 变量
2.7.1 变量
变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据
2.7.2 变量类型
变量类型:
内置变量,如:PS1,PATH,HISTSIZE
用户自定义变量
不同的变量存放的数据不同,决定了以下
1. 数据存储方式
2. 参与的运算
3. 表示的数据范围
变量数据类型:
字符
数值:整型、浮点型,bash 不支持浮点数
2.7.3 编程语言分类
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-20
#FileName: backup.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
echo -e "\033[1;32mStarting backup...\033[0m"
sleep 2
cp -av /etc/ /data/etc`date +%F`/
echo -e "\033[1;32mBackup is finished\033[0m"

2.6 脚本调试

检测脚本中的语法错误

bash -n /path/to/some_script

调试执行

bash -x /path/to/some_script

2.7 变量

2.7.1 变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

2.7.2 变量类型

变量类型:

  • 内置变量,如:PS1,PATH,HISTSIZE
  • 用户自定义变量

不同的变量存放的数据不同,决定了以下

  1. 1数据存储方式
  2. 2参与的运算
  3. 表示的数据范围

变量数据类型:

  • 字符
  • 数值:整型、浮点型,bash 不支持浮点数

2.7.3 编程语言分类

一文详解shell 脚本语言的基本结构,万字长文,建议收藏_第1张图片

 

静态和动态语言

  • 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
  • 动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

强类型和弱类型语言

  • 强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# ,python

如:以下python代码

print('magedu'+ 10) 提示出错,不会自动转换类型

print('magedu'+str(10)) 结果为magedu10,需要显示转换类型

  • 弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用

如:bash ,php,javascript

2.7.4 Shell中变量命名法则

  • 不能使程序中的保留字:如:if, for
  • 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”
  • 见名知义,用英文名字,并体现出实际作用
  • 统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName
  • 变量名大写
  • 局部变量小写
  • 函数名小写

2.7.5 变量定义和引用

变量的生效范围等标准划分变量类型

  • 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
  • 环境变量:生效范围为当前shell进程及其子进程
  • 本地变量:生效范围为当前shell进程中某代码片断,通常指函数

变量赋值:

name='value'

value 可以是以下多种形式

直接字串:name='root'
变量引用:name="$USER"
命令引用:name=`COMMAND` 或者 name=$(COMMAND)

变量引用:

$name
${name}

弱引用和强引用

  • "$name " 弱引用,其中的变量引用会被替换为变量值
  • '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

显示已定义的所有变量:

set

删除变量:

unset name

范例:

[root@centos8 script40]#cat systeminfo.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: systeminfo.sh
#URL: http://www.magedu.com
#Description: Show system information
#Copyright (C): 2019 All rights reserved
#********************************************************************
COLOR="\033[1;31m"
END="\033[0m"
echo -e  "\033[1;32m-----------------Host systeminfo---------------$END"
echo -e  "HOSTNAME:     $COLOR`hostname`$END"
echo -e  "IPADDR:       $COLOR` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]
{1,3}' |head -n1`$END"
echo -e  "OSVERSION:    $COLOR`cat /etc/redhat-release`$END"
echo -e  "KERNEL:       $COLOR`uname -r`$END"
echo -e  "CPU:         $COLOR`lscpu|grep 'Model name'|tr -s ' '|cut -d : -
f2`$END"
echo -e  "MEMORY:       $COLOR`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"

练习

  • 1、编写脚本 systeminfo.sh,显示当前主机系统信息,包括:主机名,IPv4地址,操作系统版本,内核
  • 版本,CPU型号,内存大小,硬盘大小
  • 2、编写脚本 backup.sh,可实现每日将/etc/目录备份到/backup/etcYYYY-mm-dd中
  • 3、编写脚本 disk.sh,显示当前硬盘分区中空间利用率最大的值
  • 4、编写脚本 links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数,并按连接数从大到小排序

2.7.6 环境变量

变量声明和赋值:

export name=VALUE
declare -x name=VALUE

变量引用:

$name
${name}

显示所有环境变量:

env
printenv
export
declare -x

删除变量:

unset name

bash内建的环境变量

PATH
SHELL
USER
UID
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
_   下划线 表示前一命令的最后一个参数

2.7.7 只读变量

只读变量:只能声明定义,但后续不能修改和删除

声明只读变量:

readonly name
declare  -r name

查看只读变量:

readonly [-p]
declare -r

2.7.8 位置变量

位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异

清空所有位置变量

set --

2.7.9 退出状态码变量

进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255

$?的值为0 代表成功
$?的值是1到255   代表失败

范例:

ping -c1 -W1 hostdown &> /dev/null 
echo $?

用户可以在脚本中使用以下命令自定义退出状态码

exit [n]

注意:

脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

2.7.10 展开命令行

展开命令执行顺序

把命令行分成单个命令词
展开别名
展开大括号的声明({})
展开波浪符声明(~)
命令替换$() 和 ``
再次把命令行分成命令词
展开文件通配(*、?、[abc]等等)
准备I/0重导向(<、>)
运行命令

防止扩展

反斜线(\)会使随后的字符按原意解释

范例:

echo Your cost: \$5.00 
Your cost: $5.00

加引号来防止扩展

单引号(’’)防止所有扩展
双引号(”“)也可防止扩展,但是以下情况例外:$(美元符号)

变量扩展

`` : 反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换

2.7.11 脚本安全和set

set 命令:可以用来定制shell环境

$- 变量

h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭

i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,在脚本中,i选项是关闭的

m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等

B:braceexpand,大括号扩展

H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令

set 命令实现脚本安全

-u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset

-e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit

-o option 显示,打开或者关闭选项

显示选项:set -o

打开选项:set -o 选项

关闭选项:set +o 选项

-x 当执行命令时,打印命令及其参数,类似 bash -x

范例:

[root@centos8 ~]#set -o
allexport     off
braceexpand   on
emacs         on
errexit       off
errtrace       off
functrace     off
hashall       on
histexpand     on
history       on
ignoreeof     off
interactive-comments on
keyword       off
monitor       on
noclobber     off
noexec         off
noglob         off
nolog         off
notify         off
nounset       off
onecmd         off
physical       off
pipefail       off
posix         off
privileged     off
verbose       off
vi             off
xtrace         off

2.8 格式化输出printf

格式

printf "指定的格式" "文本1" ”文本2“……

一文详解shell 脚本语言的基本结构,万字长文,建议收藏_第2张图片

 

常用格式替换符

一文详解shell 脚本语言的基本结构,万字长文,建议收藏_第3张图片

 

说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,- 表示左对齐

常用转义字符

一文详解shell 脚本语言的基本结构,万字长文,建议收藏_第4张图片

 

范例:

[root@centos8 ~]#printf "%s\n" 1 2 3 4
1234
[root@centos8 ~]#printf "%f\n" 1 2 3 4
1.000000
2.000000
3.000000
4.000000
#.2f 表示保留两位小数
[root@centos8 ~]#printf "%.2f\n" 1 2 3 4
1.00
2.00
3.00
4.00
[root@centos8 ~]#printf "(%s)" 1 2 3 4;echo ""
(1)(2)(3)(4)
[root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
 (1) (2) (3) (4) 
[root@centos8 ~]#printf "%s %s\n" 1 2 3 4
1 2 3 4
[root@centos8 ~]#printf "%s %s %s\n" 1 2 3 4
1 2 3 4  
#%-10s 表示宽度10个字符,左对齐
[root@centos8 ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70 
小红 女 18 50
姓名     性别     年龄   体重
小明     男        20   70
小红     女        18   50
#将十进制的17转换成16进制数
[root@centos8 ~]#printf "%X" 17
11[root@centos8 ~]# #将十六进制C转换成十进制
[root@centos8 ~]#printf "%d\n" 0xC
12
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" $VAR
welcome
to
Magedu
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" "$VAR"
welcome to Magedu
[root@centos8 ~]#

2.9 算数运算

bash中的算术运算:

+, -, *, /, %取模(取余), **(乘方)

乘法符号有些场景中需要转义

实现算术运算:

(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...)
(5) declare –i var = 数值
(6) echo ‘算术表达式’ | bc

内建的随机数生成器变量:

$RANDOM   取值范围:0-32767

范例:

#生成 0 - 49 之间随机数
echo $[$RANDOM%50]
#随机字体颜色
[root@centos8 ~]#echo -e "\033[1;$[RANDOM%7+31]mmagedu\033[0m"
magedu

增强型赋值:

+= i+=10 相当于 i=i+10
-= i-=j   相当于 i=i-j
*=
/=
%=
++ i++,++i   相当于 i=i+1
-- i--,--i   相当于 i=i-1

格式:

let varOPERvalue

范例:

#自加3后自赋值
let count+=3
[root@centos8 ~]#i=10
[root@centos8 ~]#let i+=20 
[root@centos8 ~]#echo $i
30
[root@centos8 ~]#j=20
[root@centos8 ~]#let i*=j 
[root@centos8 ~]#echo $i
600

范例:

#自增,自减
let var+=1
let var++
let var-=1
let var--
[root@centos8 ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j"
i=2,j=1
[root@centos8 ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j"
i=2,j=2

2.10 逻辑运算

true, false

1, 0

与:&

1 与 1 = 1

1 与 0 = 0

0 与 1 = 0

0 与 0 = 0

或:|

1 或 1 = 1

1 或 0 = 1

0 或 1 = 1

0 或 0 = 0

非:!

! 1 = 0 ! true

! 0 = 1 ! false

异或:^

异或的两个值,相同为假,不同为真

范例:

[root@centos8 ~]#true 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#false
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! true
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! false
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@centos8 ~]#x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
x=20,y=10

短路运算

  • 短路与

CMD1 短路与 CMD2

第一个CMD1结果为 0 (假 ),总的结果必定为0,因此不需要执行CMD2

第一个CMD1结果为 1 (真),第二个CMD2必须要参与运算,才能得到最终的结果

  • 短路或

CMD1 短路或 CMD2

第一个CMD1结果为1 (真),总的结果必定为1,因此不需要执行CMD2

第一个CMD1结果为0 (假 ),第二个CMD2 必须要参与运算,,才能得到最终的结果

2.11 条件测试命令

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测

试过程

评估布尔声明,以便用在条件性执行中

若真,则状态码变量 返 回 若 假 , 则 状 态 码 变 量? 返回1

条件测试命令

  • test EXPRESSION
  • [ EXPRESSION ]
  • [[ EXPRESSION ]]

注意:EXPRESSION前后必须有空白字符

-v VAR 变量VAR是否设置

示例:判断 NAME 变量是否定义

[ -v NAME ]

范例:

[root@centos8 ~]#unset x
[root@centos8 ~]#test -v x 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#x=10
[root@centos8 ~]#test -v x 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#y=""
[root@centos8 ~]#test -v y
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -v y ]
[root@centos8 ~]#echo $?
0

2.11.2 数值测试

-gt 是否大于
-ge 是否大于等于
-eq 是否等于
-ne 是否不等于
-lt 是否小于
-le 是否小于等于

范例:

[root@centos8 ~]#i=10
[root@centos8 ~]#j=8
[root@centos8 ~]#[ $i -lt $j ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ $i -gt $j ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ i -gt j ] 
-bash: [: i: integer expression expected

2.11.3 字符串测试

-z "STRING" 字符串是否为空,空为真,不空为假
-n "STRING" 字符串是否不空,不空为真,空为假 
= 是否等于
!= 是否不等于
> ascii码是否大于ascii码
< 是否小于
== 左侧字符串是否和右侧的PATTERN相同
 注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的PATTERN所匹配
 注意: 此表达式用于[[ ]]中;扩展的正则表达式

范例:

[root@centos8 ~]#unset str
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=""
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=" "
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
 1
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str1=magedu
[root@centos8 ~]#str2=mage
[root@centos8 ~]#[ $str1 = $str2 ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str2=magedu
[root@centos8 ~]#[ $str1 = $str2 ]
[root@centos8 ~]#echo $?
0

范例:

[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#FILE=test.txt
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[[ "$FILE" != *.log ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=100
[root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=A10
[root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#IP=1.2.3.4
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#IP=1.2.3.4567
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
[root@centos8 ~]#echo $?
1

2.11.4 文件测试

存在性测试

-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

范例:

[root@centos8 ~]#[ -d /etc ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -d /etc/issue ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -L /bin ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -L /bin/ ]
[root@centos8 ~]#echo $?
1

文件权限测试:

-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

范例:

[root@centos8 ~]#[ -w /etc/shadow ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x /etc/shadow ] 
[root@centos8 ~]#echo $?
1

文件属性测试

-s FILE: 是否存在且非空
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2

2.12 关于()和{}

( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash搜索(list)

{ list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }

范例: () 和 {}

[root@centos8 ~]#name=mage;(echo $name;name=wang;echo $name );echo $name
mage
wang
mage
[root@centos8 ~]#name=mage;{ echo $name;name=wang;echo $name; } ;echo $name
mage
wang
wang
[root@centos8 ~]#umask
0022
[root@centos8 ~]#(umask 066;touch f1.txt)
[root@centos8 ~]#ll f1.txt 
-rw------- 1 root root 0 Dec 23 16:58 f1.txt
[root@centos8 ~]#umask
0022
[root@centos8 ~]#( cd /data;ls )
test.log
[root@centos8 ~]#pwd
/root
[root@centos8 ~]#{ cd /data;ls; }
test.log
[root@centos8 data]#pwd
/data
[root@centos8 data]#

2.13 组合测试条件

第一种方式:

[ EXPRESSION1 -a EXPRESSION2 ] 并且
[ EXPRESSION1 -o EXPRESSION2 ] 或者
[ ! EXPRESSION ] 取反

说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持

范例:

[root@centos8 ~]#ll /data/script40/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chmod +x /data/script40/test.sh
[root@centos8 ~]#ll /data/script40/test.sh
-rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chmod -x /data/script40/test.sh
[root@centos8 ~]#ll /data/script40/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -o -x $FILE ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x $FILE ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ ! -x $FILE ] 
[root@centos8 ~]#echo $?
0

第二种方式:

 

COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND   非,取反

一文详解shell 脚本语言的基本结构,万字长文,建议收藏_第5张图片

 

[root@centos7 ~]#[ $[RANDOM%6] -eq 0 ] && rm -rf /* || echo "click"
click

范例:

[root@centos8 ~]#id wang &> /dev/null ||   useradd wang
[root@centos8 ~]#id zhang &> /dev/null ||   useradd zhang
[root@centos8 ~]#getent passwd zhang
zhang:x:1002:1002::/home/zhang:/bin/bash
[root@centos8 ~]#[ -f “$FILE” ] && [[ “$FILE”=~ .*\.sh$ ]] && chmod +x $FILE
[root@centos8 ~]#grep -q no_such_user /etc/passwd || echo 'No such user'
No such user
[root@centos8 ~]#ping -c1 -W1 172.16.0.1 &> /dev/null && echo '172.16.0.1 is 
up' || (echo '172.16.0.1 is unreachable'; exit 1) 
172.16.0.1 is up
test "A" = "B" && echo "Strings are equal" 
test "A"-eq "B" && echo "Integers are equal"
[ "A" = "B" ] && echo "Strings are equal" 
[ "A" -eq "B" ] && echo "Integers are equal"
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
[ -z "HOSTNAME" -o   HOSTNAME = "localhost.localdomain" ]&& hostname 
www.magedu.com

范例:

[root@centos8 ~]#cat /data/script40/ping.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: ping.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
IP=172.16.0.1
ping -c1 -W1 $IP &> /dev/null && echo "$IP is up" || {  echo "$IP is 
unreachable"; exit; }
echo "Script is finished"
[root@centos8 ~]#bash /data/script40/ping.sh
172.16.0.1 is up
Script is finished
[root@centos8 ~]#vim /data/script40/ping.sh
[root@centos8 ~]#cat /data/script40/ping.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: ping.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
IP=172.16.0.123
ping -c1 -W1 $IP &> /dev/null && echo "$IP is up" || {  echo "$IP is 
unreachable"; exit; }
echo "Script is finished"
[root@centos8 ~]#bash /data/script40/ping.sh
172.16.0.123 is unreachable

范例:

[root@centos8 ~]#cat /data/script40/disk_check.sh 
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: disk_check.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
WARNING=80
SPACE_USED=`df|grep '^/dev/sd'|tr -s ' ' %|cut -d% -f5|sort -nr|head -1`
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full" 
| mail -s diskwaring root

练习

1、编写脚本 argsnum.sh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数

2、编写脚本 hostping.sh,接受一个主机的IPv4地址做为参数,测试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可ping通,则提示用户“该IP地址不可访问”

3、编写脚本 checkdisk.sh,检查磁盘分区空间和inode使用率,如果超过80%,就发广播警告空间将满

4、编写脚本 per.sh,判断当前用户对指定参数文件,是否不可读并且不可写

5、编写脚本 excute.sh ,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件

6、编写脚本 nologin.sh和 login.sh,实现禁止和允许普通用户登录系统

2.14 使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量

格式:

read [options] [name ...]

常见选项:

-p 指定要显示的提示

-s 静默输入,一般用于密码

-n N 指定输入的字符长度N

-d ‘字符’ 输入结束符

-t N TIMEOUT为N秒

范例:

[root@centos8 ~]#read 
wang
[root@centos8 ~]#echo $REPLY
wang
[root@centos8 ~]#read NAME TITLE
wang cto
[root@centos8 ~]#echo $NAME
wang
[root@centos8 ~]#echo $TITLE
cto
#Pipelines:A pipeline is a sequence of one or more commands separated by one of 
the control operators | or |&
[root@centos8 ~]#echo magedu | read NAME 
[root@centos8 ~]#echo $NAME
[root@centos8 ~]#echo magedu | { read NAME; echo $NAME; }
magedu
[root@centos8 ~]#read -p "Please input your name: " NAME
Please input your name: wang
[root@centos8 ~]#echo $NAME
wang

范例:

read -p “Enter a filename: “ FILE

范例:鸡兔同笼算法,今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?

[root@centos8 ~]#cat /data/script40/chook_rabbit.sh 
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: chook_rabbit.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
read -p "请输入头的数量: " HEAD
read -p "请输入脚的数量: " FOOT
RABBIT=$[FOOT/2-HEAD]
CHOOK=$[HEAD-RABBIT]
echo "兔子: " $RABBIT
echo "鸡: " $CHOOK

你可能感兴趣的:(笔记,shell)