Shell 脚本的运行方式 与 变量的深入解析
Shell脚本
两种方式相同:
[root@db01 ~]# vim aa.sh
#!/bin/bash
...
...
[root@db01 ~]# vim bb.sh
#!/usr/bin/env bash
...
...
# /usr/bin/env 命令可以自动找出后面所加的命令所在的路径并直接执行.(只找环境变量目录)
[root@db01 /]# /usr/bin/env bash
运行shell脚本的三种方式
方式一:绝对路径,需要当前用户对脚本文件有rx权限
[root@Centos7 ~]# /scripts/day02/hello.sh
-bash: /scripts/day02/hello.sh: Permission denied
[root@Centos7 ~]#
[root@Centos7 ~]# ll !ll /scripts/day02/hello.sh
-rw-r--r-- 1 root root 41 Aug 25 19:43 /scripts/day02/hello.sh
[root@Centos7 ~]# chmod +x !
chmod +x /scripts/day02/hello.sh
[root@Centos7 ~]# /scripts/day02/hello.sh
hello world
方式二:./脚本文件.sh,需要当前用户对脚本文件有rx权限
[root@Centos7 day02]# chmod o=x hello.sh
[root@Centos7 day02]# ll hello.sh
-rwxr-x--x 1 root root 41 Aug 25 19:43 hello.sh
[root@Centos7 day02]# su - egon
Last login: Tue Aug 25 19:48:57 CST 2020 on pts/0
[egon@Centos7 ~]cd /scripts/day02/
[egon@Centos7 day02] ./hello.sh
bash: ./hello.sh: Permission denied
方式三:指定解释器来解释执行脚本程序,需要当前用户对脚本文件有r权限
!! 解释:我们执行的是bash命令,所有用户对bash命令都有执行权限,所以我们只需要考虑脚本文件的读权限即可
[root@Centos7 day02]# chmod o=- hello.sh
[root@Centos7 day02]#
[root@Centos7 day02]# su - egon
Last login: Tue Aug 25 19:49:33 CST 2020 on pts/0
[egon@Centos7 ~]cd /scripts/day02/
[egon@Centos7 day02] ll
total 4
-rwxr-x--- 1 root root 26 Aug 25 19:53 hello.sh
[egon@Centos7 day02]bash hello.sh
bash: hello.sh: Permission denied
[egon@Centos7 day02] exit
logout
[root@Centos7 day02]# chmod o=x hello.sh
[root@Centos7 day02]# su - egon
Last login: Tue Aug 25 19:53:31 CST 2020 on pts/0
[egon@Centos7 ~]!cd
cd /scripts/day02/
[egon@Centos7 day02] bash hello.sh
bash: hello.sh: Permission denied
[egon@Centos7 day02]exit
logout
[root@Centos7 day02]# chmod o=r hello.sh
[root@Centos7 day02]# su - egon
Last login: Tue Aug 25 19:54:07 CST 2020 on pts/0
[egon@Centos7 ~] !cd
cd /scripts/day02/
[egon@Centos7 day02]$ bash hello.sh
hello worl
#在这里,执行的是bash命令,而不是脚本.通过bash读取后面的脚本内容.所以不需要脚本有执行权限也能执行.
方式四:在当前bash进程中运行
前三种方式都是在子bash进程中运行
[root@Centos7 ~]# echo x
[root@Centos7 ~]# source /scripts/day02/hello.sh
hello world
[root@Centos7 ~]# cat !
cat /scripts/day02/hello.sh
x=111
echo "hello world"
[root@Centos7 ~]# echo x
111
[root@Centos7 ~]# unset x
[root@Centos7 ~]#
[root@Centos7 ~]# . /scripts/day02/hello.sh
hello world
[root@Centos7 ~]# echox
11
变量
变量的概念
# 1、什么是变量
量:记录事物的状态
变:事物的状态是可以发生变化的
# 2、为何要有变量
书面解释:变量是编程语言为我们提供的一种存取内存的机制
大白话:编程语言里之所有有变量这种语法是为了让计算机能够像人一样去记忆事物的状态
# 3、如何用变量
原则:先定义、后引用
x=1 # 等号左右两侧不要有空格
echo x
# 注意:没有事先定义变量而取值,会取到空,但是不会报错
[root@Centos7 ~]# echox
[root@Centos7 ~]# x=111
[root@Centos7 ~]# echo x
111
[root@Centos7 ~]#
# 删除变量
[root@Centos7 ~]# x=111
[root@Centos7 ~]# echox
111
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo $x
[root@Centos7 ~]#
变量名的命名
# 注意:变量名的命令应该见名知意,同时遵循如下规则
以字母或下划线开头,剩下的部分可以是:字母、数字、下划线,最好遵循下述规范:
1.以字母开头
2.使用中划线或者下划线做单词的连接
3.同类型的用数字区分
4.对于文件最好加上拓展名
例如: sql_bak.tar.gz,log_bak.tar.bz2
5、不要带有空格、?、*等特殊字符
6、不能使用bash中的关键字,例如if,for,while,do等
7、不要和系统环境变量冲突
# 示例
[root@Centos7 ~]# xxx=18
[root@Centos7 ~]# age=18
[root@Centos7 ~]# salary=18
[root@Centos7 ~]# num=18
[root@Centos7 ~]#
[root@Centos7 ~]# gender="male"
[root@Centos7 ~]# ip="1.1.1.1"
[root@Centos7 ~]#
[root@Centos7 ~]#
[root@Centos7 ~]# age_of_egon=18
[root@Centos7 ~]#
[root@Centos7 ~]#
[root@Centos7 ~]# AgeOfEgon=18
[root@Centos7 ~]#
变量值的三种来源
1、直接赋值
[root@Centos7 ~]# age=18
[root@Centos7 ~]# salary=3.1
[root@Centos7 ~]# name="egon"
[root@Centos7 ~]#
[root@Centos7 ~]# name="EGON"
[root@Centos7 ~]# echo $name
EGON
[root@Centos7 ~]#
2、从键盘输入读取值来赋值给变量名
# -p参数:指定提示信息
[root@Centos7 ~]# read -p "请输入你的操作>>>: " cmd
请输入你的操作>>>: start
[root@Centos7 ~]# echo cmd
start
# -t参数:指定超时时间
[root@Centos7 ~]#
[root@Centos7 ~]# read -t3 -p ">>>: " x
>>>: [root@Centos7 ~]# echox
# -n参数:指定读取的字符个数
[root@Centos7 ~]# read -n2 -p ">>>: " x
>>>: 11[root@Centos7 ~]# read -n2 -p ">>>: " x
>>>: ^C
[root@Centos7 ~]# read -n3 -p ">>>: " x
>>>: 111[root@Centos7 ~]# echo x
111
[root@Centos7 ~]#
# 练习题:
[root@Centos7 day02]# chmod +x login.sh
[root@Centos7 day02]# ./login.sh
请输入您的账号: xxx
请输入您的密码: 123
登录失败
[root@Centos7 day02]# ./login.sh
请输入您的账号: egon
请输入您的密码: 123
登录成
[root@Centos7 day02]# cat login.sh
#!/bin/bash
db_user="egon"
db_pwd="123"
read -p "请输入您的账号: " username
read -p "请输入您的密码: " password
[username == db_user -apassword == $db_pwd ] && echo "登录成功" || echo "登录失败
3、位置参数:$n
01 23..{10}
[root@Centos7 day02]# ./server.sh start
[root@Centos7 day02]# ./server.sh stop
[root@Centos7 day02]# ./server.sh reload
[root@Centos7 day02]# vim server.sh [root@Centos7 day02]# ./server.sh start
./server.sh
start
[root@Centos7 day02]#
[root@Centos7 day02]# cat server.sh #!/bin/bash
echo0
echo 1
echo2
echo 3
echo4
echo 5
echo6
echo 7
echo8
echo 9
echo{10}
echo ${11}
[root@Centos7 day02]# ./server.sh 111 222 333 444 555 666 777 888 999 1000 2000
./server.sh
111
222
333
444
555
666
777
888
999
1000
2000
操作变量值
1、求长度
# 面试题
[root@Centos7 day02]# age=111
[root@Centos7 day02]# echo {age}
111
[root@Centos7 day02]# echo{#age}
3
[root@Centos7 day02]# echo age | wc -L
3
[root@Centos7 day02]# echoage | awk "{print length}"
3
[root@Centos7 day02]#
2、切片(了解)
[root@Centos7 day02]# msg="hello world"
[root@Centos7 day02]# echo {msg}
hello world
[root@Centos7 day02]# echo{msg:4}
o world
[root@Centos7 day02]# echo {msg:4:3}
o w
[root@Centos7 day02]# echo{msg::3}
hel
[root@Centos7 day02]#
3、截断
# 1、删除左边的
[root@Centos7 day02]# url="www.sina.com.cn"
[root@Centos7 day02]# echo {url#www.}
sina.com.cn
[root@Centos7 day02]# echo{url#*.}
sina.com.cn
[root@Centos7 day02]# echo {url##*.}
cn
[root@Centos7 day02]#
# 2、删除右边的
[root@Centos7 day02]# url="www.sina.com.cn"
[root@Centos7 day02]# echo{url%.cn}
www.sina.com
[root@Centos7 day02]# echo {url%.*}
www.sina.com
[root@Centos7 day02]# echo{url%%.*}
www
[root@Centos7 day02]# echo {url%%w*}
[root@Centos7 day02]# echo{url%w*}
ww
[root@Centos7 day02]#
# 3、示例
[root@www ~]# hostname
www.oldboy.com
[root@www ~]# echo HOSTNAME
www.oldboy.com
[root@www ~]# echo{HOSTNAME%%.*}
www
[root@www ~]# echo ${HOSTNAME#www.}
oldboy.com
[root@www ~]#
4、变量的替代
# 变量值的替换 /(替换一个) //(全部替换)
[root@www ~]# url="www.sina.com.cn"
替换一个.为空格
[root@www ~]# echo {url/./}
wwwsina.com.cn
替换所有.为空格
[root@www ~]# echo{url//./}
wwwsinacomcn
替换所有.为|
[root@www ~]# echo {url//./|}
www|sina|com|cn
# 应用批量删除文件名中的linux
[root@www test]# ls
egon_2020_01_linux.txt egon_2020_03_linux.txt egon_2020_05_linux.txt
egon_2020_02_linux.txt egon_2020_04_linux.txt
[root@www test]#
[root@www test]# echo `ls /test/`
egon_2020_01_linux.txt egon_2020_02_linux.txt egon_2020_03_linux.txt egon_2020_04_linux.txt egon_2020_05_linux.txt
[root@www test]# for fname in `ls /test/`
> do
> echofname
> done
egon_2020_01_linux.txt
egon_2020_02_linux.txt
egon_2020_03_linux.txt
egon_2020_04_linux.txt
egon_2020_05_linux.txt
[root@www test]# for fname in `ls /test/`; do mv fname{fname/_linux/}; done
[root@www test]# ls
egon_2020_01.txt egon_2020_02.txt egon_2020_03.txt egon_2020_04.txt egon_2020_05.txt
[root@www test]#
变量操作
1、变量的替代(了解)
#1 {parameter-word}: 当调取变量没有定义过,就返回word字符串信息
[root@www ~]# unset x
[root@www ~]# echo{x-111}
111
[root@www ~]#
[root@www ~]# x=333
[root@www ~]# echo {x-111}
333
[root@www ~]# x=
[root@www ~]# echo{x-111}
#2、{parameter:-word}: 当调取变量没有定义过或者是定义过变量但是值为空, 就返回word字符串信息
[root@www ~]# unset x
[root@www ~]# echo{x:-111} # 变量从未定义过
111
[root@www ~]#
[root@www ~]# x=333
[root@www ~]# echo {x:-111} # 变量定义过,并且值为333
333
[root@www ~]# x=
[root@www ~]# echo{x:-111} # 变量定义过,并且值为空
111
#3、{parameter:=word}:当调取变量信息值为空时或未定义,则设置指定字符串为新的变量值
[root@www ~]# unset x
[root@www ~]# echo {x:=111}
111
[root@www ~]# echox
111
[root@www ~]# x=
[root@www ~]# echo {x:=111}
111
[root@www ~]# echox
111
[root@www ~]# x=333
[root@www ~]# echo {x:=111}
333
[root@www ~]# echox
333
#4、{parameter:?word}:当调取变量信息值为空时或未定义,指定为赋值的错误提示信息
[root@www ~]# unset x
[root@www ~]# echo{x:?变量不存在傻叉}
-bash: x: 变量不存在傻叉
[root@www ~]#
[root@www ~]# x=
[root@www ~]# echo {x:?变量不存在傻叉}
-bash: x: 变量不存在傻叉
[root@www ~]#
[root@www ~]# x=123
[root@www ~]# echo{x:?变量不存在傻叉}
123
#5、{parameter:+word}:当调取变量信息值为空时或未定义,不做任何处理,否则word字符串将替代变量值
[root@www ~]# unset x
[root@www ~]# echo{x:+111} # 没有定义x,此时属于没有值的范畴
[root@www ~]# echo x
[root@www ~]# x=
[root@www ~]# echo{x:+111} # 定义了x但是x的值为空,此时也属于没有值的范畴
[root@www ~]# echo x
[root@www ~]# x=333
[root@www ~]# echo{x:+111} # x有值,有值则替代
111
[root@www ~]# echo $x # 替代不等于赋值
333
[root@www ~]#
2、只读变量(了解)
[root@www ~]# age=18
[root@www ~]# readonly age
[root@www ~]#
[root@www ~]# age=19
-bash: age: readonly variable
[root@www ~]# expr age + 1
19
[root@www ~]# age=`exprage + 1`
-bash: age: readonly variable
[root@www ~]#
3、预定义变量
$*:获取命令行传入的所有的位置参数
$@:获取命令行传入的所有的位置参数
# ps:当调用的脚本格式如下形式,必须使用"$@"
[root@www day03]# ./4.sh aaa bbb ccc "ddd eee" # 注意"ddd eee"
$#:获取命令行传入的所有的位置参数的个数
\$\$: 获取当前进程的pid # $PPID $UID
$?: 获取上一条命令的执行状态,0代表成功,非0代表失败
# 示例1
[root@www day03]# cat 1.sh
#!/bin/bash
echo $*
echo $@
echo $#
echo \$\$
pwd
echo $?
sleep 1000
[root@www day03]#
# 示例2
[root@www day03]# ./2.sh
当前进程的pid:9423
当前进程的ppid:9339
[root@www day03]# echo \$\$
9339
[root@www day03]#
# 示例3:
[root@www day03]# cat 3.sh
#!/bin/bash
[ $# == 2 ] && echo "参数个数正确" || echo "必须传入两个参数"
[root@www day03]#
[root@www day03]# vim 3.sh
[root@www day03]# chmod +x 3.sh
[root@www day03]# ./3.sh
必须传入两个参数
[root@www day03]# ./3.sh 11
必须传入两个参数
[root@www day03]# ./3.sh 11 22
参数个数正确
[root@www day03]#
# 示例4:$*与$@的区别
[root@www day03]# cat 4.sh
#!/bin/bash
for i in $*
do
echo $i
done
echo "================"
for i in $@
do
echo $i
done
[root@www day03]#
[root@www day03]# ./4.sh aaa bbb ccc "ddd eee"
aaa
bbb
ccc
ddd
eee
================
aaa
bbb
ccc
ddd
eee
# 示例5:$*与$@的区别
[root@www day03]# cat 5.sh
#!/bin/bash
#for i in "$*"
#do
# echo $i
#done
echo "================"
for i in "$@"
do
echo $i
done
[root@www day03]#
[root@www day03]# ./5.sh aaa bbb ccc "ddd eee"
================
aaa
bbb
ccc
ddd eee
# 示例6:
[root@www day03]# cat ping.sh
#!/bin/bash
for ip in $*
do
ping -c1 $ip &>/dev/null
[ $? == 0 ] && echo "$ip:up" || echo "$ip:down"
done
[root@www day03]#
[root@www day03]# chmod +x ping.sh
[root@www day03]# ./ping.sh 127.0.0.1 10.10.0.10 10.10.0.11 172.168.11.12
127.0.0.1:up
10.10.0.10:down
10.10.0.11:down
172.168.11.12:down
# 示例7
[root@www day03]# cat ping2.sh
#!/bin/bash
for ip in $*
do
(ping -c1 $ip &>/dev/null ; [ $? == 0 ] && echo "$ip:up" >> ping.log || echo "$ip:down" >> ping.log) &
done