Shell基础

  • 2019-11-17
  • 1,064
  • 3
  • 2

解释型语言与编译型语言的区别

解释型语言:附带解释器,程序语句可以被实时执行,无法直接捕获代码异常,开发效率高

编译型语言:需要使用编译器,编译源代码,否则程序无法执行,开发效率低

注释:

  • #!/bin/bash 作用:告诉脚本使用的是哪种命令解释器。如不指shell,以当前shell作为执行的shell。
  • shell中以#表示开头,整个行就被当作一个注释。执行时被忽略。
  • shell程序一般以.sh结尾
[root@localhost SHELL]#  vim test.sh
[root@localhost SHELL]# chmod +x test.sh 
[root@localhost SHELL]# ./test.sh 
hello world

创建shell程序的步骤:

  • 第一步:创建一个包含命令和控制结构的文件。
  • 第二步:修改这个文件的权限使它可以执行。
  • 第三步:检测语法错误
  • 第四步:执行

shell脚本通常的执行方式

  • /root/test.sh  或者 ./test.sh (当前路径下执行脚本的话要有执行权限chmod +x test.sh)
  • bash test.sh 或 sh test.sh  (这种方式可以不对脚本文件添加执行权限)
  • source test.sh (可以没有执行权限)
  • sh < test.sh 或者 cat test.sh |sh(bash)

SHELL变量及运用

变量是shell 传递数据的一种方法。变量是用来代表每个值的符号名。我们可以把变量当成一个容器,通过变量,可以在内存中存储数据。也可以在脚本执行中进行修改和访问存储的数据

变量的设置规则

  • 变量名称通常是大写字母,它可以由数字、字母(大小写)和下划线_组成。变量名区分大小写;但是大家要注意变量名称不能以数字开头
  • 等号 = 用于为变量分配值,在使用过程中等号两边不能有空格
  • 变量存储的数据类型是整数值和字符串值
  • 在对变量赋于字符串值时,建议大家用引号将其括起来。因为如果字符串中存在空格隔符号。需要使用单引号或双引号
  • 要对变量进行调用,可以在变量名称前加美元符号$
  • 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含“$变量名”或用${变量名}包含

变量的分类

  1. 用户自定义变量
  2. 环境变量:这种变量中主要保存的是和系统操作环境相关的数据。
  3. 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
  4. 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
    按照变量作用域可以分成2类:全局变量和局部变量。
    局部变量是shell 程序内部定义的,其使用范围仅限于定义它的程序,对其它程序不可见。包括:用户自定义变量、位置变量和预定义变量。
    全局变量是环境变量,其值不随shell 脚本的执行结束而消失

用户定义变量

变量名命名规则:

  • 由字母或下划线打头
  • 不允许数字开头,后面由字母、数字或下划线组成
  • 并且大小写字母意义不同
  • 在使用变量时,在变量名前加$

例1:给变量VAR1赋值

[root@localhost SHELL]# VAR1=123
[root@localhost SHELL]# echo $VAR1
123

例2:错误的赋值方式,不允许数字开头,等号两边不能有空格

[root@localhost SHELL]# VAR2 =456
bash: VAR2: 未找到命令...

[root@localhost SHELL]# VAR2= 456
bash: 456: 未找到命令...

[root@localhost SHELL]# VAR2 = 456
bash: VAR2: 未找到命令...

[root@localhost SHELL]# 3VAR2 = 456
bash: 3VAR2: 未找到命令...

例3:变量值的叠加,使用${}

$name是${name}的简化版本,但是在某些情况下,还必须使用花括号引起的方式来消除歧义并避免意外的结果

[root@localhost SHELL]# var4=mysql
[root@localhost SHELL]# echo $var4
mysql

[root@localhost SHELL]# echo $var4-db.log
mysql-db.log

[root@localhost SHELL]# echo $var4.db.log
mysql.db.log

[root@localhost SHELL]# echo $var4db.log
.log

[root@localhost SHELL]# echo ${var4}db.log
mysqldb.log

删除变量

[root@localhost SHELL]# unset VAR1
[root@localhost SHELL]# echo $VAR1

命令的替换,使用$()或反引号

在命令行调用date命令

  • 扩展:date命令是显示或设置系统时间与日期。
  • -s<字符串>:根据字符串来设置日期与时间。字符串前后必须加上双引号;
  • <+时间日期格式>:指定显示时,使用特定的日期时间格式。

例:格式化输出

[root@localhost SHELL]# date +%Y-%m-%d
2019-11-17

[root@localhost SHELL]# date +"%Y-%m-%d %H:%M:%S"
2019-11-17 15:24:42

[root@localhost SHELL]# date +"%Y-%m-%d %H:%M:%S"-mysql.tar.gz
2019-11-17 15:26:49-mysql.tar.gz

: %y 年份只显示2位,  %Y年份显示4位

date命令加减操作

date +%Y%m%d    显示当天年月日
date -d “+1 day” +%Y%m%d 显示明天的日期
date -d “-1 day” +%Y%m%d 显示昨天的日期
date -d “-1 month” +%Y%m%d 显示上一月的日期
date -d “+1 month” +%Y%m%d  显示下一月的日期
date -d “-1 year” +%Y%m%d 显示前一年的日期
date -d “+1 year” +%Y%m%d 显示下一年的日期
[root@localhost SHELL]# date -d +1day +"%Y-%m-%d %H:%M:%S"
2019-11-18 15:42:10
[root@localhost SHELL]# date -d +1month +"%Y-%m-%d %H:%M:%S"
2019-12-17 15:42:22
[root@localhost SHELL]# date -d +1year +"%Y-%m-%d %H:%M:%S"
2020-11-17 15:42:32

设定时间

date -s 20180523                #设置成20180523,这样会把具体时间设置成空00:00:00

date -s 01:01:01                #设置具体时间,不会对日期做更改

date -s "2018-05-23 01:01:01"   #这样可以设置全部时间

在命令中调用date命令输出值

[root@localhost SHELL]# echo `date`
2019年 11月 17日 星期日 15:57:43 CST

[root@localhost SHELL]# echo $(date)
2019年 11月 17日 星期日 15:57:57 CST

[root@localhost SHELL]# echo `date +%Y-%m-%d`
2019-11-17

命令的嵌套使用,使用$( $( ))

[root@localhost SHELL]# find /root/ -name *.txt
[root@localhost SHELL]# var6=$(tar zcvf root.tar.gz $(find /root -name *.txt))
tar: 从成员名中删除开头的“/”
[root@localhost SHELL]# echo var6
var6
[root@localhost SHELL]# echo $var6
/root/.cache/tracker/db-version.txt /root/.cache/tracker/db-locale.txt /root/.cache/tracker/parser-sha1.txt /root/.cache/tracker/locale-for-miner-user-guides.txt /root/.cache/tracker/locale-for-miner-apps.txt /root/.cache/tracker/last-crawl.txt /root/.cache/tracker/first-index.txt /root/.mozilla/firefox/88aj79s7.default/SiteSecurityServiceState.txt /root/.mozilla/firefox/88aj79s7.default/revocations.txt /root/.mozilla/firefox/88aj79s7.default/SecurityPreloadState.txt /root/.mozilla/firefox/88aj79s7.default/TRRBlacklist.txt /root/.mozilla/firefox/88aj79s7.default/AlternateServices.txt

shell中单引号和双引号区别

  • ‘’  在单引号中所有的字符包括特殊字符($,”,`和\)都将解释成字符本身而成为普通字符。
  • “”  在双引号中,除了$, ”, `和\以外所有的字符都解释成字符本身,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义
能否引用变量 能否引用转移符 能否引用文本格式符(如:换行符、制表符)
单引号
双引号
无引号

:\转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如\$将输出“$”符号,而不当做是变量引用

例:

[root@localhost SHELL]# var1=Shuai
[root@localhost SHELL]# echo $var1 
Shuai
[root@localhost SHELL]# echo \$var1
$var1

例1:给变量值赋于多个单词,需要使用单引号和双引号

[root@localhost SHELL]# var2=Shuai Guoer
bash: Guoer: 未找到命令...
[root@localhost SHELL]# var2="Shuai Guoer"
[root@localhost SHELL]# echo $var2 
Shuai Guoer

例2:赋值时单引号和双引号的区别

[root@localhost SHELL]# var3='love.$var2.com'
[root@localhost SHELL]# var4="love.$var2.com"
[root@localhost SHELL]# echo $var3
love.$var2.com
[root@localhost SHELL]# echo $var4
love.Shuai Guoer.com

:单引号之间的内容原封不动赋值给变量,    双引号之间的内容如有特殊符号会保留它的特殊含义

环境变量

在bash shell中,环境变量分为两类:全局变量局部变量

  • 全局变量:对于shell会话和所有的子shell都是可见的
  • 局部变量: 它只在自己的进程当中使用

pstree         # 以树状图的方式展现进程之间的派生关系,显示效果比较直观

[root@localhost SHELL]# pstree | grep bash
        |-gnome-terminal--+-bash-+-grep
        |                 |-bash

例1:局部变量

[root@localhost SHELL]# var1=Shuai
[root@localhost SHELL]# echo $var1 
Shuai
# 新建一个终端
[root@localhost SHELL]# echo $var1

例2:env命令查看所全局变量

[root@localhost SHELL]# env
[root@localhost SHELL]# env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

例3:使用export把这个局部变量输出为全局变量

[root@localhost SHELL]# export var1=Shuai
[root@localhost SHELL]# echo $var1 
Shuai

例4:让变量永久生效,可以把定义好的变量写入配置文件

当登录系统或新开启一个ssh连接启动bash进程时,一定会按照顺序加载这4个配置文件:

/etc/profile 系统全局环境和登录系统的一些配置
/etc/bashrc shell全局自义配置文件,用于自定义shell
/root/.bashrc 用于单独自定义某个用户的bash
/root/.bash_profile 用户单独自定义某个用户的系统环境
设置永久变量
[root@localhost SHELL]# vim /etc/profile
export var1=Shuai

[root@localhost SHELL]# source /etc/profile        # 重新加载profile文件

[root@localhost ~]# ssh root@192.168.1.11
root@192.168.1.11's password: 
Last login: Sun Nov 17 17:48:19 2019 from 192.168.1.22
[root@localhost ~]# echo $var1
Shuai

设置PATH环境变量

SHELL要执行某一个程序,它要在系统中去搜索这个程序的路径,path变量是用来定义命令和查找命令的目录,当我们安装了第三方程序后,可以把第三方程序bin目录添加到这个path路径内,就可以在全局调用这个第三方程序的

例1:

[root@localhost SHELL]# vim /opt/backup
#!/bin/bash
echo "备份完成"
[root@localhost SHELL]# chmod +x /opt/backup 
[root@localhost SHELL]# /opt/backup 
备份完成
[root@localhost SHELL]# backup
bash: backup: 未找到命令...

将backup命令添加PATH中

第一种方法:

[root@localhost SHELL]# PATH=/opt/:$PATH
[root@localhost SHELL]# backup 
备份完成

第二种方法:

[root@localhost SHELL]# vim /etc/profile
export PATH=/opt/:$PATH
[root@localhost SHELL]# source /etc/profile
[root@localhost SHELL]# backup 
备份完成

shell位置变量

Shell解释执行用户的命令时,将命令行的第一个字符作为命令名,而其它字符作为参数。 

  • $0  获取当前执行shell脚本的文件文件名,包括脚本路径,命令本身
  • $n  获取当前脚本的第n个参数 n=1,2…..n 当n大于9时 用${10}表示

# 使用场景:服务器启动传参数
[root@localhost SHELL]# /etc/init.d/network restart

例1:

[root@localhost SHELL]# vim print.sh

#!/bin/bash
echo "本shell的文件名: $0"
echo "第1个参数:  $1"
echo "第2个参数:  $2"
echo "第3个参数:  $3"
echo "第4个参数:  $4"

[root@localhost SHELL]# chmod +x print.sh 

[root@localhost SHELL]# ./print.sh 111 222 333
本Shell的文件名:./print.sh
第一个参数: 111
第二个参数: 222
第三个参数: 333

例2:shell启动脚本

[root@localhost SHELL]# vim server.sh
#!/bin/bash
############################  服务启动脚本  ##########################
# 判断pid文件是否存在
pid="/root/SHELL/pid"
if [ ! -f $pid ];       then
        echo 0 > $pid
fi
# 服务运行状态
if [ "$1" == "start" ] ; then
        echo "$0 正在启动..."
        echo 1 > $pid
        echo "$0 启动成功"
elif [ "$1" == "stop" ]; then
        echo "$0 正在停止..."
        echo 0 > $pid
        echo "$0 停止成功"
elif [ "$1" == "restart" ];      then
        echo "$0 正在重启..."
        echo 0 > $pid
        echo 1 > $pid
        echo "$0 重启成功"
elif [ "$1" == "status" ];       then
        s=$(cat /root/SHELL/pid)
        if [ "$s" -eq 1 ];      then
                echo "$0 已启动"
        else
                echo "$0 已停止"
        fi
else
        echo "请输入有效参数:start | stop | restart | status"
fi
# 测试
[root@localhost SHELL]# ./server.sh status
./server.sh 已停止
[root@localhost SHELL]# 
[root@localhost SHELL]# ./server.sh start
./server.sh 正在启动...
./server.sh 启动成功
[root@localhost SHELL]# ./server.sh status
./server.sh 已启动
[root@localhost SHELL]# ./server.sh stop
./server.sh 正在停止...
./server.sh 停止成功
[root@localhost SHELL]# ./server.sh status
./server.sh 已停止
[root@localhost SHELL]# ./server.sh restart
./server.sh 正在重启...
./server.sh 重启成功
[root@localhost SHELL]# ./server.sh status
./server.sh 已启动

编写shell启动脚本时遇到的问题!!!

报错:[: ==: 期待一元表达式]

解决方案

  1. 当 if 语句中使用 [ ] 条件修饰符时, $flag 变量必须加上引号。
  2.  当 if 语句中使用 [[]] 条件修饰符时,$flag 变量的引号可有可无

特殊变量

有些变量是一开始执行Script脚本时就会设定,且不能被修改,但我们不叫它只读的系统变量,而叫它特殊变量。这些变量当一执行程序时就有了,以下是一些特殊变量:

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

例子:

[root@localhost SHELL]# vim variable.sh

#!/bin/bash
echo "$* 表示这个程序的所有参数"
echo "$# 表示这个程序的参数个数"

echo "$$ 表示程序的进程ID"

touch /tmp/a.txt &
echo "$! 执行上一个后台指令的PID"
echo "$$ 表示程序的进程ID"
echo "$? 表示上一个程序执行的返回结果"

# 运行结果
[root@localhost SHELL]# ./variable.sh aaa bbb ccc
aaa bbb ccc 表示这个程序的所有参数
3 表示这个程序的参数个数
20464 表示程序的进程ID
20465 执行上一个后台指令的PID
20464 表示程序的进程ID
0 表示上一个程序执行的返回结

例2:常用的环境变量

[root@localhost SHELL]# vim env.sh
#!/bin/bash
echo $HOME
echo $PATH
echo $PWD

[root@localhost SHELL]# bash env.sh 
/root
/opt/:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin:/usr/local/mysql/bin
/root/SHELL

 

Shell基本运算符

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
+ 加法 `expr $a + $b` 结果为 30。
减法 `expr $a – $b` 结果为 -10。
* 乘法 `expr $a \* $b` 结果为  200。
/ 除法 `expr $b / $a` 结果为 2。
% 取余 `expr $b % $a` 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。

注意条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [  $a == $b  ]

(1)对数字的基本计算

expr命令:做比较时,输出结果假为0,1为真;特殊符号用转义符

[root@localhost SHELL]# expr 2 > 3
[root@localhost SHELL]# expr 2 \> 3
0
[root@localhost SHELL]# expr 3 \> 2
1
[root@localhost SHELL]# expr 3 + 2
5
[root@localhost SHELL]# expr 3 - 1
2
[root@localhost SHELL]# expr 3 * 3
expr: 语法错误
[root@localhost SHELL]# expr 3 \* 3
9
[root@localhost SHELL]# expr 3 \/ 3
1

(2)对字符串的处理

[root@localhost SHELL]# expr length "hello world"
11
[root@localhost SHELL]# expr substr "hello world" 1 5
hello

使用$(( ))

格式:$((表达式1,表达2))

特点:

  1. 在双括号结构中,所有表达式可以像c语言一样,如:a++,b–等。a++  等价于 a=a+1
  2. 在双括号结构中,所有变量可以不加入:“$”符号前缀。
  3. 双括号可以进行逻辑运算,四则运算
  4. 双括号结构 扩展了for,while,if条件测试运算
  5. 支持多个表达式运算,各个表达式之间用“,”分开

算术运算

[root@localhost SHELL]# a=$((1+2))
[root@localhost SHELL]# echo $a
3

常用的算数运算符

运算符    意义
++   — 递增及递减,可前置也可以后置
+  –  ! ~ 一元运算的正负号 逻辑与取反
+  –  *  /   % 加减乘除与余数
<   <=   >   >= 比较大小符号
==   != 相等 不相等
>>  << 向左位移 向右位移
& ^   | 位的与 位的异或 位的或
&&  || 逻辑与 逻辑或
? : 条件判断

递增、递减

说明: a++或a–为先赋值再+1或减1  ;  ++a或–a为先加1或减1,然后再进行赋值

[root@localhost SHELL]# echo $((a++))
3
[root@localhost SHELL]# echo $((a++))
4
[root@localhost SHELL]# echo $((a++))
5
[root@localhost SHELL]# echo $((++a))
7
[root@localhost SHELL]# 
[root@localhost SHELL]# echo $((++a))
8
[root@localhost SHELL]# echo $((++a))
9

求1到100的和

[root@xuegod63 opt]# echo $((100*(1+100)/2))
5050

read命令键盘读取变量的值

从键盘读取变量的值,通常用在shell脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在read命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量

read -p "请输入你的密码:" -n 7 -t 5 password
echo -e "\n password is $password"
请输入你的密码:5201314 
password is 5201314

参数说明:

  •  -p:输入提示文字
  •  -n:输入字符长度限制
  •  -t:输入限时
  •  -s: 隐藏输入内容
  •  -r:允许让输入中的内容包括:空格、/、\、 ?等特殊字符串

read从键盘读入数据,赋给变量

[root@localhost SHELL]# read a b
hello world
[root@localhost SHELL]# echo $a $b
hello world

read 综合实例

[root@localhost SHELL]#  vim read.sh  #写入以下内容
#!/bin/bash
read -p "请输入姓名:" NAME
read -p "请输入年龄:" AGE
read -p "请输入性别:" SEX

cat << EOF
*********************
你的基本信息如下:
姓名: $NAME
年龄:$AGE
性别:$SEX
********************
EOF
[root@localhost SHELL]# bash read.sh
请输入姓名:Shuai
请输入年龄:22
请输入性别:男
*********************
你的基本信息如下:
姓名: Shuai
年龄:22
性别:男
********************

Shell echo 命令

1.显示普通字符串:

echo "It is a test"

这里的双引号完全可以省略,以下命令与上面实例效果一致:

echo It is a test

2.显示转义字符

echo "\"It is a test\""

结果将是:

"It is a test"

同样,双引号也可以省略

3.显示变量

read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量

#!/bin/sh
read name 
echo "$name It is a test"

以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:

[root@www ~]# sh test.sh
OK                     #标准输入
OK It is a test        #输出

4.显示换行

echo -e "OK! \n" # -e 开启转义
echo "It it a test"

输出结果:

OK!

It it a test

5.显示不换行

#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"

6.显示结果定向至文件

[root@shuai ~]# echo "my name is Shuai" > myname
[root@shuai ~]# cat myname 
my name is Shuai

7.原样输出字符串,不进行转义或取变量(用单引号)

echo '$name\"'

输出结果:

$name\"

8.显示命令执行结果

echo `date`

注意: 这里使用的是反引号 `, 而不是单引号 

结果将显示当前日期

[root@shuai ~]# echo `date`
2018年 08月 26日 星期日 06:14:39 CS

评论

  • shuai
    shuai回复
    QQbrowser 10 QQbrowser 10 Windows 10 Windows 10

    ***************当你发现自己的才华撑不起野心时,就请安静下来学习吧***************

  • 和光同尘堂回复
    Firefox 43 Firefox 43 GNU/Linux GNU/Linux

    :mianqiang: :mianqiang: :mianqiang: :mianqiang:

发表评论

:zhenbang: :yiwen: :yinyue: :yinxian: :yi: :xxyl: :xinsui: :xiaonian: :weiqu: :tushe: :tu: :taiyang: :taikaixin: :shuijiao: :shenli: :shengqi: :ruo: :qianbi: :qian: :pen: :neng: :mianqiang: :meigui: :lu: :liwu: :kuanghan: :ku: :kaixin: :jinya: :jiku: :huaxin: :huaji: :hu: :heixian: :hehe: :han: :haha: :haha2: :guai: :dangao: :damuzhi: :daku: :chabei: :caihong: :bugaoxing: :bishi: :aixin: :a: :OK: :) :(