shell脚本语言的基本结构
shell脚本的用途
- 自动化常用命令
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
shell脚本的基本结构
shell脚本编程:是基于过程式、解释执行的语言
编程语言的基本结构:
- 各种系统命令的组合
- 数据存储:变量、数组
- 表达式:a+b
- 控制语句:if
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
创建shell脚本过程
第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!
第二步:加执行权限
chmod +x hello.sh
第三步:运行脚本
./hello.sh
第一个脚本及运行
#!/bin/bashecho "hello world"
在脚本文件目录下执行
root@sjn:/home# ./hello.sh
hello world
在任意一个目录执行
root@sjn:/opt# /home/hello.sh
hello world
通过bash来执行
root@sjn:/home# bash ./hello.sh
hello world
通过cat和bash来运行
root@sjn:/home# cat hello.sh | bash
hello world
通过curl下载远程服务器上脚本,在本机上运行
curl http://10.0.0.7/hello.sh | bash
通过wget执行
wget -qO - 10.0.0.7/hello.sh | bash
变量
变量类型
变量类型:
- 内置变量,如:PS1,PATH,UID,HOSTNAME,BASH,HISTSIZE
- 用户自定义变量
不同的变量存放的数据不同,决定了
- 数据存储方式
- 参与的运算
- 表示的数据范围
变量的数据类型
- 字符
- 数值:整型、浮点型,bash不支持浮点数
Shell中变量命令法则
- 不能使用程序中保留字:如:if,for
- 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线-
- 顾名知义,用英文名字,并体现出实际作用
- 统一命名规则:驼峰命名
- 变量名大写
- 局部变量小写
- 函数名小写
变量定义和引用
变量的生效范围等标准划分变量类型
- 普通变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效
- 环境变量:生效范围为当前shell进程及其子进程
- 本地变量:生效范围为当前shell进程某代码片段,通常指函数
变量赋值:
name='value'
value可以是多种形式
直接字串:name='root'
变量引用:name="$USER"
命令引用:name=`COMMAND` 或者 name=$(COMMAND)
注:变量赋值是临时生效,当退出shell时,变量会自动删除,无法持久保存。脚本中的变量会随着脚本的结束而被删除。
变量引用
$name
${name}
例子:
root@sjn:/etc/nginx/conf.d# echo $NAME $AGE
sjn 20
root@sjn:/etc/nginx/conf.d# echo $NAME$AGE
sjn20
root@sjn:/etc/nginx/conf.d# echo $NAME_$AGE
20
root@sjn:/etc/nginx/conf.d# echo ${NAME}_$AGE
sjn_20
弱引用和强引用
- “$NMAE” 弱引用,其中的变量引用会被替换为变量值
- '$NAME’强引用,其中的变量引用不会被替换为变量值,而保持原字符串
root@sjn:/home# echo "I am $NAME"
I am root
root@sjn:/home# echo 'I am $NAME'
I am $NAME
显示已定义变量
set
删除变量
unset
范例1:systeminfo.sh
RED="\E[1;31m"
GREEN="\E[1;32m"
END="\E[0m"
echo -e "$GREEN----------------Host systeminfo--------------$END"
echo -e "HOSTNAME: $RED`hostname`$END"
echo -e "IPADDR: $RED`ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -n1`$END"
echo -e "OSVERSION: $RED`cat /etc/issue`$END"
echo -e "KERNEL: $RED`uname -r`$END"
echo -e "CPU: $RED`lscpu | grep 'Model name' | tr -s ' ' | cut -d : -f2`$END"
echo -e "MEMORY: $RED`free -h | grep Mem | tr -s ' ' : | cut -d : -f2`$END"
echo -e "DISK: $RED`lsblk | grep '^sd' | tr -s ' ' | cut -d " " -f4`$END"
echo -e "$GREEN---------------------------------------------$END"
范例2:利用变量实现动态命令
root@sjn:~# CMD=hostname
root@sjn:~# $CMD
sjn
环境变量
- 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
- 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
变量声明和赋值
#一步到位
export name=VALUE
declare -x name=VALUE#分成两步
name=VALUE
export name
变量引用:
$name
${name}
显示所有环境变量
env
printenv
export
declare -x
bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL #shell的嵌套层数
LANG
MAIL
HOSTNAME
HISTSIZE
只读变量
只读变量:只能声明定义,后续不能修改和删除。
声明只读变量
readonly name
declare -r name
查看只读变量
readonly [-p]
declare -r
范例:
root@sjn:~# readonly PI=3.14159
root@sjn:~# echo $PI
3.14159
root@sjn:~# unset PI
-bash: unset: PI: cannot unset: readonly variable
root@sjn:~# echo $PI
3.14159
位置变量
位置变量:在bash shell中内置的变量,在脚本代码中通过命令行传递给脚本的参数。
$1,$2,...,对应第一,第二个等参数
$0, 命令本身,包括路径
$*, 传递给脚本的所有参数,全部参数合为一个字符串
$@, 传递给脚本的所有参数,全部参数为独立字符串
$#, 传递给脚本的参数的个数
注意,$@, $*只在被双引号包起来才会存在差异
清空所有位置变量
set --
范例1:arg.sh
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "The number of arg is $#"
echo "All args are $*"
echo "All args are $@"
echo "The script of name is `basename $0`"
root@sjn:~# ./arg.sh 1 2 3
1st arg is 1
2st arg is 2
3st arg is 3
The number of arg is 3
All args are 1 2 3
All args are 1 2 3
The script of name is arg.sh
范例2
root@sjn:~# cat f1.sh
echo "f1.sh: args are $*"
echo "f1.sh: args are $@"./f2.sh "$*"
root@sjn:~# cat f2.sh
echo "f2.sh: args are $1"
root@sjn:~# ./f1.sh 1 2 3
f1.sh: args are 1 2 3
f1.sh: args are 1 2 3
f2.sh: args are 1 2 3
退出状态码变量
进程执行后,将使用变量$?
保存状态码的相关数字,不同的值表示成功或失败,$?
取值范围0-255
$?的值为0,代表成功
$?的值为1-255,代表失败