在一些复杂的Linux维护工作中,大量重复的输入和交互操作不但费时费力,容易出错.这时候就需要用到脚本。

  编写脚本的好处:  批量的处理,自动化的完成维护,减轻管理员的负担。

  linux的shell脚本是一种特殊的应用程序,常见的shell解释器有很多种,使用不同的shell时期内部指令:cat /etc/shells

[root@xiaolyu ~]# cat /etc/shells

/bin/bash是大多数linux中默认的shell解释器。之后的所有脚本的编写都是bash脚本。

一、编写第一个Shell脚本

将平时的操作命令顺序的放入到文件中赋予执行权限,一次的执行。

我们来编写第一个脚本first.sh

linux不以后缀名区分文件,为了方便记忆这里我就以.sh为结尾

[root@xiaolyu ~]# vim first.sh

注释:

#!/bin/bash 主要是为了声明,我所写的均为bash语言(我是用的是bash解释器)

第二行为注释行,注释信息不生效

当写一个比较大的脚本时,如果没有一个好的注释,那么也就也就没有人都能够看懂其中的意思了

再往后即执行的命令。

执行过程:

[root@xiaolyu ~]# ll first.sh                            #查看是否具有执行权限
-rw-r--r--. 1 root root 62 Aug 30 22:58 first.sh   
[root@xiaolyu ~]# chmod +x first.sh              #给脚本添加执行权限
[root@xiaolyu ~]# ll first.sh                           #查看脚本是否具有执行权限
-rwxr-xr-x. 1 root root 62 Aug 30 22:58 first.sh
[root@xiaolyu ~]# ./first.sh                           #执行脚本

执行的结果:

E-执行脚本的不同方式

第一种使用绝对路径执行

第二种使用相对路径执行,如./的方式

第三种使用 sh命令来执行  格式  sh 脚本名   不需要执行权限    -x参数

第四种使用 . (空格)脚本名称的方式执行  不需要执行权限  .  first.sh

第五种使用 source 脚本名称        不需要执行权限(主要用于生效配置文件)

#建议使用后三种,在生产环境中不要轻易的给文件可执行权限;

二、 脚本中的变量。

变量的定义是:可以存放一个可变的值的空间

可以通过不同的环境进行改变就是一个可以变的值.

默认情况下: 在Linux中可以将每个shell看成不同的执行环境,所以相同的一个变量名称在不同的变量执行环境中的变量值是不同的.

常见的shell变量分类:

自定义变量、环境变量、位置变量、预定义变量

变量的输出

一般使用echo 输出变量   echo $变量名

1.自定义变量

举例1:来进行定义一个变量名字为Linux值为7.2 

[root@xiaolyu ~]# Linux=7.2      #为变量Linux赋值

[root@xiaolyu ~]# echo $Linux    #输出变量Linux的值

7.2

[root@xiaolyu ~]# linux=6.5      #为变量linux赋值

[root@xiaolyu ~]# echo $linux      #输出变量linux的值

6.5

可以直接在命令行定义一个变量并赋予值,通过echo进行输出变量 $是引用变量的特殊字符(必须使用$符号)

注意:echo和调用的变量之间必须要有空格。

          大小写的变量的值是不同的。

举例2:当需要一起调用两组变量时

[root@xiaolyu ~]# echo $Linux $linux

7.2 6.5

直接使用echo 后面跟$调用的变量 如果有多个则空格隔开

举例3:当变量名和后面的字符容易混淆的时候应该使用{}将变量名括起来

[root@xiaolyu ~]# echo system${Linux}

system7.2

[root@xiaolyu ~]# echo ${Linux}system

7.2system

其他的特殊操作

双引号( "  ")

当=号右边赋值出现空格的时候,需要使用双引号将其扩起

[root@xiaolyu ~]# webserver="nginx 1.1"
[root@xiaolyu ~]# echo $webserver
nginx 1.1

#在双引号的范围内还可以引用其他的变量,从而能够将现有的变量赋值给新的变量

[root@xiaolyu ~]# Linux=7.2
[root@xiaolyu ~]# system="RHEL$Linux"
[root@xiaolyu ~]# echo $system
RHEL7.2
[root@xiaolyu ~]#

单引号( ' ')

当要赋值的内容包括"$"、"\"等,具有其他含义的特殊字符时,应使用单引号将其括起来;

在单引号范围内将无法引用其他的值,任何字符均作为普通字符看待,但赋值 的内容包含单引号时需要使用\’符号进行转义以免冲突.

[root@xiaolyu ~]# kernel=3.10$Linux
[root@xiaolyu ~]# echo $kernel   
3.107.2                   #这个结果不是我们想要的,我们想要的结果是$3.10$Linux
[root@xiaolyu ~]# kernel='3.10$Linux'
[root@xiaolyu ~]# echo $kernel    
3.10$Linux
[root@xiaolyu ~]#

反撇号( ` `)

  位置在键盘esc的下边的按键。

反撇号主要使用于命令替换,允许将某个命令的屏幕输出结果赋值给变量。

举例: 在命令行中查找程序的详细的信息

[root@xiaolyu ~]# rpm -qf `which pwd`
coreutils-8.22-15.el7.x86_64
[root@xiaolyu ~]# rpm -qf $(which pwd)
coreutils-8.22-15.el7.x86_64
[root@xiaolyu ~]# which pwd
/usr/bin/pwd
[root@xiaolyu ~]# rpm -qf /usr/bin/pwd
coreutils-8.22-15.el7.x86_64
[root@xiaolyu ~]#

#反撇号括起来的范围内必须是可执行的命令。否则将会出现错误

需要注意的是使用反撇号难以在一条命令中实现嵌套命令的操作,这是可以$()来替代反撇号

如果使用反撇号嵌套会出错的!!

[root@xiaolyu ~]# rpm -q `rpm -qf `which pwd``

rpm: no arguments given for query

which-2.20-7.el7.x86_64

package pwd is not installed

建议使用$()的形式嵌套

[root@xiaolyu ~]# rpm -q $(rpm -qf $(which pwd))

coreutils-8.22-15.el7.x86_64

 

read命令

除了上面的赋值之外还可以使用read命令进行赋值,read命令用来提示用户输入信息,从而实现简单的交互式过程(其实我们所输入的命令就是一种交互式的过程)

执行时需要从标准输入设备键盘读取一行,并以空格为分隔符

[root@xiaolyu ~]# read kernel Linux    #同时定义两个变量操作   
4.7.2 7.2       -->手动输入的变量值
[root@xiaolyu ~]# echo $kernel
4.7.2
[root@xiaolyu ~]# echo $Linux
7.2

为了交互式更加的形象,提高易用性,加上 -p选项来设置提示信息

[root@xiaolyu ~]# read -p "input your password:" passwd    #-p 指定提示信息
input your password:123456              #123456就是$passwd的值
[root@xiaolyu ~]# echo $passwd        #输出变量  
123456

---------------------------------------------------------------------------------------------------------------

以上的操作只是在当前的bash环境下生效,到了其他控制台或者是其他shell就不能生效了 

我们进入当前shell的子shell验证:

[root@xiaolyu ~]# echo $Linux   #在当前的shell环境输出变量
7.2
[root@xiaolyu ~]# bash            #切换子shell
[root@xiaolyu ~]# echo $Linux    #在子shell环境输出变量

#没有输出东西。

[root@xiaolyu ~]#

经过验证,进入子shell之后在局部定义的变量就不会生效了。只能说明一点,当前bash内不存在输出的变量

set  用来显示本地变量
env 用来显示环境变量
export 用来显示和设置环境变量

区别:

set  显示当前shell的变量,包括当前用户的变量
env 显示当前用户的变量
export 显示当前导出成用户变量的shell变量

将一个局部变量改变为全局变量:

export 局部变量1  局部变量2 ...

[root@xiaolyu ~]# echo $Linux
7.2
[root@xiaolyu ~]# echo $kernel
4.7.2
[root@xiaolyu ~]# bash
[root@xiaolyu ~]# echo $Linux

[root@xiaolyu ~]# echo $kernel

[root@xiaolyu ~]# exit
exit
[root@xiaolyu ~]# export Linux kernel
[root@xiaolyu ~]# bash
[root@xiaolyu ~]# echo $Linux
7.2
[root@xiaolyu ~]# echo $kernel
4.7.2
[root@xiaolyu ~]#

也可以先定义一个全局变量并赋值:

export 全局变量1=变量的值  全局变量2=变量的值 ...

[root@xiaolyu ~]# export website=www.baidu.com   #设置全局变量

[root@xiaolyu ~]# echo $website      #在当前环境输出变量
www.baidu.com     
[root@xiaolyu ~]# bash                  #进入子shell      
[root@xiaolyu ~]# echo $website     #输出子shell中的变量
www.baidu.com
[root@xiaolyu ~]#

需要注意的是变量的名是严格区分大小写的

数值变量的运算:

shell脚本的数值运算多用于脚本程序的过程控制(如循环次数,使用量比较等)

在shell环境中,只能进行比较简单的整数运算

运算符与变量之间必须有一个空各位,整数的运算主要是通过内部命令expr 命令进行运算。

格式  变量1 运算符 变量2

其中 变量1 、变量2 ……对应的需要计算的数值变量(需要$符号调用)常用的几种运算符如下所示

加法运算:+

减法运算: -

乘法运算: \*

除法运算: /

求模(取余)运算: %

若要将运算结果赋值给其他变量可以这么做

2. 环境变量

  环境变量是指系统本身运行需要由linux系统提前创建好的一类变量。

主要用于用户的工作环境,包括(用户的宿主目录,命令的查找路径,用户的当前目录,登录的终端等)环境变量的值由操作系统本身自己维护,随着用户的状态改变而改变

env调取当前环境变量

环境变量的配置文件在/etc/profile(全局)

用户宿主目录/home/berners/.bash_profile(局部) #我非root用户是berners. 

$PWD 

pwd命令就是调用了这个变量才能进行输出

$PATH

定义命令的默认搜索路径,我们讲的mysql可执行程序优化的时候我们是直接将程序路径写到了这个变量中才可以再任何目录下进行输入.

$USER

就是当前登陆系统的用户

$SHELL

显示当前所用的shell

$HOME

显示当前用户的家目录。一般非root用户的家目录都在/home目录下,有个以当前用户命名的目录。root用户家目录在/root下。

由/etc/passwd的倒数第二个域决定

3.位置变量

  当执行命令行操作时,命令行中第一个字段表示命令字或程序名,其余的字符串参数按照从左到右的顺序依次给位置变量赋值   位置变量也称为位置参数,使用$1 $2 $3 …$9表示

以ls  -lh  /boot/为例

其中除了 ls 之外的都是位置参数

-lh是一个位置参数使用$1表示 依次往后排,(空格分隔)

$0属于预定义变量而不是位置变量

在下面的例子中我通过编写一个加法运算的脚本来说明位置变量

vim positionVariable.sh

 4.预定义变量

  系统预先定义的变量简称为预定义变量,是由系统预先定义的一组变量,这些变量通常用于保存与系统 / 命令等有关的信息。预定义变量由系统自动生成 / 维护,用户无需修改其值。预定义变量一般有下面几个。

$#:命令行中位置变量的个数(程序执行了几个位置参数)

$*:所有位置变量的内容(具体的内容 比如/boot就是一个具体的内容)

$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错

判断是否出现错误正常为0异常错误为非0 取值在1-127之间

$0:当前执行的进程/程序名(就是当前执行的命令或程序的名字)

下面我通过一个例子来解释

vim backup.sh  编译一个使用打包命令打包多个目录或文件

执行脚本查看效果: .   ./backup.sh

三、文件测试

  文件测试是指根据给定的路径名称,判断是文件还是目录,判断是具有读写执行的权限,判断文件目录是否存在。

文件测试一般有两种方法;

一种是使用test命令进行判断 另外一种就是 [   ]命令。

test条件表达式

[条件表达式]

常用的选项如下:

-d:测试是否为目录(Directory)或目录是否存在

-e:测试目录或文件是否存在(Exist)

-f:测试是否为文件(File)或文件是否存在

-r:测试当前用户是否有权限读取(Read)

-w:测试当前用户是否有权限写入(Write)

-x:测试当前用户是否有权限执行(eXcute)

举例:一般我们挂在光盘的时候习惯将光盘挂载在/media/cdrom这个目录,但是rhel系统默认不存在这个目录,这时我们可以先判断一下这个目录是否存在

-d:测试是否为目录(Directory)或目录是否存在

1. 通过[条件表达式]来判断。

2. 通过test表达式来判断。

使用[ ]的这种方式进行判断,这种也是最常用的一种格式注意两边最少需要一个空格位

使用echo 输出一下$? 可以看见返回值为非0通过判断的返回结果我们可以断定cdrom这个目录是不存。

当我将cdrom这个目录创建完成之后,再进行判断时,条件成立返回值为0,这个表达式是成立的。

通过查看变量$?的方式比较不直观,我们可以使用逻辑测试中的&来进行判断

在表达式的后面执行 双&, 如果前面的表达式成立则输出YES否则什么都不输出。

-e:测试目录或文件是否存在(Exist)

-f:测试是否为文件(File)或文件是否存在

-r:测试当前用户是否有权限读取(Read)

shell脚本一的更多相关文章

  1. 第一个shell脚本

    打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好. #!/bin/bash echo "Hello World !" &quo ...

  2. 使用C#给Linux写Shell脚本

    在这个逼格决定人格,鄙视链盛行的年头,尤其是咱们IT界,请问您今天鄙视与被鄙视的次数分别是多少?如果手中没有一点压箱的本事,那就只有看的份了.今天我们也要提升下自己的格调,学习些脑洞大开的东西,学完之 ...

  3. shell脚本规划化模板

    shell脚本规划化模板 Linux运维过程中,shell脚本是不可缺少的工具,但是每个运维人员编程的习惯都不一样,很多时候就是实现某个功能,写出来的脚本都是烂七八糟的.脚本必须规范化,应该从以后几个 ...

  4. Shell脚本编程30分钟入门

    Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...

  5. Linux Shell脚本逻辑操作符简介

    在写程序时,会用到条件判断,测试条件是否成立.很多时候,判断条件是多个的,这个时候需要用到逻辑操作符.shell脚本中常用的有哪些逻辑操作符呢? 1.逻辑与: -a 格式: conditon1 -a ...

  6. Linux shell脚本编程(三)

    Linux shell脚本编程 流程控制: 循环语句:for,while,until while循环: while CONDITION; do 循环体 done 进入条件:当CONDITION为“真” ...

  7. Linux shell脚本编程(二)

    Linux shell脚本编程(二) 练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 ...

  8. Linux shell脚本编程(一)

    Linux shell脚本编程: 守护进程,服务进程:启动?开机时自动启动: 交互式进程:shell应用程序 广义:GUI,CLI GUI: CLI: 词法分析:命令,选项,参数 内建命令: 外部命令 ...

  9. 详解Linux交互式shell脚本中创建对话框实例教程_linux服务器

    本教程我们通过实现来讲讲Linux交互式shell脚本中创建各种各样对话框,对话框在Linux中可以友好的提示操作者,感兴趣的朋友可以参考学习一下. 当你在终端环境下安装新的软件时,你可以经常看到信息 ...

  10. shell 脚本之循环使用 for while 详解

    任何一种编程语言中循环是比不可少的,当然 shell 脚本也少不了循环语句,包括 for 语句. while 语句.文中主要以实际用例来说明 for while 都有哪些常见的使用方法和技巧. 一.f ...

随机推荐

  1. JavaScript老梗之this对象

    Js中的this关键词貌似是初学者必经的坑 都不例外 我们经常听到其他人说 this对象谁调用指向谁 的确这是最容易理解的 但是我们可以更加深入的去探索下 加深印象以便更加灵活的适用它 这里不得不提下 ...

  2. css3 tween

    /* * Tween.js * t: current time(当前时间) * b: beginning value(初始值) * c: change in value(变化量) * d: durat ...

  3. RUDP之三 —— Virtual Connection over UDP

    原文链接 原文:http://gafferongames.com/networking-for-game-programmers/virtual-connection-over-udp/ Introd ...

  4. LightOJ1171 Knights in Chessboard (II)(二分图最大点独立集)

    题目 Source http://www.lightoj.com/volume_showproblem.php?problem=1171 Description Given an m x n ches ...

  5. 水坑式攻击-APT攻击常见手段

    所谓“水坑攻击”,是指黑客通过分析被攻击者的网络活动规律,寻找被攻击者经常访问的网站的弱点,先攻下该网站并植入攻击代码,等待被攻击者来访时实施攻击. 水坑攻击属于APT攻击的一种,与钓鱼攻击相比,黑客 ...

  6. sql server 权限体系

    --给sql server添加一个新用户[账号,密码,数据库名] execute  sp_addlogin 'baishi', '123','db'; execute  sp_addlogin 'wx ...

  7. jsp页面取得一对多中的set集合的size

    jsp中使用${list.size }会编译成list.getSize()方法,并不能获取list的长度,因为程序回去找List对象中的getSize()方法,所以只能想别的办法, 一种方法是在后台程 ...

  8. PHP编程效率的20个要点

    用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则 不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数” 用 单引号代替双引 ...

  9. c++ 能够记录状态的vector

    这个想法来自于数组链表,在数组链表中,数组的每一个元素对应一个指针,这个指针是下一个元素的index.用整数表示指针. 这是这个vector的源码: #include <iostream> ...

  10. Android四大组件之actiivity

    1.Acitivity Activity是Android一个非常重要的用户接口(四大组件之一),是可见的,主要是用户和应用程序之间进行交互的接口.在每个Activity中都可以放很多控件,所以也可以把 ...