shell脚本

shell脚本_第1张图片

 一.什么是shell 

   Shell是一种计算机操作系统的外壳或命令解释器,它提供了用户与操作系统内核进行交互的方式。用户可以通过Shell执行命令,启动程序,管理文件和目录,以及进行各种系统操作。

   Shell可以以交互模式或批处理模式运行。在交互模式中,用户可以直接在Shell中输入命令,并立即查看结果。而在批处理模式中,用户可以将一系列的命令写入脚本文件,然后通过执行脚本文件一次性地运行这些命令,这对于自动化任务非常有用。

   常见的Shell有许多种,如Bash(Bourne Again Shell)、sh(Bourne Shell)、csh(C Shell)、ksh(Korn Shell)等。不同的Shell具有不同的语法和功能,但它们的基本原理和作用都是相似的。

 shell脚本_第2张图片

shell是一块包裹着系统核心的壳,处于操作系统的最外层,与用户直接对话,把用户的输入,解释给操作系统,然后处理操作系统的输出结果,输出到屏幕给与用户看到结果。

Shell的作用可以总结为以下几个方面:

1. 命令执行:Shell允许用户通过输入命令来执行各种操作系统的功能和程序。用户可以运行系统命令、启动应用程序、管理文件和目录等。

2. 程序脚本:Shell提供了脚本编程的功能,用户可以编写一系列的命令和逻辑,存储为脚本文件,并通过Shell解释器执行。这样可以实现自动化任务、批处理操作,提高工作效率。

3. 环境配置:用户可以通过Shell配置和管理系统的环境。例如,设置系统变量、定制命令别名、配置默认编辑器等。这样可以根据个人需求和习惯来调整系统的行为和外观。

4. 输入输出重定向:Shell提供了重定向功能,可以将命令的输入从键盘改为文件,将输出保存到文件中,或者将命令的输出作为其他命令的输入。这样可以方便地进行文件操作、数据处理和管道操作。

5. 权限控制:Shell可以通过访问控制机制管理用户对系统资源的访问权限。例如,在使用Shell执行命令时,系统会检查用户的权限,只允许具有足够权限的用户执行特殊的操作。

总而言之,Shell是用户与操作系统内核进行交互的接口,提供了执行命令、编写脚本、配置环境、管理权限等功能,使用户能够更自由地使用和控制计算机系统。

shell脚本_第3张图片

·命令行操作,shell解释执行后,输出结果到黑屏命令行界面

·图形化操作,shell接受点击动作,输出图案数据

shell命令:由C语言编写后,gcc编译成二进制文件,存储在usr/bin目录,通过shell命令和shell解释器调用文件;

二.什么是shell脚本

当命令或者程序语句写在文件中,我们执行文件,读取其中的代码,这个程序文件就称之为shell脚本。在shell脚本里定义多条Linux命令以及循环控制语句,然后将这些Linux命令一次性执行完毕,执行脚本文件的方式称之为,非交互式方式。

- windows中存在*.bat批处理脚本

- Linux中常用*.sh脚本文件

 shellj脚本规则:

在Linux系统中,shelI脚本或者称之为(bash shell程序〉通常都是vim编辑,由Linux命令、bash shell指令、逻辑控制语句和注释信息组成。

 三.Shebang

# !/bin/sh
echo "我是一个shell脚本"                    

计算机程序中,shebang指的是出现在文本文件的第一行前两个字符#!在Unix系统中,程序会分析 shebang后面的内容,作为解释器的指令,例如

·以#!/bin/sh开头的文件,程序在执行的时候会调用/bin/sh ,也就是bash解释器

·以# !/usr/bin/python开头的文件,代表指定python解释器去执行

·以# ! /usr/bin/env 解释器名称,是一种在不同平台上都能正确找到解释器的办法

inux的which命令用于查找给定的命令在哪个目录下执行。它会在系统的 PATH 环境变量所设置的目录中查找给定命令的可执行文件,并返回第一个找到的路径。如果找不到该命令,则会返回错误信息。

注意事项:
1.如果脚本未指定shebang ,脚本执行的时候,默认用当前shell去解释脚本,即 $SHELL
2.如果 shebang 指定了可执行的解释器,如/bin/bash或/usr/bin/python ,脚本在执行时,文件名会作为参数传递给解释器
3.如果#!指定的解释程序没有可执行权限,则会报错bad interpreter: Permission denied”。
4.如果#!指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的SHELL去执行这个脚本。
5.如果#!指定的解释程序不存在,那么会报错"bad interpreter: No such file or directory”。
6.#之后的解释程序,需要写其绝对路径(如:#!/bin/bash),它是不会自动到$PATH中寻找解释器的。

7.如果你使用"bash test.sh"这样的命令来执行脚本,那么#!这一行将会被忽略掉,解释器当然是用命令行中显式指定的bash。
 

 四.执行shell脚本的方式

1.bash hello.shsh hello.sh ,文件本身没权限执行,没x权限,则使用的方法,或脚本未指定shebang ,重点推荐的方式,属于/bin/sh hello.sh的简化形式。

代码实例:

[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh

echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh hello.sh
我是一个shell脚本
[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh

echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# bash hello.sh
我是一个shell脚本

2.使用绝对/相对路径执行脚本,需要文件含有x权限

代码实例:

[root@iZ2zeg0eyon02gbtl3sldpZ c]# chmod +x hello.sh
[root@iZ2zeg0eyon02gbtl3sldpZ c]# ./hello.sh
我是一个shell脚本

3.source hello.sh或者. hello.sh ,代表执行的含义,source等于点.。需要注意的是,此种方法是在当前shell中执行,其余都是创建子shell执行。

代码实例: 

[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh

echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# source hello.sh
我是一个shell脚本

4.少见的用法,sh < script.sh,重定向

代码实例: 

[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh < hello.sh
我是一个shell脚本
[root@iZ2zeg0eyon02gbtl3sldpZ c]# bash < hello.sh
我是一个shell脚本

五.bash特性

. bash是一个命令处理器,运行在文本窗口中,并能执行用户直接输入的命令. bash还能从文件中读取linxu命令,称之为脚本

. bash支持通配符、管道、命令替换、条件判断等逻辑控制语句

 history  查看历史命令
echo $HISTSIZE 查看历史命令数目
vim ~/.bash_history 打开存储文件
echo $HISTFILE 显示历史文件路径
history -c 清空历史命令(文件不改变)
history -r 恢复历史命令
!历史id 快速执行历史命令
!! 执行上次历史命令

bash特性汇总
1.文件路径tab键补全·命令补全
2.快捷键ctrl + a,e,u,k,h

3·通配符
4·命令历史

5·命令别名

6·命令行展开
 

 六.shell变量 

变量定义和取值方式:

[root@iZ2zeg0eyon02gbtl3sldpZ c]# name="我是变量"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo ${name}
我是变量
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name
我是变量

${name},表示完整取值,大括号可以省略

 shell变量作用域

shell脚本_第4张图片

 本地变量中,子shell和父亲shell完全隔离,切换shell变量会丢失

pstree是一种命令行工具,用于显示进程树。它可以显示当前系统中所有进程的层次结构,以及它们之间的父子关系。通过使用pstree命令,用户可以更好地了解系统中正在运行的进程,并且可以更轻松地诊断和解决问题。

shell脚本_第5张图片

单引号变量:不识别特殊语法

双引号变量:能识别特殊语法

代码实例: 

#单引号
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name="tom"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name1='$name'
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name1
$name


#双引号
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name2="$name"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name2
tom

1.每次调用bash/sh解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量,之前定义的变量还在。通过pstree命令检查进程树
2.调用source是在当前shell环境加载脚本,因此保留变量(.sh文件中定义的变量,保存到当前shell中)

sh 进入子shell
bash 进入子shell
exit 退出bash

环境变量:也叫全局变量,针对当前shell以及任意子进程,环境变量也分为自定义,内置两种环境变量。

局部变量:针对shell脚本或shell函数中定义

位置参数变量:ls -l /opt    -l和opt都是位置参数变量

$?:判断上一条命令是否成功

0:成功

1-255:失败

代码实例:

[root@iZ2zeg0eyon02gbtl3sldpZ ~]# cd ..
[root@iZ2zeg0eyon02gbtl3sldpZ /]# echo $?
0
[root@iZ2zeg0eyon02gbtl3sldpZ /]# 

在linux中反引号,中的命令执行结果会被保留下来

代码实例: 

[root@iZ2zeg0eyon02gbtl3sldpZ c]# name=`ls`
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name
hello.sh hellow.sh

七.环境变量设置

环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境、保证shell命令的正确执行。shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。
环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量配置文件

·用户个人配置文件 ~/.bash_profile 、 ~/.bashrc远程登录用户特有文件
·全局配置文件/etc/profile 、/etc/bashrc ,且系统建议最好创建在/etc/profile.d/ ,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户

环境变量:能找出linux服务器上,各种变量 

useradd  name 增加用户
passwd  name 给用户设置密码
su - name 切换用户
pwd 查看绝对路径

在~/.bash_profile 、 ~/.bashrc加入export name="cao"后,重新登录该用户,就可以得到环境变量name,不论在哪一个shell中,都可以访问。但是其它用户访问不到。

 在/etc/profile 、/etc/bashrc中加入name="cao"后,重新登录该用户,既可以得到全局配置的环境变量,在所有用户都可以访问,重名时比用户优先级低。

set 输出所有变量,包括全局和局部(当前shell)
env   只显示全局变量
declare 输出所有变量
export 显示和设置环境变量值
unset 变量名 删除变量或函数
readonly 只读变量,shell结束后失效

set | wc -l    显示set命令有多少行

set | grep ^name   查找以name开头的环境变量

bash多命令用“;”隔开

shell脚本_第6张图片

 八.shell变量

取出变量值:

·单引号,所见即所得,强引用

·双引夸,输出引号里所有内容,识别特殊符号,弱引用

·无引号,连续的符号可以不加引号,有空格则有歧义,最好使用双引号。反引号,引用命令执行结果,等于$()用法

$0:获取shell脚本文件名,以及脚本路径
$n:获取shell脚本的第n个参数, n在1~9之间,如$1 ,$2,$9 ,大于9则需要写,${10},参数         空格隔开
$# :获取执行的shel脚本后面的参数总个数4
$*:获取shel1脚本所有参数,不加引号等同于$@作用,加上引号"$*"作用是接收所有参              数为单个字符串,"$1$2..

$@ :不加引号,效果同上,加引号,是接收所有参数为独立字符串,如"$1"“$2”“$3”...,空格         保留
 

ls -l
#-l 参数

text.sh

sh text.sh 参数1 参数2 参数3

$*和$@的区别你了解吗?
$*和$@都表示传递给函数或脚本的所有参数
当$*和$@不被双引号”"包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号"“包含时,就会有区别了:
"$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做─份数据。“$@"仍然将每个参数都看作一份数据,彼此之间是独立的。
比如传递了5个参数,那么对于""$*"来说,这5个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于$@"来说,这5个参数是相互独立的,它们是5 份数据。
如果使用echo直接输出$*"和"$@"”做对比,是看不出区别的﹔但如果使用for 循环来逐个输出数据,立即就能看出区别来。

 shell for循环 

代码: 

#!/bin/bash

echo "print each param from \"\$*\""

for i in "$*"
do
        echo "$i"
done

echo "print each param from \"\$@\""      
#\转译
for i in "$@"
do
        echo "$i"
done

#do代表循环体开始,done代表循环体结束

结果:

[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh diffent.sh a b c d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d

特殊状态变量:

$?:   上一次命令执行状态返回值,0正确,非0失败

$$:  当前shel1脚本的进程号(PID)
$!:  上一次后台进程的PID
$_:  取得上一次命令,最后一个参数
查找方式:  man bash
搜索:  Special Parameters
 

 nohup xxxx & 1> /dev/null     程序后台运行,日志写入黑洞文件

九. shell子串

bash一些基础的内置命令

echo  

-n 不换行输出

-e 解析字符串中的特殊符号(\n 换行 \r 回车  \t 制表符  \b退格)

eval 执行多个命令

eval ls;cd ..

exec

不创建子进程,执行后续命令,且执行完后自动exit

expr数值计算

expr length "${name}"    统计变量长度

 shell的花式玩法

${变量}          返回变量值
${#变量}          返回变量长度,字符长度
${变量:start}     返回变量start数值之后的字符
${变量:start : length}   提取startt之后的length限制的字符
${变量#word}   从变量开头删除最短匹配的word子串   //本值不变
${变量##word}   从变量开头,删除最长匹配的word
${变量%word}   从变量结尾删除最短的word
${变量%%word}   从变量结尾开始删除最长匹配的word
${变量/pattern/string}   用string代替第一个匹配的pattern

${变量//pattern/string}  用string代替所有的pattern

echo ${name} | wc -l    显示行数

echo ${name} | wc -L   显示最长的一行的个数

echo "${name}" | awk '{print length($0)}'   //个数

shell编程,尽量使用linux内置的命令,内置的操作,和内置的函数,效率最高c语言开发,效率最高,尽可能的减少管道符的操作

 字符串截取

#从开头删除匹配最短

##开头删除匹配最长

%从结尾删除匹配最短

%%从结尾删除匹配最长

指定字符内容截取
a*c匹配开头为a,中间任意个字符,结尾为c的字符串a*C匹配开头为a,中间任意个字符,结尾为c的字符串
 

 特殊shell扩展变量

如果parameter变量值为空,返回word字符串,赋值给result变量
result=${parameter : -word}


如果para变量为空,则word替代变量值,且返回其值

result=${parameter :=word}


如果para变量为空,word当作stderr输出,否则输出变量值用于设置变量为空导致错误时,返回的错误信息
${parameter : ?word}


如果para变量为空,什么都不做,否则word返回

${parameter : +word}
 

 ps -ef --forest    //显示进程和shell详细信息

shell的进程理念,需要使用()小括号

source和.执行脚本,是在当前的shell中执行

 Linux默认有关的shell变量

BASH_SUBSHELL

0代表在当前shell执行的,否则是开辟子shell执行的,1代表子shell,2代表孙shell

():开启子shell运行

linux内置命令,外置命令

内置命令:在系统启动时就加载入内存,常驻内存,执行效率高,但是占用资源,cd

外置命令:用户需要从硬盘中读取程序文件,再读入内存加载/bin  /usr/bin   /sbin  usr/sbin

外置命令特点:效率低一些,并且一定会开启子进程执行

内置命令特点:不会产生子进程,和shell是一体的,不需要单独读取某个文件,系统启动后,就执行在内存中了。

内置命令查看:compgen -b

shell数值计算

shell的一些基础命令,只支持整数的运算,小数的计算需要如bc这样的命令才支持

· ·:反引号,执行命令后,放到字符串和$()相同

who命令:查看用户登录时间和用户名

${var}:取出变量结果的

$():在括号中执行命令,且拿到命令的执行结果

shell脚本_第7张图片

shell脚本_第8张图片

 (()):进行数值运算

shell脚本_第9张图片

 shell脚本_第10张图片

 shell脚本_第11张图片

 shell脚本_第12张图片

 exit :返回一个状态码

 shell脚本_第13张图片

 shell脚本_第14张图片

 奇奇怪怪的使用算法

Let命令执行:

let命令的执行,效果等同于双小括号,但是双小括号更加高效,左移右移要加转移符

expr命令执行:

expr:简单计算器,必须是以传入参数的形式

shell脚本_第15张图片

 :冒号,计算字符串的字符数量(字节),支持通配符

shell脚本_第16张图片

 bc计算器:

bc交互式的操作,支持小数的计算

bc结合管道符:

shell脚本_第17张图片

案例:

 计算1-1000的和

 tr是替换

 seq是生成数列

awk计算:

支持小数计算,

 $[表达式]:

shell脚本_第18张图片

 十.条件测试

1.test条件测试

test命令评估一个表达式,它的结果是真,还是假,如果条件为真,那么命令执行状态码结果就为0否则就是不为0,通过$?取值;

shell脚本_第19张图片

 shell脚本_第20张图片

 shell脚本_第21张图片

 shell脚本_第22张图片

 shell脚本_第23张图片

shutdown语法: 

shell脚本_第24张图片

# 语法 shutdown -h 小时:分钟
# 示例,晚上十点半自动关机
shutdown -h 22:30

2.[  ]条件测试

text和[ ]的作用是一样的,注意中括号前后都要有空格,条件测试中使用变量,必须添加双引号。

 双中括号:[[   ]]

支持正则,并且&&和||,<,>可写在内部,[ ]不支持正则通配符,&&和||不能写在里面。

字符串测试:

shell脚本_第25张图片

注意:!也是一个操作符,取反的意思 

 字符串变量的比较,一定要加入双引号。操作符两边一定要有空格

数值比较测试:

shell脚本_第26张图片

 []和test:

 在中括号中,使用数学比较符号,请添加转义符号。!=不用加

shell脚本_第27张图片

 变量的话要加双引号

shell脚本_第28张图片

 text和[ ]支持,-eq此类写法,也支持>,<等。

双中括号:

对单中括号的补充,支持正则表达式,且不需要转义符号

 [[   ]]支持,-eq此类写法,也支持>,<等 

逻辑判断符号:

&&    -a      与运算,两边都为真,才为真

||        -o      或运算,两边有一个为真,就为真

 中括号逻辑运算比较:

shell脚本_第29张图片

 单个中括号内不能使用&&和||

 双中括号可以使用

 cat还能这样使用。

shell脚本_第30张图片

 十一.if语句开发

shell脚本_第31张图片

 if    <条件表达>

then

        代码

elif <条件表达>

then

        代码
...

fi

十二.shell函数 

shell脚本_第32张图片

 当使用function关键字时,可以省略括号

shell脚本_第33张图片

 当函数的定义和执行分开不在一个文件时,

手动:

shell脚本_第34张图片

 shell脚本_第35张图片

 脚本:

shell脚本_第36张图片

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