内容列表
1. 使用多个命令
方式 | 样式 | 介绍 |
---|---|---|
使用; 连接两条命令 | command1 ; command2 | 第一条失败后,第二条仍然会 执行 |
使用&& 连接两条命令 | command1 && command2 | 第一条失败后,第二条不会 执行 |
# 1. 使用;分隔两个命令
[root@vm14 ~]# date ; pwd
2020年 03月 29日 星期日 21:18:41 CST
/root
# 使用;进行分隔的命令,当第一条失败后,第二条仍然会执行
[root@vm14 ~]# date %m ; pwd
date: 无效的日期"%m"
/root
# 2. 使用&&连接
[root@vm14 ~]# date && pwd
2020年 03月 29日 星期日 21:20:31 CST
/root
# 使用&&连接的两条命令,第一条失败后,第二条不会继续执行
[root@vm14 ~]# date %m && pwd
date: 无效的日期"%m"
2. 创建脚本文件
shell脚本第一行内容格式为:#!/bin/bash
,用于指定执行脚本所使用的的shell(shell有多种,此处指定使用bash执行)。当然第一行内容可以缺失
,执行时会使用用户的默认shell执行。
我们通过vim创建第一个测试脚本/root/shell/test1.sh
,内容如下:
#!/bin/bash
# 这一行是注释内容,shell中以#开头的都是注释(不包括第一行shell类型声明)
date
pwd
在目录/root/shell
下脚本执行:
# 方式1,使用sh进行执行
[root@vm14 shell]# sh test1.sh
2020年 03月 29日 星期日 21:36:40 CST
/root/shell
# 方式2,使用相对路径进行执行
[root@vm14 shell]# chmod u+x test1.sh
[root@vm14 shell]# ./test1.sh
2020年 03月 29日 星期日 21:40:02 CST
/root/shell
# 方式3,将/root/shell配置到PATH中,然后使用文件名进行调用
# 3.1 将/root/shell加入PATH
cat >> ~/.bash_profile << EOF
PATH=\$PATH:/root/shell
export PATH
EOF
# 3.2 使PATH生效
[root@vm14 shell]# source ~/.bash_profile
# 3.3 查看PATH,如果输出内容包含/root/shell则说明设置成功
[root@vm14 shell]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/shell
# 3.4 执行shell(需要进行权限修改)
[root@vm14 shell]# test1.sh
2020年 03月 29日 星期日 21:50:17 CST
/root/shell
# 方式4,一般情况下~/bin已经被加入到PATH中,也就是我们只需要在~(用户home)下创建bin目录,然后在bin下创建shell脚本便可直接执行
3. 显示消息
# 使用echo将信息显示到控制台,字符串无需用引号(’|")进行标示
[root@vm14 shell]# echo this is a test message
this is a test message
# 当内容有单引号时,用双引号标示字符串
[root@vm14 shell]# echo "this's a ' message"
this's a ' message
# 当内容有双引号时,用单引号标示字符串
[root@vm14 shell]# echo 'this is a "" message'
this is a "" message
# 同时包含时
[root@vm14 shell]# echo "this'"'s a " message'
this's a " message
创建脚本/root/shell/test2.sh
,内容如下
#!/bin/bash
# 输出当前时间
echo '当前时间是:'
date
脚本执行:
# 在/root/shell下执行
[root@vm14 shell]# sh test2.sh
当前时间是:
2020年 03月 29日 星期日 22:08:00 CST
# 上面的输出中描述与时间不在一行,可以将脚本中echo命令第一个参数改成-n使其输出到一行
# echo -n '当前时间是:'
[root@vm14 shell]# sh test2.sh
当前时间是:2020年 03月 29日 星期日 22:10:59 CST
4. 使用变量
4.1 环境变量
shell维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用
户名、用户的系统ID(也称为UID)、用户的默认主目录以及shell查找程序的搜索路径。可以用
set命令来显示一份完整的当前环境变量列表。
[root@vm14 shell]# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
# 省略
USER=root
XDG_RUNTIME_DIR=/run/user/0
XDG_SESSION_ID=17
_=test2.sh
colors=/root/.dir_colors
获取系统变量
# 显示用户名
[root@vm14 shell]# echo 用户名:$USER
用户名:root
# 显示home
[root@vm14 shell]# echo home:$HOME
home:/root
# 转义字符使用,使用\可以使$不再解读为取变量值
[root@vm14 shell]# echo 商品价格:$15
商品价格:5
[root@vm14 shell]# echo 商品价格:\$15
商品价格:$15
4.2 用户变量
# 定义变量
[root@vm14 shell]# var1=第一个变量
[root@vm14 shell]# var2=第二个变量
[root@vm14 shell]# echo $var1
第一个变量
[root@vm14 shell]# echo $var1 $var2
第一个变量 第二个变量
4.3 命令替换
命令替换:将命令执行结果赋值给变量
# 方式1,使用`符号
[root@vm14 shell]# var1=`date`
[root@vm14 shell]# echo $var1
2020年 03月 29日 星期日 22:25:46 CST
# 方式2,使用$()
[root@vm14 shell]# var2=$(date)
[root@vm14 shell]# echo $var2
2020年 03月 29日 星期日 22:26:28 CST
应用示例
# 根据日期生成日志文件
[root@vm14 shell]# touch $(date +%Y%m%d).log
# 查看生成文件
[root@vm14 shell]# ls
20200329.log test1.sh test2.sh
命令替换会创建一个子shell来运行对应的命令。子shell( subshell)是由运行该脚本的shell
所创建出来的一个独立的子shell( child shell)。正因如此,由该子shell所执行命令是无法
使用脚本中所创建的变量的。
在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候
不加入路径,就不会创建子shell。如果你使用的是内建的shell命令,并不会涉及子shell。
在命令行提示符下运行脚本时一定要留心!
5. 输入输出重定向
5.1 输出重定向
# > 覆盖重定向, command > outputfile
# 将date命令的结果输出到date.log文件中(会覆盖之前内容)
[root@vm14 shell]# date > date.log
[root@vm14 shell]# cat date.log
2020年 03月 29日 星期日 22:35:03 CST
# >> 追加重定向, command >> outputfile
# 将date命令的结果输出到date.log文件中(不覆盖之前内容)
[root@vm14 shell]# date >> date.log
[root@vm14 shell]# cat date.log
2020年 03月 29日 星期日 22:35:03 CST
2020年 03月 29日 星期日 22:36:40 CST
5.2 输入重定向
# < 文件输入重定向, command < inputfile
# 计算文件test1.sh的行数、词数、字节数
[root@vm14 shell]# wc < test1.sh
4 5 121
# 内联输入重定向( inline input redirection),格式如下
command << marker
data
marker
# 示例:
wc << EOF
TEST 1
TEST 2
TEST3
EOF
# 上例中EOF为使用的marker,可以自己定义,比如定义成 END
wc << END
TEST 1
TEST 2
TEST3
END
# 上面两个效果是一致的
6. 管道
管道:将上个命令的输出,传递给下个命令当做输入。
格式:command1 | command2 ,将command1的输出,传递给command2当做输入
# 将date命令的输出,传递给wc命令作为输入
[root@vm14 ~]# date | wc
1 6 43
# ps -ef显示全部进程,通过管道传递给grep命令,进行筛选
[root@vm14 ~]# ps -ef |grep ssh
root 6669 1 0 15:23 ? 00:00:00 /usr/sbin/sshd -D
root 62710 6669 0 21:42 ? 00:00:00 sshd: root@pts/0
root 62742 62715 0 21:44 pts/0 00:00:00 grep --color=auto ssh
7. 数学运算
7.1 expr命令
操作符与操作数之间必须要有空格
,且仅支持整数运算
。
# 加法
[root@vm14 ~]# expr 1 + 1
2
# 减法
[root@vm14 ~]# expr 4 - 1
3
# 乘法,需要对*进行转义
[root@vm14 ~]# expr 1 \* 4
4
# 除法
[root@vm14 ~]# expr 4 / 3
1
expr命令支持的所有命令符列表
7.2 方括号
格式:$[num1 操作符 num2],数字与操作符之间空隔可有可无
,仅支持整数运算
。
# 加法
[root@vm14 ~]# echo $[1+2]
3
# 减法
[root@vm14 ~]# echo $[4 -1]
3
# 乘法,不需要对*进行转义
[root@vm14 ~]# echo $[1*4]
4
# 除法
[root@vm14 ~]# echo $[4/3]
1
7.3 bash计算器
bash计算器能够识别
- 数字(整数和浮点数)
- 变量(简单变量和数组)
- 注释(以#或C语言中的/* */开始的行)
- 表达式
- 编程语句(例如if-then语句)
- 函数
7.3.1 bash计算器初试:
# 安装bash计算器
yum install bc
# 使用,命令行中输入bc,然后回车
[root@vm14 ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'.
# 加法:输入1.1+2.11,然后回车
1.1+2.11
3.21
# 减法:输入4.21-1.1,然后回车
4.21-1.1
3.11
# 乘法:输入1.99*1.21,然后回车
1.99*1.21
2.40
# 除法:输入4/3,然后回车
4/3
1
# 精度问题,上面的除法只保留了整数部分,可以通过scale=4来设置保留4位小数
scale=4
# 重算除法
4/3
1.3333
# 重算乘法
1.99*1.21
2.4079
# 使用quit命令退出
quit
7.3.2 脚本中使用bc
# 示例1,使用$()
[root@vm14 ~]# var1=$(echo 'scale=4; 1.99*1.1'|bc)
[root@vm14 ~]# echo $var1
2.189
# 示例2,使用``
[root@vm14 ~]# echo `echo "scale=4; $var1*$var2"|bc`
2.189
# 示例3 使用内联输入重定向
echo $(bc << EOF
1.99*1.1
EOF
)
# 返回值
2.18
8. 退出脚本
8.1 退出状态码
shell中运行的每个命令都使用退出状态码( exit status)告诉shell它已经运行完毕。退出状态码是一个0~ 255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。
Linux提供了一个专门的变量$?
来保存上个已执行命令的退出状态码。
[root@vm14 ~]# date
2020年 03月 30日 星期一 22:31:09 CST
# 查看date命令的状态码,按照惯例,一个成功结束的命令的退出状态码是0。
[root@vm14 ~]# echo $?
0
# 如果一个命令结束时有错误,退出状态码就是一个正数值。
[root@vm14 ~]# date %m
date: 无效的日期"%m"
[root@vm14 ~]# echo $?
1
Linux退出状态码列表
8.2 exit命令
默认情况下, shell脚本会以脚本中的最后一个命令
的退出状态码退出。exit
命令允许你在脚本结束时指定一个退出状态码。
自定义状态码示例:
创建脚本/root/shell/test3.sh
,内容如下:
#!/bin/bash
# 自定义退出状态码
var1=10
var2=30
var3=$[$var1*$var2]
echo var3 is $var3
# 此处返回300
exit $var3
执行脚本
[root@vm14 shell]# sh test3.sh
var3 is 300
# 返回值是44,因为状态码范围是0-255,当返回值val超过这个范围时返回:val % 256 > 0 ? val % 256 : val % 256 +256
# 此处val = 300 , 也就是返回300 % 256 =44
[root@vm14 shell]# echo $?
44
附录:
expr命令符列表:
操作符 | 功能 |
---|---|
ARG1 | ARG2 | 如果ARG1既不是null也不是零值,返回ARG1;否则返回ARG2 |
ARG1 & ARG2 | 如果没有参数是null或零值,返回ARG1;否则返回0 |
ARG1 < ARG2 | 如果ARG1小于ARG2,返回1;否则返回0 |
ARG1 <= ARG2 | 如果ARG1小于或等于ARG2,返回1;否则返回0 |
ARG1 = ARG2 | 如果ARG1等于ARG2,返回1;否则返回0 |
ARG1 != ARG2 | 如果ARG1不等于ARG2,返回1;否则返回0 |
ARG1 >= ARG2 | 如果ARG1大于或等于ARG2,返回1;否则返回0 |
ARG1 > ARG2 | 如果ARG1大于ARG2,返回1;否则返回0 |
ARG1 + ARG2 | 返回ARG1和ARG2的算术运算和 |
ARG1 - ARG2 | 返回ARG1和ARG2的算术运算差 |
ARG1 * ARG2 | 返回ARG1和ARG2的算术乘积 |
ARG1 / ARG2 | 返回ARG1被ARG2除的算术商 |
ARG1 % ARG2 | 返回ARG1被ARG2除的算术余数 |
STRING : REGEXP | 如果REGEXP匹配到了STRING中的某个模式,返回该模式匹配 |
match STRING REGEXP | 如果REGEXP匹配到了STRING中的某个模式,返回该模式匹配 |
substr STRING POS LENGTH | 返回起始位置为POS(从1开始计数)、长度为LENGTH个字符的子字符串 |
index STRING CHARS | 返回在STRING中找到CHARS字符串的位置;否则,返回0 |
length STRING | 返回字符串STRING的数值长度 |
+ TOKEN | 将TOKEN解释成字符串,即使是个关键字 |
(EXPRESSION) | 返回EXPRESSION的值 |
Linux退出状态码:
状 态 码 | 描 述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的shell命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与Linux信号x相关的严重错误 |
130 | 通过Ctrl+C终止的命令 |
255 | 正常范围之外的退出状态码 |