shell脚本从入门到精通(初级)之入门篇

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

shell脚本从⼊门到精通(初级)之⼊门篇
写在开头
本⽂是阅读《Linux命令⾏与shell脚本编程⼤全》时的⼀些笔记,主要是shell脚本的⼀些基本语法,
还有很多细节和⾼级内容没有写到。

笔者也是shell script菜鸟,如有不当欢迎指正。

⽬录:
1. 环境变量
#!/bin/bash
# 环境变量
echo "User Info:"
echo "user: $USER"
echo "UID : $EUID"
echo "home: $HOME"
echo “$HOSTNAME”
2. ⽤户变量
变量命名规则:
1. 由字母、数字和下划线组成
2. ⼤⼩写敏感
#!/bin/bash
# ⽤户变量
var1=100
var2=hello
var3="hello world"
echo "$var1 $var2 $var3"
3. 特殊变量
变量含义
$0当前脚本的⽂件名
$n传递给脚本或函数的参数。

n 是⼀个数字
$#传递给脚本或函数的参数个数。

$*传递给脚本或函数的所有参数。

$@传递给脚本或函数的所有参数
$?上个命令的退出状态,或函数的返回值。

$$当前Shell进程ID。

对于 Shell 脚本,就是这些脚本所在的进程ID。

#!/bin/bash
echo "Total Number of Parameters : $#"
echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "PID $$"
echo "$?"
$@ 与 $* 的区别
$* 和 $@ 都表⽰传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。

但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为⼀个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

#!/bin/bash
echo ‘$@:’
for i in $@;do
done
echo ‘"$@:"’
for i in "$@";do
echo $i
done
echo ‘$*:’
for i in $*;do
echo $i
done
echo ‘"$*:"’
for i in "$*";do
echo $i
done
结果:
$@:
1
2
3
"$*":
1
2
3
$@:
1
2
3
"$*":
1 2 3
4. ``与$()
把命令的执⾏结果赋给变量的两种⽅式
#!/bin/bash
time=`date +%y%m%d`
time=$(date +%y%m%d)
1. expr
#!/bin/bash
# 注意变量和=之间不能有空格,expr 和 = 之间要有⼀个空格var= expr 1 + 2
echo $var
expr 极难⽤,⼀般不⽤
2. [] 与 (())
#!/bin/bash
#
var=$[ 1 + 2 ]
var=$(( 3 + 4 ))
3. bc
上述两种只能计算整数,对于浮点数需要使⽤bc 在脚本中使⽤bc的格式:
variable=`echo "option; expression" |bc`
#!/bin/bash
var=`echo "scale=2;5/3" | bc`
echo $var
1. if
1.1 if-then
格式:
if command
then
command
fi
#!/bin/bash
if date
then
echo "command is succeed" fi
1.2 if-then-else
格式:
if command
then
command
else
command
fi
例:
#!/bin/bash
# 查找系统中是否存在httpd⽤户if grep httpd /etc/passwd
then
echo "httpd is exist"
else
echo "httpd not find"
fi
1.3 if嵌套
格式:
if command
then
command
elif command
command
else
command
fi
2. test
功能:
1. 数值⽐较
2. 字符串⽐较
3. ⽂件⽐较
格式:
test condition

[ command ] -- 更常⽤2.1 数值⽐较
⽐较描述
-eq等于
-ge⼤于等于
-gt⼤于
-le⼩于等于
-lt⼩于
-ne不等于
例:
#!/bin/bash
date
if [ $? -eq 0 ];then
echo "command is succeed" fi
# 或
echo "command is succeed"
fi
2.2 字符串⽐较
⽐较描述例
str1 = str2字符串是否相同
str1 != str2字符串是否不同
str1 < str2str1是否⽐str2⼩
str1 > str2str1是否⽐str2⼤[ b \> a ] && echo "true" (注意>需要转义)
-n str字符串长度⾮0为真[ -n "str" ] && echo "str is not null"
-z str字符串长度为0为真[ -z "" ] && echo "str is null"
2.3 ⽂件⽐较
⽐较描述例
-d file检查file是否存在并是⼀个⽬录[ -d /data ] && echo "exist" -f file检查file是否存在并是⼀个⽬录
-e file检查file是否存在
-r file检查file是否存在并可读
-s file检查file是否存在并⾮空
-w file检查file是否存在并可写
-x file检查file是否存在并可执⾏
-O file检查file是否存在并属当前⽤户所有
-G file检查file是否存在并且默认组与当前⽤户相同
file1 -nt file2file1是否⽐file2新
file1 -ot file2file1是否⽐file2旧
2.4 复合条件
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
3. case
格式:
case variable in
pattern1 | pattern2) command1;;
pattern3) command2;;
*) default command;;
esca
例:
#!/bin/bash
read -p "input something: " var
case $var in
[0-9])
echo "number";;
[a-z])
echo "character";;
*)
echo "other";;
esac
4. for
4.1 bash中的for
格式:
for var in list
do
command
done
例1:查看服务状态
for service in apache2 mysqld zabbix-server zabbix-agent
do
status=$(systemctl status mysql | awk '/Active/ {print $2,$3}') echo $service $status
done
例2:使⽤通配符
#!/bin/bash
# 注意在$file上加“”,否则如果出现带空格的⽬录名,脚本会出错for file in /tmp/*
do
if [ -d "$file" ]
then
echo "$file" is a directory
elif [ -f "$file" ]
then
echo "$file" is a file
fi
done
4.2 C 语⾔风格的for
例:
#!/bin/bash
for (( i=1; i<=10; i++ ))
do
echo $i
done
#!/bin/bash
# 单变量
for (( i=1; i<=10; i++ ))
do
echo $i
done
# 多变量
for (( i=1,j=10; i<=10; i++,j-- ))
do
echo $i $j
done
5. while
例:检测站点状态
#!/bin/bash
urls="
https://
https://
https:///abc
https:///index/
192.168.1.111
"
for url in $urls;do
count=0
while [ $count -lt 3 ];do
STATUS=$(curl -I -m 10 -o /dev/null -s -w %{http_code} $url) if [ $STATUS -eq 200 ];then
echo "$url OK"
break 1
fi
count=$(($count+1))
done
if [ $count -eq 3 ];then
echo "$url Error"
fi
done
6. until
#!/bin/bash
var=10
until [ $var -eq 0 ];do
var=$[$var-2]
done
7. 控制循环
7.1 break
#!/bin/bash
# break 跳出当前循环
# break n 跳出n层循环
for (( i=0; i<10; i++ ));do
if [ $i -eq 5 ];then
break
fi
echo $i
done
7.2 continue
1. 命令⾏参数
例1:
#!/bin/bash
echo $1+$2=$[$1+$2]
./add.sh 3 4
3+4=7
例2:shift
#!/bin/bash
# 把变量的位置向左移
while [ -n "$1" ];do
echo $1
shift
done
2.getopts
格式:getopts optstring variable
optstring: 选项字母,如果字母要求有参数就加⼀个:,要去掉错误消息的话可以在optstring前加⼀个: variable:保存当前参数
#!/bin/bash
# getopts的⽤法
# opt 会保存输⼊的参数,如 r i
# OPTARG保存参数值
# 参数需要⼀个值就在参数后⾯加⼀个: 如i:
while getopts ri: opt
do
case "$opt" in
i) echo "install service $OPTARG";;
r) echo "remove all service";;
*) echo "Unknown option: $opt";;
esac
done
root@localhost:/# ./getopts.sh -i apache2
install service apache2
root@localhost:/# ./getopts.sh -r
remove all service
root@localhost:/# ./getopts.sh -a
./getopts.sh: illegal option -- a
Unknown option: ?
3. 获得⽤户输⼊ read
3.1 普通⽤法
#!/bin/bash
read name
echo $name
3.2 指定提⽰符
#!/bin/bash
read -p "Enter your name: " name
echo "Hello $name "
3.3 指定超时时间
#!/bin/bash
if read -t 5 -p "Enter your name: " name
then
echo "Hello $name"
else
echo "TIME OUT"
fi
3.4 隐藏数据
#!/bin/bash
read -s -p "Enter passwd: " passwd
echo "$passwd"
3.5 限制输⼊长度
#!/bin/bash
read -n1 -p "Do you want continue[Y/N]?" answer
echo
echo "$answer"
显⽰脚本输出的⽅法:
1. 在显⽰器上显⽰
2. 将输出重定向到⽂件
描述符缩写描述
0STDIN标准输⼊
1STDOUT标准输出
2STDERR标准错误
1. 在脚本中重定向
1. 临时重定向
使⽤场景:在脚本中⽣成错误消息
#!/bin/bash
echo "This is an error message" >&2
echo "This is normal output"
默认情况下Linux 会将STDERR定向到STDOUT
$./error.sh
This is an error message
This is normal output
在执⾏脚本的时候重定向STDERR,ERR⽂本就会被重定向$ ./error.sh 2> error.log
This is normal output
$ cat error.log
This is an error message
2. 永久重定向
⽤exec命令告诉shell在执⾏脚本期间重定向某个特定⽂件描述符#!/bin/bash
exec 2>errout
echo "This is error"
exec 1>testout
echo "testout"
echo "testout to errout" >&2
$ ./test.sh
This is error
$ cat errout
testout to errout
$ cat testout
testout
2. 记录消息
tee : 将输出⼀边发送到显⽰器⼀边发送到⽇志⽂件tee 默认会覆盖原来的⽂件,可以使⽤-a追加
$ date | tee -a date.txt
Fri Nov 23 11:03:15 CST 2018
$ cat date.txt
Fri Nov 23 11:03:07 CST 2018
Fri Nov 23 11:03:15 CST 2018
1.基本函数
#!/bin/bash
# 定义⽅式1
function foo {
echo "This is a func"
}
# 定义⽅式2
bar() {
echo "This is another func"
}
# 函数的调⽤
foo
bar
$ ./func.sh
This is a func
This is another func
2.返回值
1. 默认退出状态码
#!/bin/bash
function foo {
echo "This is a func"
}
foo
echo "Exit status is $?"
2. 使⽤return命令
#!/bin/bash
function foo {
echo "Hello world"
return 2
}
foo
echo "Exit status is $?"
./func.sh
Hello world
Exit status is 2
3. 使⽤函数输出
#!/bin/bash
function foo {
echo "Hello world"
}
foo
# 把函数的输出赋值给变量
result=`foo`
echo "Exit status is $result"
$./func.sh
Hello world
Exit status is Hello world
3.变量
1. 传参
#!/bin/bash
function status {
systemctl status $1
}
status sshd
2. 局部变量与全局变量
#!/bin/bash
# 定义全局变量
hostname="web"
function foo {
str="hello"
# 使⽤ local 定义局部变量
local user="http"
# 可以在函数内使⽤全局变量
echo "$hostname"
echo "$user"
}
foo
# 在函数中定义的局部变量不能在全局使⽤
echo "$str $user"
3. 数组变量
如果将数组变量作为函数参数,函数只会取数组变量的第⼀个值
#!/bin/bash
function foo {
arr=$1
echo "The received array is ${arr[*]}"
}
myarr=(1 2 3 4 5)
foo $myarr
解决⽅法
#!/bin/bash
function foo {
arr=$@
echo "The received array is ${arr[*]}"
}
myarr=(1 2 3 4 5)
# 将该数组变量的值分解成单个的值,然后将这些值作为函数参数使⽤。

foo ${myarr[*]}
1.处理信号
1.1查看Linux信号
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
在Linux编程时会遇到的最常见的Linux系统信号
信号值描述触发
1SIGHUP挂起进程
2SIGINT终⽌进程Ctrl + C
3SIGQUIT停⽌进程
9SIGKILL⽆条件终⽌进程
15SIGTERM尽可能终⽌进程
17SIGSTOP⽆条件停⽌进程,但不是终⽌进程
18SIGTSTP停⽌或暂停进程,但不终⽌进程Ctrl+Z
19SIGCONT继续运⾏停⽌的进程
1.2 捕捉信号
格式:trap command signals

#!/bin/bash
trap "echo 'You Enter Ctrl + C'" SIGINT
for (( i=0; i<10; i++ ));do
echo $i
sleep 1
done
# ./signal.sh
1
^CYou Enter Ctrl + C
2
^CYou Enter Ctrl + C
2.脚本执⾏
1. 脚本执⾏
bash file.sh

chmod +x file.sh
./file.sh
2. 后台运⾏脚本
./test.sh &
nohub ./test.sh &
附:退出状态
可以使⽤$?查看上⼀个命令的退出状态码
状态码含义
0命令成功结束
1通⽤未知错误
2误⽤shell命令
126命令不可执⾏
127没有找到命令
128+x Linux信号x的严重错误
130命令通过Ctrl+C终⽌
255退出状态码越界。

相关文档
最新文档