shell脚本编程

作用:通过命令行解析的方式,自动执行设定好的程序或命令代码。(若将脚本挂到定时任务中,就会自动在非工作时间里自动触发执行程序)

Shell脚本文件以“.sh”结尾

规范的Shell脚本第一行会指出由哪个程序(解释器)来执行脚本中的内容。在linux bash编程中一般为:#!/bin/bash (表示该脚本运用/bin/bash命令进行解析)

Shell的输出用echo命令;

Python的输出用print命令

执行脚本的方式:

方法一:/bin/sh是bash的软链接,也就是说我么既可以用sh执行也可以用bash执行脚本

# sh yunjisuan.sh

# bash yunjisuan.sh

方法二:以绝对路径的方式执行脚本(前提:将该脚本添加x执行权限 )

# chmod +x yunjisuan.sh

# /root/benet/yunjisuan.sh

方法三:以source脚本路径的方式执行脚本(等同于“.脚本路径” )只在当前环境生效

# source yunjisuan.sh

# . yunjisuan.sh

方法四:以相对路径的方式执行脚本(前提:将该脚本添加x执行权限 )

# ./yunjisuan.sh

写脚本

(1)vim编辑yunjisuan.sh

(2)查看yunjisuan.sh脚本

(3)执行yunjisuan.sh脚本

脚本中书写的命令必须是非交互式的命令!!!

虽然脚本可以自动化执行,但脚本不会判断命令是否执行成功,因此需要进行逻辑判断

方法一:

test命令

判断该字符串表示为文件还是目录

-d 测试是否为目录

-e 测试目录或文件是否存在

-f 测试是否为文件

-l 测试是否为链接文件

-r 测试当前用户是否可读

-w 测试当前用户是否可写

-x 测试当前用户是否可执行

-s 测试文件大小非0时为真(若为非空文件,则为真)

-u 测试是否具有SUID属性

-g 测试是否具有SGID属性

-k 测试是否具有sticky bit 粘滞位属性

-z 测试字符串是否为空(zero)

file1 -nt file2测试第一个文件是否比第二个文件新(new then)

file1 -ot file2 测试第一个文件是否比第二个文件旧(old then)

file1 -ef file2 测试第一个文件是否与第二个文件为同一个文件(link之类的文件)

# test -d 目标路径

# echo $?判断是否是目录,若显示0表示真(是目录),若显示非0则假(不是目录)

# test -f 目标路径

判断目标是不是文件

# echo $?

$?返回值参考

0 表示运行成功

2 权限拒绝

1~125 表示运行失败,脚本命令,系统命令错误或参数传递错误;

126 找到该命令,但无法执行

127 未找到要运行的命令

128 命令被系统强制结束

方法二:

使用“[]”,表示开启判断条件(“[]”两边须有空格)

# xx=”welcome”

# [ $xx == welcome] && echo “0” || echo “1”

0

“[]”应用于整数 (格式:整数1 操作符 整数2)

-gt(great than)表示大于

-lt(less than)表示小于

-eq(equal)表示等于

-ne (not equal)表示不等于

-ge 表示大于等于

-le表示小于等于

&& 逻辑与,表示前一指令为真,执行后一指令,否则不执行

|| 逻辑或,表示前一指令为假,执行后一指令,否则不执行

# xx=”44”

# if [ -f "$file1" ];then echo 1;else echo 0;fi

相当于# [ -f "file1" ] && echo 1 ||echo 0

# [ $xx -eq 34 ] && echo “0” || echo “1”

1

字符串测试

[ -z “字符串” ]  字符串内容为空

[ -n “字符串” ]  字符串内容不为空

${#变量名}   求变量的字符串位数,判断字符串是否为空

# xx=”123411”

# echo ${#xx}

6

# xx=””

# echo ${#xx}

0

脚本的交互式输出模式

方法一:

执行脚本过程中,存在需要用户输入内容的情况,通过read命令进行交互式输入

添加注释给用户:

输入格式:read -p “文本提示” 变量名

输0出格式:echo $变量名

创建用户名和密码

#!/bin/bash

User="yunjisuan"

Passwd="123456"

read -p "请输入用户名" user

read -p "请输入密码" passwd

[ $User -eq $user ] && echo "YOU ARE RIGHT" || echo “YOU ARE WRONG”

[ $Passwd -eq $user ] && echo "YOU ARE RIGHT" || echo "YOU ARE WRONG"

逻辑测试

“[]”中,-a(&&) 表示并且;

-o (||)表示或者

!逻辑否

方法二:通过参数传递的方式进行交互式输入

/etc/init.d/ 服务启动脚本

服务启动脚本/etc/init.d/后面写的内容就是参数,通过这个参数进行交互式输入

$# 表示脚本要处理的的参数个数

$? 表示命令或脚本执行状态码

$* 表示横向罗列脚本要处理的所有参数(把所有参数视为整体)

$@ 表示横向罗列脚本要处理的所有参数(把所有参数视为单个参数的组合)

$0 表示脚本文件的绝对路径或相对路径(脚本文件的执行路径)

$1 第一个参数

$n 第n个参数

脚本中反引号“``”、“$()”的应用

变量的算数运算

变量的数值运算多用于脚本程序的过程控制,只能进行简单的整数运算,不支持小数运算,整数值得运算主要通过内部命令expr进行。

# x=11

# y=22

# expr $x \* $y

格式: expr 变量1 运算符 变量2...

++ --   增加及减少,可前置也可放在结尾

! ~  一元运算的正负号,非,逻辑与位的取反

\*   乘法

/   除法

%  取余

**  幂运算

+ 加法

-  减法

<; <=;>; >= 比较符号

== 1+= 相等,不相等

<<  向左移动

>>  向右移动

>>>  填0右移

& 位的与AND

^  位的异或

|  位的或

&&  位的AND

||   位的OR

?:  条件表达式

=; += ;-= ;*=等 赋值运算符

(())用法(常用于简单的整数运算)

“(())”在命令行执行时不需要$符号,但是输出需要$符号

“(())”里所有字符之间有无或多个空格没有任何影响

# b=$((1+2**3-4%3))

# echo $b

8

# echo $((1+2**3-4%3))

8

a++,a--,++a,--a区别

变量a在前,表达式的值为a,然后a自增或自减,变量a在符号后,表达式值自增或自减,然后a值自增或自减。

# a=8

# echo $a

8(a赋值为8)

# echo $((a+=1)) #相当于a=a+1

9(a赋值为a+1=9)

# echo $((a++)) #a在前,先输出a的值,在加1

9(a赋值为上一值a为9)

# echo $a

10(a赋值上一值的9++,9+1为10)

# echo $((a--))

10(a取上一值a为10)

# echo $a

9(a取上一值10--,10-1为9)

# echo $((++a))

10(先+1,在取上一值9,1+9=10)

# echo $a

10(取上一值10)

# echo $((--a))

9(先-1,取上一值10,10-1=9)

# echo $a

9(取上一值9)

Shell脚本中不支持“i++”表达,可以用C语言的((i++))在shell中表示

或者“let h++”

 

 

If条件语句

格式(fi 表示结束)

(一)单分支条件判断语句

(1)

if    条件1

then

动作1

else

动作2

fi

(2)(用;分隔)

if 条件1;then

动作1

else

动作2

fi

在vim中编辑yunjisuan.sh脚本

#!/bin/bash

read -p "请输入一个数字:" num

if [ $num == 60 ];then

echo "猜对了"

fi

# sh yunjisuan.sh

请输入一个数字:60

猜对了

在vim中编辑yunjisuan.sh脚本

#!/bin/bash

read -p "请输入一个数字:" num

if [ $num == 60 ];then

echo "猜对了"

else

echo "猜错了"

fi

# sh yunjisuan.sh

请输入一个数字:45

猜错了

(二)多分支条件判断语句(elif就是else if)

if 条件1;then

动作1

elif 条件2;then

动作2

else

动作3

fi

查看当前文件的绝对目录

# dirname 目标文件的绝对路径

查看当前文件的基本文件名称

# basename 目标文件的绝对路径

自定义搭建本地yum仓库脚本

(1)移除光盘,再挂载

(2)判断光盘挂载

(3)挂载本地yum仓库脚本

(4)判断一级目录、二级目录是否存在

(5)配置文件手动生成,避免之前被修改过(重定向或echo -e)

#!/bin/bash

umount /dev/sr0&>/dev/null

[ -d /media/cdrom ]|| mkdir -p /media/cdrom(还可以用test和if的方法)

mount /dev/sr0 /media/cdrom &>/dev/null

if [ $? -ne 0 ];then

echo "请插入光盘"

exit

fi

[ -d /etc/yum.repos.d ] || mkdir -p /etc/yum.repos.d

cd /etc/yum.repos.d

mv * /tmp/

echo -e “[local]\nname=local\nbaseurl=file:///media/cdrom/\ngpgcheck=0\nenabled=1”>/etc/

yum.repos.d/localyum.repo

(或)

cat > /etc/yum.repos.d/localyum.repo << FOF

[local]

name=local

baseurl=file:///media/cdrom

gpgcheck=0

enabled=1

F0F

yum -y clean all &>/dev/null

yum makecache &>/dev/null

[ $? -eq 0 ] && echo "yum仓库搭建完毕" || echo "缓存建立失败!"

配置文件手动生成

用脚本手动生成配置文件,一般用重定向

输入重定向通过FOF标识(任意定义,但成对出现),将FOF之间的内容输入重定向到cat,cat再输出重定向给/etc/yum.repos.d/yum/repo文件

while循环语句

格式:

while 条件

do

循环体(指令)

done

休息命令:sleep 1 休息1秒,usleep 1000000 休息1秒,单位微妙

从1到100求和

#!/bin/bash

i=1

sum=0

while [ $i -lt 100 ]

do

((sum=sum+i))

((i++))

done

echo $sum

守护进程

#!/bin/bash

while true

do

uptime >> /var/log/uptime.log

sleep 2

done

倒计时

#!/bin/bash

i=10

while [ $i -gt 0 ]

do

echo $i

((i--))

done

无限循环

(1)

#!/bin/bash

read -p "输入:" i

while [ $i -gt 0 ]

do

echo $i

let i++

done

(2)

#!/bin/bash

read -p "输入:" i

while :

do

echo $i

let i++

done

强行中止

# exit

防止脚本执行中断的方法

1)sh while01.sh & #放在后台执行
2)screen 分离 ctrl+a+d 查看screen -ls进入screen -r num
3)nohup while01.sh &

 

for循环语句

格式:

for 变量名 in 变量取值列表

do

循环体(指令)

done

示例:循环

for ((i=0;i<10:i++))

do

echo $i

done

打印列表元素

for的三种输出方式

(1)

#!/bin/bash

for i in 1 2 3 4 5

do

echo $i

done

(2)

#!/bin/bash

for i in {1..5}

do

echo $i

done

(3)

#!/bin/bash

for i in `seq 5`

do

echo $i

done

#!/bin/bash

h=0

for i in {1..10}

do

echo $h

let h++

done

开机启动项优化

#!/bin/bash

for i in `chkconfig | grep "3:on" | awk '{print $1}'`

do

chkconfig $i off

done

if [ -e sysstat ]

then echo "sysstat exit"

else mkdir -p /media/cdrom

mount /dev/sr0 /media/cdrom

if [ $? -ne 0 ];then

echo "FAILED"

exit

else yum -y install sysstat

if [ $? -ne 0 ];then

echo "install error"

exit

else echo "install successed"

fi

fi

fi

for h in sshd network crond rsyslog sysstat

do

chkconfig $h on

done

[ $? == 0 ]&& echo "successed" || echo "failed"

在/yunjisuan目录批量创建文件

#!/bin/bash

Path=/yunjisuan

[ -d "$Path" ] || mkdir -p $Path

for i in `seq 10`

do

touch $Path/yunjisuan_$i.html

done

批量改名

#!/bin/bash

Path=/yunjisuan

[ -d "$Path" ] || mkdir -p $Path

for file in `ls $Path`

do

mv $Path/$file "$Path/"`echo $file | sed -r 's#yunjisuan(.*).html#linux\1.HTML#g'`

done

批量创建用户并设置密码

#!/bin/bash

User=yunjisuan

Path=/tmp

for user in ${User}{01..10}

do

useradd $user > /dev/null 2>&1

if [ $user -ne 0 ];then

echo "$user created failed"

echo "scripts begin to rollback"

for i in ${User}{01..10}

do

userder -r $i >/dev/null 2>&1

[ $? -eq 0 ] || exit 1

done

echo >$Path/usr_passwd

exit 1

else

passWD=`echo $RANDOM | md5sum | cut -c1-8` (表示取一大串随机数,从这串随机数前截取1-8位)

[ -d $Path ] || mkdir $Path

echo $passWD | passwd --stdin $user

echo "$user:$passWD">> $Path/user_passwd

fi

done

exit 0 表示正常运行程序并退出程序

exit 1 或exit -1 表示非正常运行导致退出程序

echo -n 不换行

获取当前目录下的目录名做为变量列表打印输出

#!/bin/bash

Path=`pwd`

echo $Path

for filename in `ls`

do

[ -d ${Path}/${filename} ] && echo $filename

done

九九乘法表

#!/bin/bash

for ((i=1;i<10;i++))

do

for ((j=1;j<=i;j++))

do

echo -n "$j * $j =$((i*j))"

echo -n " "

done

echo " "

done

显示出1-100的偶数

#!/bin/bash

for i in {1..100}

do

[ $(($i%2)) -eq 0 ] && echo $i

done

显示出1000-2000的质数

#!/bin/bash

for i in {1000..2000}

do

[ $(factor $i | awk '{print NF}') -le 2 ] && echo $i

done

factor命令:分解因数

Case语句

用途:菜单;启动脚本

case语句适合变量的值少,且为固定的数字或字符串集合。 系统服务启动脚本传参的判断多用case语句

格式:

case "字符串变量" in

值1)

指令1

;;

值2)

指令2

;;

*)

指令

esac

注意:case语句相当于一个if的多分支结构语句

值1的选项

apple)

echo -e "@RED_COLOR apple $RES"

;;

也可以这样写,输入2种格式找同一个选项

apple|APPLE)

echo -e "$RED_COLOR apple $RES"

;;

服务脚本框架

#!/bin/bash

. /etc/init.d/functions

case $1 in

start)

action "服务开始启动"   /bin/true

;;

stop)

action "服务准备停止"   /bin/false

;;

restart)

action "服务准备停止"   /bin/true

action "服务来时启动"   /bin/true

;;

*)

echo "请输入正确参数"

;;

esac

在当前脚本引用函数库(绝对路径)

Function对应的是action “ ” 路径

/bin/true 表示一个标志

设置脚本配置启动级别

(1)为脚本设置启动级别

将脚本复制到/etc/init.d/下,vim编辑/etc/init.d/cash.sh脚本

# chkconfig: 35 90 10

(2)在chkconfig中添加脚本

# chkconfig --add case.sh

# chkconfig --list case.sh

(3)设置关闭cash.sh

# chkconfig case.sh off

Shell函数

不论什么编程语言,基本只有三种编程的方法(指如何去编写代码的方法论)

1、面向过程

2、面向对象

3、函数式编程

在shell语言中,只能支持面向过程这种编程方法。

在shell中,function表示函数(function、return可以不写)

格式:

function 函数名(){

命令序列

[return x]

}

函数名

函数体只有被调用时才会启动,若要重复启动该函数,只需将函数名重复n遍

获取随机数的几种方法

(1)通过系统环境变量$RANDOM

# echo $RANDOM

6178

# echo $RANDOM

30890

# echo $((RANDOM%9)) #输出0~9之间随机数

2

# echo $((RANDOM%9))

# echo $((RANDOM%9))$((RANDOM%9)) #输出00~99 随机数

64

# echo $RANDOM|md5sum #随机数长短不一,可以用md5sum命令统一格式化

599e328a94329684ce5c92b850d32f26 -

(2)通过openssl产生

# openssl rand -base64 8

aND8WMRM6vQ=

# openssl rand -base64 8

RsRdRq/9vi4=

# openssl rand -base64 8|md5sum

b1108cafbc2291392e41d2c914360138 -

# openssl rand -base64 10

1frkA2kIJODxqQ==

(3)通过时间获得随机数(date命令详解见下页文档)

# echo $(date +%N)

361599138

# echo $(date +%t%N)

950526316

(4)Urandom

# head /dev/urandom | cksum

621330951 2535

# head /dev/urandom | cksum

404398617 2470

(5)UUID

# cat /proc/sys/kernel/random/uuid

8a6c5bbe-2d42-44ac-9ef1-3e7683a613e3

# cat /proc/sys/kernel/random/uuid

c828c209-5b5f-4bc7-917c-678ed4215988

# uuidgen

961dc354-81b2-4564-9b85-6095ed4bc7b5

循环控制语句break、continue、exit、return

作用:用于循环结构中控制循环语句

break n:n表示跳出循环的层数,如果省略n表示跳出整个循环(只跳出所在位置的循环)

continue n:n表示退出到第n层继续循环,如果省略n表示跳过本次循环,忽略本次循环剩余代码,进入循环的下一次循环exit n:退出当前shell程序,n为返回值,n也可以省略,在下一个shell里通过$?接收这个n值

return n:用在函数里,做为函数的返回值,用于判断函数执行是否正确。和exit一样,如果函数里有循环,也会直接退出循环,退出函数

break n:n表示跳出循环的层数,如果省略n表示跳出整个循环

#!/bin/bash

for ((i=0;i<=5;i++))

do

[ $i -eq 3 ] && break

echo $i

done

echo "ok"

break只跳出所在位置的一个整个循环循环

continue n:n表示退出到第n层继续循环,如果省略n表示跳过本次循环,忽略本次循环剩余代码,进入循环的下一次循环

#!/bin/bash

for ((i=0;i<=5;i++))

do

[ $i -eq 3 ] && continue

echo $i

done

echo "ok"

exit n:退出当前shell程序,n为返回值,n也可以省略,在下一个shell里通过$?接收这个n值

#!/bin/bash

for ((i=0;i<=5;i++))

do

[ $i -eq 3 ] && exit 2

echo $i

done

echo "ok"

return n:用在函数里,做为函数的返回值,用于判断函数执行是否正确。和exit一样,如果函数里有循环,也会直接退出循环,退出函数

#!/bin/bash

function xxx() {

for ((i=0;i<=5;i++))

do

[ $i -eq 3 ] && return 7

echo $i

done

echo "ok"

}

xxx

echo $?

shell脚本的调试

(1)使用dos2unix处理脚本

从windows编辑的脚本到Linux下需要使用这个命令
dos2unix windows.sh

(2)使用echo命令调试

在变量读取或修改的前后假如echo $变量,也可在后面使用exit退出脚本,这样可以不用注释后边代码

(3)利用bash的参数调试

sh [-nvx]
-n:不会执行该脚本,仅查询脚本语法是否有问题,并给出错误提示。可用于生产服务器那些只能执行一次不可逆的脚本。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示。(一般不用)
-x:将执行的脚本内容及输出显示到屏幕上,常用

1)要记得首先用dos2unix对脚本格式化
2)直接执行脚本根据报错来调试,有时报错不准确。
3)sh -x调试整个脚本,显示执行过程。
4)set -x和set +x调试部分脚本(在脚本中设置)
5)echo输出变量及相关内容,然后紧跟着exit退出,不执行后面程序的方式,一步步跟踪脚本,对于逻辑错误比较好用。

ping -c 1 ip   只ping一次

#!/bin/bash

for ip in 192.168.214.{1..254}

do

ping -c 1 $ip &> /dev/null

if [$? -eq 0 ];then

echo "$ip正常状态"

fi

done

Linux系统——shell脚本的更多相关文章

  1. Linux系统Shell脚本编程

    1. shell脚本概念:C语言编写的.命令解释器.编程语言. 是用户使用linux的桥梁. shell脚本语言非常擅长处理文本类型的数据. 2. shell脚本作用:自动化管理.监控管理.日志数据处 ...

  2. Linux系统——shell脚本应用示例

    传入一个网段地址,自动找出本网段内存活的IP地址.2,将存活的IP地址当作密码来创建Linux用户,用户名格式为:你的名字_数字 3,有几个存活IP地址,就自动创建几个用户   4,最后将创建的用户名 ...

  3. linux服务器批量部署应用系统shell脚本(Tomcat/jetty)

    linux服务器批量部署应用系统shell脚本: 1.请更换代码内的服务器地址(Tomcat或jetty服务器) serverRoot=/home/undoner/java_tool/apache-t ...

  4. 从windows到linux的shell脚本编码和格式问题

    从windows到linux的shell脚本编码和格式问题   从windows到Linux的shell脚本编码和格式问题 1.异常问题 :set ff=unix 启动脚本在启动时报错比如执行sh s ...

  5. Linux简单Shell脚本监控MySQL、Apache Web和磁盘空间

    Linux简单Shell脚本监控MySQL.Apache Web和磁盘空间 1. 目的或任务 当MySQL数据库.Apache Web服务器停止运行时,重新启动运行,并发送邮件通知: 当服务器磁盘的空 ...

  6. Linux:从windows到linux的shell脚本编码和格式

    从windows到linux的shell脚本编码和格式问题 异常问题 :set ff=unix 启动脚本在启动时报错比如执行sh start.sh,时会报Command not found等等的错误, ...

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

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

  8. 使用C#给Linux写Shell脚本(下篇)

    在上篇的<使用C#给Linux写Shell脚本>结尾中,我们留下了一个关于C#如何调用BashShell的问题.在文章发布之后,我留意到有读者留言推荐使用“Pash”(一款类PowerSh ...

  9. Linux/Unix shell 脚本中调用SQL,RMAN脚本

    Linux/Unix shell脚本中调用或执行SQL,RMAN 等为自动化作业以及多次反复执行提供了极大的便利,因此通过Linux/Unix shell来完成Oracle的相关工作,也是DBA必不可 ...

随机推荐

  1. 【BZOJ】1629: [Usaco2007 Demo]Cow Acrobats(贪心+排序)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1629 这题我想了很久都没想出来啊... 其实任意两头相邻的牛交换顺序对其它牛是没有影响的.. 那么我 ...

  2. 修改CFileDialog的标题

    CFileDialog   f(TRUE);   f.m_ofn.lpstrTitle   =   "我的标题";   f.DoModal(); 设置标题! CFileDialog ...

  3. python定义函数时的默认返回值

    python定义函数时,一般都会有指定返回值,如果没有显式指定返回值,那么python就会默认返回值为None, 即隐式返回语句: return None 执行如下代码 def now(): prin ...

  4. webstorm配置内存参数,解决卡顿

    找到WebStorm.exe.vmoptions这个文件,路径如下webstorm安装主目录>bin>WebStorm.exe.vmoptions更改为第二行:-Xms526m第三行:-X ...

  5. 使用Fastjson生成Json字符串少字段属性(数据丢失)

    最后是控制台打印生成的结果如下:FastJson生成字符串是:{"id":"2","name":"节点1"," ...

  6. js 常用 DOM 元素宽高

    提示:document.documentElement 和 document.getElementsByTagName('html')[0] 是一样的: 1.视口大小(不包括滚动条,视口字面理解当然是 ...

  7. JRebel插件安装配置与破解激活(多方案)详细教程

    JRebel 介绍 IDEA上原生是不支持热部署的,一般更新了 Java 文件后要手动重启 Tomcat 服务器,才能生效,浪费不少生命啊.目前对于idea热部署最好的解决方案就是安装JRebel插件 ...

  8. 如何给MFC的菜单项添加快捷键

    我们一起分享,如何给MFC的菜单项添加快捷键.[程序在VC6.0编译环境下编译通过.(VS2010的编译环境大同小异)] 1.程序演示环境 1.1新建一个[对话框(Dialog)]的程序.然后,New ...

  9. Code Forces 644B Processing Queries

    B. Processing Queries time limit per test5 seconds memory limit per test256 megabytes inputstandard ...

  10. Code Forces 20A BerOS file system

    A. BerOS file system time limit per test 2 seconds memory limit per test 64 megabytes input standard ...