在一些复杂的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. POJ 2431Expedition

    Description A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Bein ...

  2. requirejs 多页面,多js 打包代码,requirejs多对多打包【收藏】

    这段代码来自 http://stackoverflow.com/questions/20583812/grunt-requirejs-optimizer-for-a-multi-app-project ...

  3. Codeforces Round #107 (Div. 2)

    D题 并查集+组合 #include <iostream> #include <cstdio> #include <cstring> using namespace ...

  4. Spring基础学习笔记-Bean的基础知识

    一. Bean的定义,初始化,使用和销毁 二.ref指定依赖的三种模式 三.Bean的五种自动装配模式(autowire) 四.Bean依赖检查的4种模式:配合atuowire使用,dependenc ...

  5. jquery实现限制textarea输入字数

    ie中可用onpropertychange监听改变事件 火狐和谷歌可用oninput监听改变事件 综合: //使系统中class='text-length'的输入框只能输入200字符(主要用于text ...

  6. 20145205 《Java程序设计》第6周学习总结

    教材学习内容总结 -若要将数据从来源中取出,可以使用输入串流:若要将数据写入目的地,可以使用输出串流.在java中,输入串流代表对象为java.in.InputStream的实例:输出串流代表对象为j ...

  7. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  8. 如何给你的LinuxVPS装个远程桌面

    有些人抱怨Linux的系统没有桌面,用着实在是不方便.今天整理一下网上的教程,给VPS装个桌面环境.Centos系统+X Window+GNOME Desktop. 此程序会安装无数乱七八糟的东西到你 ...

  9. Sublime P4语法高亮设置

    Github插件链接:p4-syntax-highlighter 首先安装Package Control. 进入Package界面,我的目录: /Users/wasdns/Library/Applic ...

  10. python - socket - client端指定ip和端口

    问题描述: 在设备中有3个NI, ip分别为192.168.1.5/6/7.其中本端192.168.1.6同对端192.168.1.10建立了一个tunnel. 我希望测试tunnel连通性, 对端起 ...