查看 shell 和 bash:
# 查看系统的 shell 种类
$ cat /etc/shells
# 查看当前用户的 shell
$ echo $SHELL
$ grep root /etc/passwd
# sh为bash的软链接,大多数情况下,脚本的开头使用“#! /bin/bash”和“#! /bin/sh”是没有区别的
但更规范的写法是在脚本的开头使用“#! /bin/bash”。
$ ll /bin/sh
# 查看 bash 版本
$ cat /etc/redhat-release
$ bash --version
在 shell 脚本的第一行,指定要使用的 shell:
#!/bin/bash
# 这是注释
# 打印日期
date
who
如果两个命令一起运行,可以把它们放在同一行,之间使用分号隔开:
$ date ; who
# 另一种创建简单脚本的方式
$ cat >test.sh
echo "I'm xiaocan"
^C
# 直接运行脚本,提示无权限
$ ./test.sh
-bash: ./test.sh: Permission denied
# 使用 sh 可以运行
$ sh test.sh
I'm xiaocan
# 添加执行权限
$ chmod u+x test.sh
$ ./test.sh
I'm xiaocan
如何运行脚本
使用 ./test
的方式执行脚本,需要文件有执行权限,用 chmod u+x
赋予权限。在创建文件时,umask
的值决定了新文件的默认权限设置,在 Ubuntu 中 umask 的值是 022(参加书本第 7 章)
使用 sh test1
的方式执行脚本,不需要文件有执行权限。
使用 source
或 .
运行脚本,它是在当前的 shell 中运行,而不是创建子 shell 运行。
$ cat >test.sh
msg="xiaocan"
^C
$ echo $msg
$ . test.sh
$ echo $msg
xiaocan
使用 echo
需要注意的点
- 默认情况下,不需要使用引号,但是字符串里面有单引号或双引号就有问题了
- 如果用到引号,使用另一个引号包括字符串
- 可用单引号或双引号
- 使用
-n
参数可以不换行 - 单引号中不能使用变量
因此建议,养成使用双引号的习惯。
# 正常情况下不用引号
$ echo This is a test
This is a test
# 字符串含有单引号
$ echo Let's see if this'll work
Lets see if thisll work
# 双引号包括含有单引号的字符串
$ echo "Let's see if this'll work"
Let's see if this'll work
# 单引号包括含有双引号的字符串
$ echo 'He says "shell is easy".'
He says "shell is easy".
# 使用 -n 不换行
$ cat test.sh
echo -n "The time and date are: "
date
msg="This is a test message."
echo "$msg"
echo '$msg'
$ sh test.sh
The time and date are: Fri May 8 21:43:49 CST 2019
This is a test message.
$msg
使用变量
环境变量
shell 维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用 户名、用户的系统ID(也称为UID)、用户的默认主目录以及shell查找程序的搜索路径。可以用 set
命令来显示一份完整的当前环境变量列表。
set
命令查看当前环境变量列表;- 在环境变量名称之前加上美元符号(
$
)来使用环境变量: ```bash $ echo $PATH /home/xiaocan/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
$ echo $USER xiaocan
$ echo $HOME /home/xiaocan
<a name="GU23d"></a>
## 自定义变量
用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个。变量区分大小写。
使用等号将值赋给用户变量。在变量、等号和值之间不能出现空格。
引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符。
引用变量有两种方式:`$variable` 或 `${variable}`
如果 `$` 只是当作正常的美元符号使用,需要转义:
```bash
# 使用定义 $1 变量,因此只显示 5
$ echo "The cost of the itme is $15"
The cost of the itme is 5
# 转义 $
$ echo "The cost of the itme is \$15"
The cost of the itme is $15
命令替换
有两种方法可以将命令输出赋给变量:
- 反引号 `
$()
格式,最好用这种方式。
#!/bin/bash
testing=`date`
today=$(date +%y%m%d)
# 创建日志文件
touch log.$today
重定向输入和输出
>
输出重定向>>
追加输出<
输入重定向
这三个都很简单,不多介绍
$ who > user.txt
$ date >> user.txt
# 使用 wc 统计 user.txt
$ wc < user.txt
内联输入重定向:
使用符号 <<
,还必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致。
shell 会用 PS2
环境变量中定义的次提示符来提示输入数据。
# 查看 PS2 环境变量
$ set | grep PS2
PS2='> '
$ wc << EOF
> hello world
> hello shell
> EOF
2 4 24
管道
- 管道两边的命令会同时运行
- 第一个命令输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何中间文件或缓冲区。
$ rpm -qa | sort | more
数学运算
三种方式
expr
命令,符号两边必须有空格,特殊符号如*
需要转义。在脚本中使用命令替换获取 expr 命令的输出- 使用方括号
$[operation]
,不必注意空格,可以使用任何算数运算,使用 $ 引用变量 - 使用双括号
$((operation))
,不用 $ 就可使用变量,推荐使用。
$ expr 1 + 5
6
$ expr 2 * 5
expr: syntax error
$ expr 2 \* 5
10
$ var1=$[ 1 + 5 ]
$ echo $var1
6
$ var2=$[2*5]
$ echo $var2
10
$ var3=$[$var1 * ($var1 +$var2)]
$ echo $var3
96
# 注意使用变量时不用加 $
$ var4=$((var1*var2))
$ echo $var4
60
$ cat test.sh
#!/bin/bash
var1=10
var2=20
# 使用命令替换获取 expr 的结果
var3=$(expr $var2 / $var1)
echo The result is $var3
$ sh test.sh
The result is 2
bash 计算器
bash shell 只支持整数运算。zsh 支持浮点数运算。
使用内建的 bash 计算器——bc
也可以进行浮点数运算。
使用 bc
命令进入计算器,quit
退出。-q
命令行选项可以不显示欢迎信息。
浮点数运算是由 scale
变量控制的,如果不指定的话,就是 0
bash计算器还能支持变量
$ bc -q
3.14/5
0
scale=4
3.14/5
.6280
var1=10
var2=10*2
print var2
20
quit
$
在脚本中使用 bc
,使用命令替换的方式,格式为:
variable=$(echo "options; expression" | bc)
options 设置变量,可以设置多个,使用分号隔开; express 设置 bc 要执行的数学表达式。
#!/bin/bash
var1=100
var2=45
var3=$(echo "scale=4; $var1 / $var2" | bc)
echo "The answer for this is $var3"
**bc**
和内联重定向结合使用,可以让多个运算过程变得清晰。
需要注意的是,在计算器里面创建的变量,不能在 shell 脚本中使用。
# bc 和内联输入重定向结合使用
var8=$(bc << EOF
scale = 4
a1 = $var4 * $var5
b1 = $var6 * $var7
a1 + b1
EOF
)
退出脚本
退出状态码是一个 0~255的整数值,一个成功结束的命令的退出状态码是 0。如果超过这个范围,最终的结果就是指定的数值除以 256 后得到的余数。
使用 $?
查看上个已执行命令的退出状态码。
使用 exit
命令指定退出状态码。
常用的退出状态码:
状态码 | 描述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的shell命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与 Linux 信号 x 相关的严重错误 |
130 | 通过 Ctrl+C 终止的命令 |
255 | 正常范围之外的退出状态码 |