前言
本文主要是shell脚本的一些基本语法,小编也是shell菜鸟,不当之处欢迎指正。
一.变量
1.环境变量
#!bin/bash #环境变量 echo "User Info :" echo "user : $USER" echo "UID : $EUID" echo "home : $HOME" echo ''HOSTNAME''
2.用户变量
变量命名规则:
由字母,数字和下划线组成;
大小写敏感
#!bin/bash var1="hello" var2="world" var3=100 echo "$var1 $var2 $var3"
3.特殊变量
变量 | 含义 |
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ |
当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
#!bin/bash echo " file name : $0 " echo " Total Number Parameters : $# " echo " Frist name : $1" echo " Quoted Values: $@ " echo " Quoted Values: $* " echo " $? " echo " shell PID: $$"
$@ 与 $* 的区别
$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。
但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。
#! /bin/bash echo '$@:' for i in $@ do echo $i 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
var=`date +%y%m%d`
echo $var
var1=$(date +%y%m%d)
echo $var1
二.数学计算
1.expr
#!/bin/bash # 注意变量和=之间不能有空格,expr 和 = 之间要有一个空格 var= expr 1 + 2 echo $var
2.[ ] 与 (( ))
#!/bin/bash # var=$[ 1 + 2 ]
echo $var var=$(( 3 + 4 ))
echo $var
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
#!/bin/bash if command then command else command fi
例:
#!/bin/bah # 查找系统中是否存在httpd用户 if grep httpd /etc/passwd then echo "httpd is exist" else echo "httpd not find" fi
1.3 if嵌套
#!/bin/bash if command then command elif command command else command fi
2.test
功能:
数值比较
字符串比较
文件比较
格式:
#!/bin/bash test condition 或 [ command ] --更常用
2.1 数值比较
比较 | 描述 |
-eq | 等于 |
-ge | 大于等于 |
-gt | 大于 |
-le | 小于等于 |
-lt | 小于 |
-ne | 不等于 |
例:
#!bin/bash date if [ $? -eq 0 ] then echo "command is succeed" fi #或 if test date then echo "command is succeed" fi
2.2 字符串比较
比较 | 描述 | 例 |
str1=str2 | 字符串是否相同 | |
str1 !=str2 | 字符串是否不同 | |
str1<str2 | str1是否小于str2 | |
str1>str2 | str1是否大于str2 |
[b>a] && echo "true" (注意>需要转义) |
-n str | 字符串长度非零为真 | [-n "abc"] && echo "str is not null" |
-z str | 字符串长度为0为真 | [-z ""] && echo "str is null" |
2.3 文件比较
比较 | 描述 | 例 |
-d file | 检查file是否存在并是一个目录 | |
-f file | 检查file是否存在并是一个目录 | |
-e file | 检查file是否存在 | |
-r file | 检查文件是否存在并可读 | |
-s file | 检查文件是否存在并非空 | |
-w file | 检查文件是否存在并可写 | |
-x file | 检查文件是否存在并可执行 | |
-O file | 检查文件是否存在并属当前用户所有 | |
-G file | 检查文件是否存在并且默认组与当前用户相同 | |
file1 -nt file2 | file1是否比file2新 |
2.4 复合条件
[condition1] && [condition2]
[condition1] ll [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 "str" *) echo "请重新输入"
esca
4.for
4.1 bash中的for
格式:
for var in command do command done
例:
#!/bin/bash #查看服务状态 for service in apache2 mysqld zabbix-server zabbix-agent do status=$(systemctl status mysql | awk ' /Active/ {print $2,$3}' ) echo $service $status done
例:使用通配符
#!/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 #多变量 for (( i =1,j=10; i<=10; i++,j-- )) do echo $i $j done
5.while
例:
#!/bin/bash #检查站点状态 urls=" https://www.baidu.com https://www.taobao.com https://www.jd.com/abc https://www.12306.cn/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 ] echo $var done
7.循环控制
7.1 break
#!/bin/bash #break跳出当前循环 #break n 跳出n层循环 for (( i=1; i<=10; i++ )) do if [$i -eq 5] then break fi echo $i done
四 . 输入
1.命令行参数
例:
#!/bin/bash echo $1 + 0$2 =$[ $1 +$2 ] #执行命令 ./shell_name 3 4 3 + 4=7
例:
#!/bin/bash #把变量位置左移 while [ -n "$!"] do echo $1 shift done
2.getopts
格式:getopts optstring variable
optstring:选项字母,如果字母要求有参数就加一个:,要去掉错误信息的话可以再optstring前加一个:
variable:保存当前参数
#!/bin/bash #getopts用法 #opt会保存输入的参数,如 r,i,x #OPTARG保存参数值 #参数需要就在后面加一个: 如 i: while getopts rix: opt do case "$opt" in r ) echo " remove all service " ;; i ) echo " install service $OPTARG " ;; x) echo " 可执行 " ;; *) echo " Unknown option :$opt " ;; esac done root@localhost:/# ./getopts.sh -i apache1 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 you name: " name echo " Hello $name "
3.3指定超时时间
#!/bin/bash if read -t 5 -p " Enter you name: " name then echo " Hello $name " else echo " time out" fi
3.4隐藏数据
#!/bin/bash read -s -p " Enter Password: " password echo echo " $password "
五.输出
现实脚本输出的方法:
1.显示器显示
2.将输出重定向到文件
描述符 | 缩写 | 描述 |
0 | STDIN | 标准输入 |
1 | STDOUT | 标准输出 |
2 | STDERR | 标准错误 |
1.脚本中重定向
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
1.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
六.函数
1.基本函数
#!/bin/bash #定义方式1 functionfoo{ echo "This is a func " } #定义方式2 bar() { echo " This is another func " } #函数的调用 foo bar
2.返回值
1.默认退出状态码
#!/bin/bash #定义方式1 function foo{ echo "hello world " } foo echo "Exit status is $?"
2.使用return命令
#!/bin/bash #定义方式1 function foo{ echo " hello world " return 1 } foo echo " Exit status is $?"
3.使用函数输出
#!/bin/bash #定义方式1 function foo{ echo " hello world " return 1 } #赋值给变量 result = foo echo " Exit status is $result "
3.变量
1.传参
#!/bin/bash function status{ systemctl status $1 } status sshd
2.局部变量与全局变量
#!/bin/bash #定义全局变量 hostname = "web" function foo { str = " hello " #使用local定义局部变量 local user = "https" echo " $hostname " echo " $user " } foo #在函数内部定义的局部变量不能再全局使用 echo " $str $user"
3.数组变量
#解决方法 #!/bin/bash function foo { arr =$@ echo "Thr received array is ${ arr[ * ] } " } myarr = (1 2 3 4 ) foo ${ myarr[*] }
七.控制脚本
1.处理信号
1.1. 查看LInux信号
kill -l
在Linux 编程时会遇到最常见的Linux系统信号
信 号 值 描 述 触发 1 SIGHUP 挂起进程 2 SIGINT 终止进程 Ctrl + C 3 SIGQUIT 停止进程 9 SIGKILL 无条件终止进程 15 SIGTERM 尽可能终止进程 17 SIGSTOP 无条件停止进程,但不是终止进程 18 SIGTSTP 停止或暂停进程,但不终止进程 Ctrl+Z 19 SIGCONT 继续运行停止的进程
1.2.脚本执行
1.脚本执行
bash filename.sh 或
chmod +x filename.sh
./ilename.sh
2.后台运行脚本
./test.sh &
nohup ./test.sh &
附:退出状态
可以使用$? 查看上一个命令的退出状态码
状态码 | 含义 |
0 | 命令成功结束 |
1 | 通知未知错误 |
2 | 误用shell命令 |
126 | 命令不可执行 |
127 | 没有找到命令 |
128+x | Linux信号x的严重错误 |
130 | 命令通过Ctrl+C终止 |
255 | 退出状态码越界 |