(1)使用多个命令
- shell脚本的关键在于输入多个命令并处理每个命令的结果,即可以将一个的结果传给另一个命令。Shell脚本允许将多个命令串联为一步使用;
一个简单的脚本:
date;who (将两个命令一起使用,命令之间用“;”隔开,可以用这种方法将任意多个命令串联起来使用,只要不超过最大命令行字符数255就行);这种方式的缺陷在于:每次都要完整输入一遍命令(解决方法是:将命令存储成一个文本文件,使用时直接调用,也即是Shell脚本文件)。
(2)创建Shell脚本文件
- 第一个Shell脚本date_who:
#!/bin/bash
# This script displays the date and who logged on
date
who
-
- 第1行,在shell脚本中,#开头的行都为注释,不会被执行,但第一行除外。“#!”是告诉shell用哪个shell来运行脚本(可以用bash shell运行,也可以是其他的shell);
- 第2行,注释行,用来说明这个脚本的作用,脚本中有注释是个良好的习惯;
运行脚本:$ date_who -bash: date_who: command not found ,问题是bash shell 找不到该脚本;
- 查看一下PATH环境变量就知道问题所在了:
#echo $PATH
/opt/node/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/java/jdk1.7.0_75/bin:/usr/local/java/jdk1.7.0_75/jre/bin:/usr/local/hadoop/bin
- PATH环境变量被设置为只在指定目录中查找命令。两个解决办法:
- 将shell脚本文件所在目录添加到PATH环境变量中;
- 在提示符中使用绝对或者相对路径来引用shell脚本。
- ./date_who
-bash: ./date_who: Permission denied
权限问题,给date_who拥有者添加运行权限,chmod u+x date_who - ./date_who 脚本正常运行。
(3)显示消息(echo命令)
- 在脚本中,如果你想要在控制台上显示信息来告诉脚本使用者脚本在做什么工作,可以使用echo命令完成:
#!/bin/bash
# This script displays the date and who logged on
echo The time and date are:
date
echo "Let's see who's logged into the system:"
who
- 注意echo默认输出的字符串不需要加“”,但是如果输出的字符串中存在”或“”,则需要使用两者中的另一种将字符串括起来;
- echo -n “The time and date are:”(-n 参数实现,结果和字符串在同一行显示);
- 如果需要在输出时,字符串尾部打印一个空格,需要使用“”,即echo -n “The time and date are: ”;
- echo命令是shell脚本中和用户交互的重要工具,还会在显示脚本变量的值时用到它。
(4)使用变量
①环境变量
- Shell维护着一组环境变量,用来记录特定的系统信息。可以使用set命令显示一份完整的活动的环境变量列表:
ABRT_DEBUG_LOG=/dev/null
BASH=/bin/bash
BASHOPTS=cmdhist:expand_aliases:extglob:extquote:force_fignore:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
...
- 使用环境变量:在环境变量前添加$来在脚本中使用它们。如下:
#!/bin/bash
# diplays user information from the system.
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
输出结果是:
User info for userid: xiaoyu1
UID: 1001
HOME: /home/xiaoyu1
- 注意,echo命令中的环境变量会在脚本运行时替换成当前值;在第一个字符串中,我们可以将$USER系统变量放到“”中,shell脚本依然会理解我的意图。但这种方式也存在一个问题:
- echo “The cost is $15” (输出结果为”The cost is 5”原因是:脚本会认为你在引用一个变量,脚本会尝试显示变量$1,但未定义,然后在显示数字5,要显示美元符号就必须在它之前放置一个\,“The cost is \$15”)
②用户变量
var1=10
var2=-57
var3=testing
var4="still more testing"
- 除了环境变量,shell脚本还允许在脚本中定义和使用自己的变量。用户自定义变量允许临时存储数据并在整个脚本中使用;
- 变量命名规范:长度<=20的字母、数字或下划线的文本字符串,且区分大小写;
- 值通过=赋给用户变量,变量、=、值之间不能有空格;
- shell脚本会自动觉得变量值的数据类型。在脚本的整个生命周期里,shell脚本中定义的变量会一直保持着它们的值,直到shell脚本完成时删除;
- 类似于系统变量,用户变量可通过$引用;
③反引号(`)
- 反引号可以将shell命令的输出赋值给变量:
- testing=`date`
- shell 会运行反引号中的命令,并将其输出赋值给变量testing。
- 例子,通过反引号获取当前日期并用它来生成唯一文件名:
#/bin/bash
today=`date +%y%m%d`
echo "today value: "$today
输出结果为 today value: 170512
(5)重定向输入和输出
①输出重定向
- 重定向最基本的类型是将命令的输出发到一个文件中。bash shell 采用>来完成这项功能。
- command>outputfile (如果文件不存在,按照umask的设置创建文件,如果输出文件存在,则重定向操作符会用新内容覆盖已存在文件的内容)
- command>>outputfile (如果文件存在,追加到文件上)
②输入重定向
- 将文件内容重定向到命令。用<完成;
- command < inputfile
- 内联输入重定向,用<<完成,这种方法允许你在命令行而不是在文件中指定输入重定向的数据。除了<<,还必须指定一个文本标记来划分要输入数据的开始和结尾。你可以使用任何字符串的值来作为文本标记,但在数据的开始和结尾必须保持一致:
command << marker
data
marker
- 例如,
#wc << EOF
> xiaoyu
> wang
> EOF
2 2 12
在命令行上使用内联输入时,shell会用PS2环境变量中定义的次提示符来提示输入数据。次提示符会一直提示输入更多数据,直到你输入了作为文本标记的那个字符串值。wc命令会对内联输入重定向提供的数据执行行、单词和字节计数。
(6)管道
- 可以实现,将一个命令的输出重定向到另一个命令,这个过程称为管道连接(piping);
- command1 | command2
- 可以在一条命令中使用任意多条管道;(rpm -qa | sort | more )
- 管道最长用的场景是,将命令产生的长输出结果通过管道传送给more命令,方便查看。
(7)执行数学运算
②使用方括号
- 在bash中,将一个数学运算结果赋值给某个变量时,你可以用$[ operation ]的格式完成:
#var1=$[1 + 5]
#echo $var1
6
- 这种机制,在脚本中同样适用;
- bash shell算术运算中的一个主要限制:
#/bin/bash
var1=100
var2=45
var3=$[ $var1 / $var2]
echo $var3
上面脚本执行的结果是2,bash shell 数学运算符只支持整数运算。
③浮点解决方案
- 最常见的解决方案是用内建的bash计算器,bc;
bc的基本用法:
- bash计算器是允许你在命令行中输入浮点表达式、解释表达式、计算并返回结果的一种编程语言。bash计算器能够识别:
- 数字(整数和浮点数)
- 变量(简单变量和数组)
- 注释(以#开始的行或C语言中的/**/对)
- 表达式
- 编程语句(例如,if-then语句)
- 函数
- bc 在shell提示符下,输入bc命令访问bash计算器;
- quit 退出bash计算器;
scale 浮点运算是由内建的scale变量控制的,在进行浮点运算前必须先设置scale的值以表明你想要精确到小数点后的位数,scale默认值是0;
#bc -q 3 / 5 0 scale=4 3/5 .6000 8/5 1.6000
- 除了普通数字,bash计算器还支持变量:
- 一旦变量的值被定义,就可以在整个bash计算器会话中使用变量。print语句可以打印变量和数字。
#bc -q var1=10 var1*4 40 print var1
- bash计算器是允许你在命令行中输入浮点表达式、解释表达式、计算并返回结果的一种编程语言。bash计算器能够识别:
在脚本中使用bc
使用反引号来运行bc命令并输出赋值给一个变量。基本格式如下:
variable=`echo “options; expression” | bc`
其中,第一部分options用来设置变量,如scale等,多个变量用;分开。expression参数定义通过bc执行的数学表达式。#/bin/bash var1=100 var2=45 var3=`echo "scale=4; $var1 / $var2" |bc` echo $var3 2.2222
上述方法适用于较短的运算,如果有很多运算,在同一个命令行中列出多个表达式就会比较麻烦。我们可以使用内联输入重定向,然后直接在控制台重定向数据。在shell脚本中,可以将输出赋给一个变量:
variable=`bc << EOF options statements expressions EOF `
EOF文本字符串标识了内联重定向数据的开始和结尾。注意,仍需使用反引号来将bc命令的输出赋值给变量。
注意:在bash计算器中创建的变量只在bash计算器中有效,不能再shell中使用这些变量。
(8)退出脚本
- shell中运行的每个命令都是用退出状态码(exit status)来告诉shell它完成了处理。退出状态码是一个0~255之间的整数,在命令结束运行时由命令传递给shell。我们可以捕获这个值并在脚本中使用。
①查看退出状态码
$? Linux提供了专属变量$?来保存上一个执行的命令的退出状态码。我们必须在要查看状态码的命令结束之后马上查看或使用$?变量。此时,变量$?的值后变成shell中执行的最后一条命令的退出状态码:
一个成功结束的命令的退出状态码是0.常用的状态退出码:
②exit命令
默认情况下,shell脚本会以脚本的最后一个命令返回的退出码退出,但可以使用exit命令在脚本结束时指定一个退出状态码:
查询变量$?的值:
可以在exit命令的参数中使用变量:
#/bin/bash var1=100 var2=45 var3=`bc << EOF scale=4 $var1 / $var2 EOF ` echo $var3 exit $var2
需要注意,退出状态码最大只能是255,看下面的例子:
#/bin/bash var1=100 var2=45 var3=`bc << EOF scale=4 $var1 / $var2 EOF ` var4=300 echo $var3 exit $var4
- 上述程序的退出状态码为44,退出状态码减到了0~255区间内。shell通过模运算得到的这个值。一个值的模就是被除后的余数,上述程序的退出状态码就是300除去256的余数,44.
- 注意,退出状态码后续中很有用,后续将会学习if-then语句如何通过检查某个命令返回的状态码来判断命令是否成功。
(9)小结