Skip to content

构建基本脚本

使用多个命令

shell脚本的关键在于输入多个命令并处理命令的结果

如果要一次使用多个命令可以放在一行中, 用冒号分割

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/10$ date; who
2022年 08月 05日 星期五 18:54:26 CST
jiao     tty2         2022-08-05 15:37 (tty2)

只要不超过命令行最大字符数225就行

有一个很大的缺陷:每次运行之前,你都必须在命令提示符下输入整个命令。可以将这些命令组合成一个简单的文本文件,这样就不需要在命令行中手动输入了。在需要运行这些命令时,只用运行这个文本文件就行了

创建shell脚本文件

在创建脚本文件的时候要在第一行指定要使用的shell

bash
  1 #!bin/bash
  2 # 这个脚本展示了谁登陆了以及展示时间
  3 date
  4 who

#为注释, 但是会解释#!

要让命令行找到shell脚本, 要采用两种方法之一

  • 将shell脚本文件所处的目录添加到PATH环境变量中;
  • 在提示符中用绝对或相对文件路径来引用shell脚本文件

有些Linux发行版将$HOME/bin目录添加进了PATH环境变量。它在每个用户的HOME目录下提供了一个存放文件的地方,shell可以在那里查找要执行的命令

更改权限, 添加文件可执行权限

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ chmod u+x shelljb1 
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb1 
2022年 08月 05日 星期五 19:14:35 CST
jiao     tty2         2022-08-05 15:37 (tty2)

显示信息

大多数的shell命令都会产生自己的输出, 这些输出会显示在运行的控制台显示器上, 如果想输出你在干什么, 可以使用

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ echo this is a string
this is a string

通常情况下不需要加引号, 但是当字符串中出现引号的时候就可Python处理一样, 文本中使用其中一种引号,而用另外一种来将字符串划定起来

bash
  1 #!/bin/bash                                                                           
  2 # 这个脚本展示了谁登陆了以及展示时间
  3 echo The tme and the date are
  4 date
  5 echo "Let's see who log in the system"
  6 who
  
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb1 
The tme and the date are
2022年 08月 05日 星期五 19:27:28 CST
Let's see who log in the system
jiao     tty2         2022-08-05 15:37 (tty2)

如果要输出没有换行的语句

bash
echo -n "string"

使用双引号把对应的句子使用引号括起来

使用变量

用shell命令使用其他数据来处理信息, 变量允许临时性的储存信息

环境变量

在脚本中你可以使用环境变量,名再加上$来使用环境变量

bash
  1 #!/bin/bash                                                                           
  2 # 打印操作系统使用者的信息
  3 echo "User info for userid: $USER"
  4 echo UID: $UID
  5 echo HOME: $HOME


jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ chmod u+x shelljb2
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb2
User info for userid: jiao
UID: 1000
HOME: /home/jiao

可以在字符串中使用$来输出变量

如果想输出一个美元符号, 需要输入\$

你可能还见过通过${variable}形式引用的变量。变量名两侧额外的花括号通常用来帮助识别美元符后的变量名

用户变量

允许在shell脚本中定义自己的变量, 定义变量允许临时存放数据在整个脚本使用

用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个。用户变量区分大小写

使用等号将值赋给用户变量。在变量、等号和值之间不能出现空格

bash
var1=10 
var2=-57 
var3=testing 
var4="still more testing

全局变量, 使用$引用

bash
  1 #!/bin/bash                                                                           
  2 # 测试变量
  3 days=10
  4 guest="Katie"
  5 echo "$guest check in $days days ago"
  6 days=5
  7 guest="Jessica"
  8 echo "$guest check in $days days ago"


jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb3
Katie check in 10 days ago
Jessica check in 5 days ago

变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符

替换命令

shell最有用的特性之一就是可以从命令中提取信息, 并把值赋值给变量, 然后可以在脚本之中使用

有两种方法

  • 反引号字符(`)
  • $()格式

命令替换允许你将shell命令的输出赋给变量。尽管这看起来并不那么重要,但它却是脚本编程中的一个主要组成部分

  • 用一对反引号把整个命令行命令围起来
bash
testing=`data`
  • 要么使用$()格式
bash
testing=$(date)

shell会运行命令替换符号中的命令,并将其输出赋给变量testing

也可以直接把上面的格式加入到字符串中, 直接输出

bash
  1 #!/bin/bash                                                                           
  2 testing=`date`
  3 echo "the date is $testing"
  4 
  5 testing2=$(date)
  6 echo "the date is $testing2"
  
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb4
the date is 2022年 08月 05日 星期五 20:04:38 CST
the date is 2022年 08月 05日 星期五 20:04:38 CST

在脚本中通过命令替换获得当前日期并用它来生成唯一文件名

bash
  1 #!/bin/bash                                                                           
  2 # copy the /usr/bin directory listing to a log file 
  3 today=$(date +%y%m%d) 
  4 ls /usr/bin -al > log.$today

**注:(存疑)命令替换会创建一个子shell来运行对应的命令。子shell(subshell)是由运行该脚本的shell所创建出来的一个独立的子shell(child shell)。正因如此,由该子shell所执行命令是无法使用脚本中所创建的变量的

在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候不加入路径,就不会创建子shell。如果你使用的是内建的shell命令,并不会涉及子shell。在命令行提示符下运行脚本时一定要留心

bash
  1 #!/bin/bash                                                                           
  2 # copy the /usr/bin directory listing to a log file 
  3 today=$(date +%y%m%d) 
  4 ls /usr/bin -al > log.$today
  5 ps --forest
  6 echo "$(ps --forest)"
  7 echo "$(echo "$today")"



jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb5
    PID TTY          TIME CMD
   2349 pts/0    00:00:00 bash
   4583 pts/0    00:00:00  \_ shelljb5
   4586 pts/0    00:00:00      \_ ps
    PID TTY          TIME CMD
   2349 pts/0    00:00:00 bash
   4583 pts/0    00:00:00  \_ shelljb5
   4587 pts/0    00:00:00      \_ ps
220805

重定向输入输出

命令输出不只显示在显示器上

bash shell提供了几个操作符,可以将命令的输出重定向到另一个位置(比如文件)

重定向可以用于输入,也可以用于输出,可以将文件重定向到命令输入。

输出重定向

bash
command > outputfile

之前显示器上输出的命令会被保存到指定的文件

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ date > test
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ ls -l
总用量 4
-rw-rw-r-- 1 jiao jiao 43  8月  5 20:58 test
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ cat test
2022年 08月 05日 星期五 20:58:45 CST

创建的文件通过umask设置

如果输出的文件已经存在, 会覆盖之前的内容

追加: 使用>>

输入重定向

将文件的内容输出到重定向的命令之中

wc命令可以对对数据中的文本进行计数。默认情况下,它会输出3个值:

  • 文本的行数
  • 文本的词数
  • 文本的字节数
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ wc < test
  3  16 135

还有另外一种输入重定向的方法,称为内联输入重定向

内联输入重定向符号是远小于号(<<)。除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致

bash
command << marker 
data 
marker
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ wc << EOF
> 123
> 321
> 213
> EOF
      3       3      12

次提示符会持续提示,以获取更多的输入数据,直到你输入了作为文本标记的那个字符串

管道

把一个命令的输出当成另一个命令的输入

bash
command1 | command2

把第一个命令的输出传给第二个

通常使用把输出导入到more, 分页查看

执行数学运算

expr命令

可以识别少量的数学和字符串操作符

QQ图片20220805213450

bash
#!/bin/bash 
# An example of using the expr command 
var1=10 
var2=20 
var3=$(expr $var2 / $var1) 
echo The result is $var3

对于那些容易被shell错误解释的字符,在它们传入expr命令之前,需要使用shell的转义字符(反斜线)将其标出来

bash
expr 5 \* 2

使用方括号

在传递变量的时候可以把他和$一同使用$[ operation ]

bash
  1 #!/bin/bash                                                                           
  2 var1=100
  3 var2=50
  4 var3=45
  5 var4=$[$var1 * ($var2 - $var3)]
  6 echo The final result id $var4

只支持整数的运算

z shell(zsh)提供了完整的浮点数算术操作。如果需要在shell脚本中进行浮点数运算,可以考虑看看z shell

浮点数解决方案

bash内建的计算器

bc基本用法

计算器实际上是一种编程语言

bash计算器能够识别:

  • 数字(整数和浮点数)
  • 变量(简单变量和数组)
  • 注释(以#或C语言中的/* */开始的行)
  • 表达式
  • 编程语句(例如if-then语句)
  • 函数

quit退出

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
3.14 * 5 +0.01
15.71

浮点运算是由内建变量scale控制的。必须将这个值设置为你希望在计算结果中保留的小数位数,否则无法得到期望的结果

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ bc -q
3.14/5
0
scale=5
3.14/5
.62800

-q: 不显示欢迎信息

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ bc -q
var1=10
var2=20
var2/var1
2
var2=var1/4
vr2
0
print var2
2

使用print输出变量

在脚本中使用

可以用命令替换运行bc命令,并将输出赋给一个变量。基本格式如下:

bash
variable=$(echo "options; expression" | bc)

第一部分options允许你设置变量。如果你需要不止一个变量,可以用分号将其分开。expression参数定义了通过bc执行的数学表达式。

bash
  1 #!/bin/bash                                                                           
  2 var1=$(echo "scale=4; 3.44/5" | bc)
  3 echo The answer is $var1

jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test3
The answer is .6880

括号中的echo是为了把整个句子输出为参数

bash
  1 #!/bin/bash                                                                           
  2 var1=100 
  3 var2=45 
  4 var3=$(echo "scale=4; $var1 / $var2" | bc)
  5 echo The answer for this is $var3

jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test4
The answer for this is 2.2222

使用变量

上面的办法使用于比较短的运算

长运算时候bc可以识别重定向, 允许你把一个文件重定向到bc处理

bash
variable=$(bc<<EOF
options
statements
expressions
EOF
)
bash
  1 #!/bin/bash                                                                           
  2 var1=10.46
  3 var2=43.67
  4 var3=33.2
  5 var4=71
  6 var5=$(bc<<EOF
  7 scale=4
  8 a1=($var1 * $var2)
  9 b1=($var3 * $var4)
 10 a1+b1
 11 EOF
 12 )
 13 echo The final answer for this mess is $var5

退出脚本

shell中的每一个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用

查看退出状态码

Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ date
2022年 08月 05日 星期五 23:11:06 CST
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
0
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ asd
Command 'asd' not found, but there are 22 similar ones.
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
127

退出的时候出错, 就会产生一个大于零的状态码

无效命令127

没有特别的规定, 但是有一定的参考值

状态码描述
0命令成功结束
1一般性未知错误
2不适合的shell命令
126命令不可执行
127没找到命令
128无效的退出参数
128+x与Linux信号x相关的严重错误
130通过Ctrl+C终止的命令
255正常范围之外的退出状态码

126 没有相关的权限

1 参数错误

exit命令

默认情况下, shell会以脚本中最后一条命令状态码退出

exit命令允许你在脚本结束时指定一个退出状态码。

bash
  1 #!/bin/bash                                                                           
  2 # 测试退出码
  3 var1=10
  4 var2=30
  5 var3=$[$var1 + $var2]
  6 echo The answer is $var3
  7 exit 5


jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test6
The answer is 40
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
5

**注:**输出的参数最大为255