shell脚本

shell注释

链接

shell文件中编程的作用

就是linux操作命令,运行.sh文件相当于执行linux命令。

.sh就是命令集文件。

shell文件的建立

vi xxx.sh

shell脚本执行四种方式

1,bash xxx.sh

在当前终端启动一个进程去执行脚本

2,./xxxx.sh

新建的文件是没有执行权限的

shell脚本_第1张图片

需要文件有执行权限(x),同样会启动一个子进程执行shell脚本

chmod u+x xxx.sh

3,source xxx.sh

不会启动子进程执行脚本,当前进程终端执行脚本

4,. xxx.sh

不会启动子进程执行脚本,当前进程终端执行脚本

3,4会影响当前终端进程

因为以上原因,使用不同方法操作$0,会得出两种结果。

linux删除键,上下左右变字母

没有vim,下载vim就行

字符串

判断字符串是否为整数

shell脚本_第2张图片

shell命令如果有问题,会提示,但是不会退出脚本的执行。

&> /dev/null------表示不保留任何输出 

  expre length 字符串----计算字符串长短

 shell脚本_第3张图片

shell中的true和false

true和false是shell中的命令。

执行true-----返回成功状态码0

执行false-----返回失败状态码1

shell脚本_第4张图片

数值和退出状态码

数值就是状态码吗

不是

在 Shell 中,作为数字,任何值都是真;作为状态码,0 表示真,非 0 表示假。

变量

定义:name=wu

等号两遍不能有空格

变量三种赋值方法

变量名=value #<==赋值时不加引号

变量名='value' #<==赋值时加单引号

变量名="value" #<==赋值时加双引号

字符串中不适用引号,使用单引号,双引号的区别

主要是对字符串中变量和命令的操作不同

字符串中有变量

字符串如果有空格,必须使用引号

不适用引号和使用双引号-----会解析出变量的值

使用单引号-----不会解析变量值,原样输出

shell脚本_第5张图片

 shell脚本_第6张图片

变量解析出字符串需不需要加引号的问题

如果字符串中含有空格,那么对变量解析就需要加上引号

shell脚本_第7张图片

如上,如果变量不加引号,解析出来的变量含有空格,就变量了两个字符串。

shell脚本_第8张图片

字符串中有命令替换

字符串如果有空格,必须使用引号

不适用引号和使用双引号-----会执行命令,将命令的执行结果拼接字符串

使用单引号-----不会执行命令,原样输出

shell脚本_第9张图片

 

 shell脚本_第10张图片

shell脚本_第11张图片

使用:${name}或者$name

只要在引号中或者没有引号的地方遇到$系统都解析为引用变量。如果$只是一个字符就用\转义。

输出:echo ${name}

变量使用{}和不适用{}的用途

当变量后面连接有其他字符的时候,必须给变量加上大括号{},例如:dbname变量的值加上_tname就要改成${dbname}_tname。

{}约定一个字整体

{}用来指定哪一部分字符串是一个变量。

变量两种取值方式

$a

${a}

字母,数字,下划线组成;不能以数字开头。

表达式赋值给变量

let value=10+20

字符串含有特殊字符时

需要加上双引号或者单引号,只能一单一双,不能单单双双。

空格

content="I am wu."

变量的作用域

1,用户自定义的变量自在本脚有用,除非export导出。

2,变量在脚本文件中定义的位置会影响这个变量在这个文件中的作用域吗:

不影响

只要是在这个文件中定义的变量,无论是在哪定义的,都可以可以在文件中的任意地方使用。

shell脚本_第12张图片

  

命令替换

使用命令替换的地方一定要使用完整格式---$() 

将一个命令的输出结果付给一个变量

1,path=$(pwd)

2,path='netstat -t'

变量值或者变量和值拼接

变量直接或者变量和值之间加上一个非字母,数字,下划线的字符就行,复杂的用“”括起来

shell脚本_第13张图片

shell脚本_第14张图片

命令合并

命令要懂得合并使用

shell脚本_第15张图片

变量的作用域

在当前bash进程创建的变量作用域只在当前进程,bash父进程和bahs子进程访问不了彼此的变量。

bash执行文件,子进程无法访问存在于父进程中的变量。

变量的导出(export)和取消导出(unset)

什么是变量的导出

就是让父进程创建的变量可以在子进程中被访问

详情链接

举例:

定义一个shell脚本coppeliasim:

#! /bin/sh
export Coppeliasim_HOME=/home/xxx/CoppeliaSim_Edu_V4_4_0_rev0_Ubuntu18_04 
$Coppeliasim_HOME/coppeliaSim.sh $*

运行coppeliasim的时候,coppeliasim种的变量Coppeliasim_HOME就会拷贝到coppliaSim.sh脚本中去使用。

什么是变量的取消导出

就是这个子进程不需要访问父进程的某个变量时,用unset取消导出。

unset会直接讲变量从内存销毁。

所以对于export和unset,我本人理解是:

export是在子进程中创建和这个变量一样的变量。

unset的时候也是直接销毁。

shell中的特殊变量

位置变量

shell脚本_第16张图片

 有关进程的变量

shell脚本_第17张图片

环境变量

什么是环境变量

就是一个变量(PATH---必须大写),用来保存指定的路径字符串的变量.

PATH保存多个路径,以冒号:隔开。

PATH里面保存的是什么的路径

命令搜索路径

就是我们执行一个命令时,linux的终端进程会根据配置的PATH路径一个一个路径去找到这个命令,然后执行这个我们输入的命令。

查看所在用户下的所有环境变量的值

env命令

shell脚本_第18张图片

保存当前用户的变量

echo $USER

 USER变量保存当前用户名

保存当前用户ID的变量

echo $UID

shell脚本_第19张图片

环境变量临时配置

shell脚本_第20张图片

注意:是冒号分隔

在当前进程配置的PATH只在当前进程有效。

每一个命令都是一个sh文件,但是为什么不用跑到命令所在文件去执行这个呢,就是因为这些命令的路径都在PATH中记录着。

bash

linux系统里有两个bash命令。

bin下的bash是其他系统里会有的,单数usr下的bash其他系统不一定有。所哟i编程shell文件时,使用到bash时,需要指定使用哪个bash来执行这个shell脚本文件。

shell脚本_第21张图片

 指定使用哪个bash

shell脚本_第22张图片

算术运算

算术运算符

shell脚本_第23张图片

算术运算命令

 shell脚本_第24张图片

(()) 

1,(())是一个命令;

2,(())中使用的变量不需要$符号;

3,只能对整形运算;

4,(())只会完成运算,没有结果输出,如果需要输出或者参与其他计算,一定要$取值;

shell脚本_第25张图片

shell脚本_第26张图片

$[ ] 

1,这个一个命令;

2,使用变量不需要$符号;

3,只能对整形运算;

4,$[]和(())都可以用于一般的算术运算;

5,$[ ]不是if中的 [ ];

为什么echo后面可以是$[],不可以是(())

因为$[]有计算结果输出,(())没有计算结果输出,而是直接(())中就完成了。

let

1,let和$[],(())一样的作用;

2,(())比let效率更好;

var=1

1,var=$var+1

2,let var=$var+1

分析以上1和2的区别:

1的结果:var=1+1

2的结果:var=2

1是字符串,知识会对字符串中的变量进行解析。解析的结果参与字符串拼接;

2是算术运算。

expr

1,expr运算的运算符和数值之间必须要有空格,否则就是字符串;

2,乘法必须转义;

shell脚本_第27张图片

 expre length 字符串----计算字符串长短

bc计算器

终端使用bc,-q表示不显示欢迎信息。

bc (-q)......quit

scale指定小数位数

shell脚本_第28张图片

文件中bc的使用

通过管道,将表达式传输给bc计算器即可。

shell脚本_第29张图片

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

options是bc的参数选项,不是你可以定义变量

bc

复杂表达式使用内联输入重定向输入到bc

注意:

1,print只能在bc 中使用;

2,bc中的表达式可以用()括起来,也可以不用。

shell的退出状态码

0~255

if--then--fi

then后可以有多个语句,语句之间换行就行。

这个语句只有一种判断条件

if--then--else--fi

注意:

1,else后没有then

2,else 后没有判断语句,没有命令。

3,只能有一个if,一个else。

因为命令执行之后只有成功和失败两种。

if---else语句以命令执行状态码是否返回0作为是否进行的条件。返回0表示命令执行成功,执行条件。

嵌套

then和else后可以嵌套if--then--fi和if--else--fi。

每一层嵌套都要用fi来结尾

多个条件判断的if--else

shell脚本_第30张图片

shell脚本_第31张图片

 if--else判断表达式

1,test

表达式非空,返回推出状态码0,否则返回非0.

2,[ ]

整数判断

[ num1 比较符号 num2 ]

第一个方括号之后和第二个方括号之前必须留有空格,否则就会报错.

shell脚本_第32张图片

对于条件测试,bash shell只能处理整数 

字符串判断

shell脚本_第33张图片

 字符串判断,>,<需要进行转义。

-n,-z检查字符串是否为空

if的高级应用

()---开启子进程运行命令

(())---复杂表达式

(())也可以用于其他地方

shell脚本_第34张图片

取反

在0和整数之间取反

表达式取反

在表达式前面加上!就可以,但是!左右都要有空格,连在一起就变成字符串了。

shell脚本_第35张图片

双括号命令既可以在if语句中使用,也可以在脚本中的普通命令里用来赋值。

注意:

1,表达式一定要在(())中,不能:

正确:

如果用于比较的变量为空,会发生什么

报错:需要一元表达式

shell脚本_第36张图片

退出码返回为2,不执行比较成功语句

 命令执行出错,那么命令退出码是什么

shell脚本_第37张图片

shell脚本_第38张图片

文件测试

shell脚本_第39张图片

shell复合条件判断

&&,|| 

shell脚本_第40张图片

case

case variable in

pattern1 | pattern2) commands1;;

pattern3) commands2;;

*) default commands;;

esac

注意:

1,双引号结尾

2,)分割参数和命令

shell脚本文件退出执行

exit (退出状态密码)

$(),$[],${}

$()----命令替换

$[]----整数运算

${}----变量限定

(()),[[]]

(())-----整数运算

[[ ]]-----

五种测试命令的区别 

shell脚本_第41张图片

 if (command)

在bash shell执行command之前,会先创建一个子shell,然后在其中执行命令。如果命令成功结束,则退出状态码(参见第11章)会被设为0,then部分的命令就会被执行。如果命令的退出状态码不为0,则不执行then部分的命令.

[[ ]]---可以使用通配符

1,不是所有的shell都支持双方括号。

2,和其他测试命令的区别就是可以使用通配符。

[ ]

1,整数比较不能使用数学比较符号

for

for var in list

do commands

done 

注意:

1,list可以是一系列值,也可以是一个变量;

2,列表的每一个值以空格分开;

如果特殊情况需要使用其他分隔符,需要改变分隔符---看链接

3,使用转义\对特殊字符进行转义,或者使用引号包含特殊字符;

命令替换作为list

shell脚本_第42张图片

 for获取目录下所有内容

shell脚本_第43张图片

shell脚本_第44张图片

为什么直接指定路径就行,而不需要读出路径中的目录和文件

for命令会遍历/home/rich/test/*匹配的结果。

对list中特殊字符的处理

问题:

shell脚本_第45张图片

有两种方法可以解决这个问题。

·使用转义字符(反斜线)将单引号转义。

·使用双引号来定义含有单引号的值。 

shell脚本_第46张图片

 更改分隔符

链接

for (()) 

shell脚本_第47张图片

shell脚本_第48张图片

shell脚本_第49张图片

while

while test command

do

other commands

done

until

 until test commands

do

other commands

done

循环可嵌套

循环控制

break,continue都可以指定跳出的循环层数

循环的结果重定向放入文件

shell脚本_第50张图片

传递参数

1,位置参数和传递的参数一 一对应;

2,位置参数直接访问,不需要再加$符号。

3,参数之间是以空格分隔的,所以shell会将字符串包含的空格视为两个参数的分隔符。要想在参数值中加入空格,必须使用引号(单引号或双引号均可)

shell脚本_第51张图片

4,如果脚本需要的命令行参数不止9个,则仍可以继续加入更多的参数,但是需要稍微修改一下位置变量名。在第9个位置变量之后,必须在变量名两侧加上花括号,比如${10}。 

5,$n要输出进行转义

shell脚本_第52张图片

获取用户输入---read

read (-p "提示语句")变量

就可以获取用户输入的值,把值付给变量。

shell脚本_第53张图片

可以输入多个变量的多个值,多出的值给最后一个变量

shell脚本_第54张图片

read -t

read -n 

read -s 无显示读取

其实显示了,看不到

read读取文件

注意:read命令读取文件。每次调用read命令都会从指定文件中读取一行文本。

重定向

重定向的左边都是命令,右边是文件,或者需要输入的数据。

重定向的文件如果不存在,会自动创建。

输出重定向

>后面是一个文件,如果文件不存在就创建。

输入重定向---<

输入重定向是文件输出的数据成为命令操作的对象。

内联输入重定向---<<

用来将数据输入到命令

任何字符都可以用来作为内联输入重定向的起止标记。

stdin,stdout,stderr

stdout和stderr

怎么将输出的数据输入一个文件,不输出到显示屏---输出重定向

怎么指定从哪地方获取输入数据---------------------------输入重定向

临时重定向和永久重定向

临时重定向

临时重定向到文件---- 命令 > file

临时重定向到标准输出-----命令 >&1

临时重定向到标准错误-----命令 >&2

临时重定向到标准输入-----命令 <&1

在重定向到文件描述符时,必须在文件描述符索引值之前加一个&。

输入临时重定向就是从屏幕获取输入

输出临时重定向是把输出的数据指定输出到标准输出(屏幕)

临时错误重定向同理。

永久重定向---exec

永久重定向作用域整个脚本执行期间

exec 0

exec 1>file1

exec 2>file2

永久输入重定向:该命令会告诉shell,它应该从文件file中而不是键盘上获取输入。

shell脚本_第55张图片

永久输出重定向是指定输出的数据输出到指定文件。

永久错误重定向同理。

如何临时重定向三个标准

命令 > file 或者 命令 1> file------代表标准输出重定向

命令 2> file--------------代表标准错误重定向

命令 0< file 或者 命令 < file--------------代表标准输入重定向

在shell中,可以使用重定向符号“>”和“2>”来将标准输出和标准错误输出(stderr)分别重定向到文件或者/dev/null,其中2代表标准错误输出,而1代表标准输出:

- >&2 :将标准输出重定向到标准错误输出。

例如,如果要将stderr重定向到一个文件,可以使用下面的命令:

```bash
command 2> error.log
```

上面的命令中,“command”代表要执行的命令,“2>”表示将标准错误输出重定向到文件“error.log”。

如果要将stderr和stdout都重定向到同一个文件,可以使用“&>”:

```bash
command &> output.log
```

上面的命令中,“&>”表示将标准错误输出和标准输出一起重定向到文件“output.log”。

如果想忽略stderr,可以将其重定向到/dev/null:

```bash
command 2> /dev/null
```

上面的命令中,所有标准错误输出都将被丢弃,不会被记录到任何地方。

注意:

1,重定向一定是命令的结果重定向,也就是重定向一定是作用在命令上的。

因为每一句shell都是一个命令。

2,以上都是覆盖方式重定向--->,也可以追加--->>.

shell脚本_第56张图片

>和>&的区别

>------重定向到文件

>&-----重定向到标准输出或者标准错误

shell脚本_第57张图片

 怎么把一个命令执行可能发生的错误保存在日志文件中

命令 2> file

这样,如果命令执行成功,就没有信息写入文件,如果有错误信息就有错误信息写入日志文件。

 怎么清空一个文件

链接

输出

ehco---输出后换行

printf---输出后不换行

用于生成提示的echo命令使用了-n选项。该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据

shell脚本_第58张图片

函数

函数的定义

#!/bin/bash
function list_func(){
    dir=$1
    file_list=`ls $dir`

    for file in $file_list
    do
        if [ -f $dir/$file ]; then
                echo "$dir/$file is file"
        else
                echo "$dir/$file is not file"
        fi
    done
}

1,function关键字

函数的调用

内部调用

function add(){
        a=$1
        sum=$2
        for ((i=0;i<$a;i=$i+1))
        do
                sum=$(($sum+$i))
        done
        echo "sum=$sum"
}

add 100 0

外部调用

#!/bin/bash
  
source ./file_func.sh
list_func ./

1,source 加入头文件,后面指定文件路径
2,函数的调用就直接调用函数名
3,函数中的变量需要参数则直接跟在调用的函数名后面

必须先source 再调用

循环结构

for循环

read -p "Please input range:" num

sum=0

for ((i=0; $i < $num; i=$i+1))
do
        ((sum=$sum+$i))
done

echo $sum
                 

日志

有时需要把信息写入日志文件。

怎么写入:

set

链接

set -e

e----exit:有错误就退出

shell命令行参数解析的两种方式

1,$1,$2,......

2,getopts---解析从命令行输入的参数

链接

shell的错误

1,如果引号使用不对称:

shell编程写入文件的数据没有写入成功的原因

没有同步得到磁盘---------sync

如果字符串变量为空

如果字符串变量为空,这个变量将不能和其他字符串比较,否则比较结果就是失败。

你可能感兴趣的:(linux,运维,服务器)