Linux运维:Shell编程

目录

0x01编写shell脚本:

文件创建:

最简单的shell脚本:

执行方式有两种:

#变量

赋值:

变量的访问:

单引号和双引号和php一样

字符串拼接:

获取字符串的长度:

截取字符串:

#数组:

数组定义

#输出重定向

#输入重定向

#shell 流程控制:

if

#运算符

#布尔运算符

#逻辑运算符

#文件测试运算:

#基本运算符:

#for

#while

#case

#Shell函数

函数的定义:

函数调用

#文件引入

#输出带颜色的字体:


命令行组合运用:

  • 使用分号:
    • 命令1;命令2;命令3
    • 依次执行,只有先后,没有逻辑关系

例如:

x=123;y=456;
mkdir /newdir;cd /newdir
//新建目录,再进入此目录

典型应用:

开启某个服务,并将此服务设为开机自启动

service vsftpd restart;chkconfig vsftpd on
  • 逻辑与分割
    • 命令1&&命令2&&命令3
    • 逻辑关系为 而且 ,期待所有命令都能执行成功,一旦前面的命令失败,后面的命令将不再执行
    • 典型应用:源代码编译安装软件包时,编译安装过程
make && make install

 

  • 逻辑或分割
    • 命令1 || 命令2|| 命令3
    • 逻辑关系为 ‘或者’,任何一条命令成功就可以了,只有在前面的命令的执行失败的时候,后面的命令才会执行
    • 典型应用:针对前置命令失败的情况,设置补充任务
id mickey || useradd mickey
若无此用户,则创建此用户

0x01编写shell脚本:

文件创建:

vi 1.sh 创建一个名为1.sh的文件,shell脚本一般以.sh结尾,但是不以.sh结尾但是有执行权限也能正常运行。

最简单的shell脚本:

#!  /bin/bash 

复习:

bin是一个软连接,其实是/usr/bin,存放的是所有的可执行命令

bash是shell脚本的解释器。

#!告诉系统用/bin/bash来解释

# 注释

#! /bin/bash

echo "hello world"

保存为hello.sh

执行方式有两种:

执行方式一:

/bin/base hello.sh

执行方式二:

chmod +x hello.sh

./hello.sh

#变量

赋值:

变量名=变量值

username='liudehua'

注意,等号两边不能有空格,变量名前不用加$符号

变量的访问:

echo $username 或者 echo ${username}

单引号和双引号和php一样

单引号原样输出,双引号会解析变量

字符串拼接:

#! /bin/bash

username="liudehua"
age=23
echo $username$age

不需要加.或者+,直接拼接在一起就可以了。

获取字符串的长度:

#! /bin/bash

username="liudehua"
echo ${#username}

截取字符串:

#! /bin/bash

username="liudehua"
echo ${username:5:7}
#!/bin/bash 所有脚本默认的起始行,说明下面的代码都是使用/bin/bash 这个shell文件来解释的。

echo -n "IP:"  //-n参数表示,显示完字符串之后光标不换行。紧跟在字符串后面

read ip  //定义一个变量ip,并从终端读取数据,相当于 var ip加上scanf

echo "your ip is:"$ip

#数组:

只支持一维数组,不支持多维数组

数组定义

变量名=(value1 value2 ...) 空格分隔

1 #! /bin/bash
  2 username=('liudehua' 'zhangxueyou')
  3 echo ${username[0]}
  1 #! /bin/bash
  2 username[2]="guofucheng"
  3 echo ${username[2]}

访问数组中的所有元素:

  1 #! /bin/bash
  2 username=('liudehua' 'zhangxueyou' 'langchaowei')
  3 echo ${username[*]}
  4 echo ${username[@]}

计算数组的长度:

echo ${#username[*]}

传值:

脚本名 参数一 参数二 参数三

接收参数 $1 $2 $3

  1 #! /bin/bash
  2 echo $0
  3 echo $1

访问第0个参数(脚本名)和第1个参数

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

$$ 脚本运行的当前进程id号

$? 显示最后命令的退出状态。0表示没有错误,其他任何值表示有错误

#输出重定向

命令 > 输出重定向

命令 >> 输出追加重定向

例如:

echo 'hello' > test.txt

本来echo命令是要在终端输出的,重定向符号>将输出重定向到了test.txt中(创建文件+覆盖写)

如果想将test.txt清空可以:

echo ''>test.txt

追加写:

echo 'hello world' >> test.txt

#输入重定向

命令

例如:

wc -l 可以统计行数

wc -l < test.txt

相当于 cat test.txt | wc -l

标准输出文件(stdout):stdout的文件描述符为1,Unix程序默认向stdout输出数据

标准错误文件 (stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息

例如:

但是如果这样写:

ech '111' 2>test.txt

就会将错误信息输入到test.txt中

/dev/null 是一个黑洞

echo 'xxx' > /dev/null 2>&1

2>&1 表示不论前面的命令错误与否,都往黑洞里面输入。

#shell 流程控制:

if

if [ condition ]

then

...

fi
if [ condition ]
then
    ...
else
    ...
fi

特别注意 condition和括号之间一定要有空格。

if [ condition ]
then
    ...
elif [ condition ]
then
    ...
fi

例如:

#! /bin/bash
score=$1

if [ $score -lt 60 ]
then
	echo '不及格'
elif [ $score -gt 60 -a $score -lt 80 ]
then
	echo '良好'
else
	echo '优秀滴'
fi

#运算符

== !=  -eq -ne -gt -lt -ge(大于等于) -le(小于等于)

#布尔运算符

!(非) -o(或) -a(与)

#逻辑运算符

|| &&

如果要用这种写法,条件必须用两个中括号

[[  condition1 && condition2 ]]

投机取巧地写法:

#! /bin/bash

[[ $1 -eq 888 ]] &&  echo '恭喜发财!'

因为当第一个条件为真时, && 符要返回真假,必须执行第二条件。所以当参数1位888时,第二句话执行了。

当参数1不为888时,第一个条件为false,短路运算,不用判断第二个条件。

#文件测试运算:

-d 是否为目录 或者可以直接理解为判断一个目录是否存在

-f 是否为文件 判断一个文件是否存在

-e 文件或目录是否存在。

#! /bin/bash

if [ -f $1 ]
then 
	echo '存在该file:'$1
else
	echo '不存在该file'
fi
	

小脚本:判断一个文件夹是否存在,如果不存在,则创建它

#! /bin/bash
[[ -d $1 ]] || mkdir $1

判断一个文件是否存在,如果不存在,则创建它:

#! /bin/bash

[ -f $1 ] || touch $1

#基本运算符:

shell脚本中没有+ - * / 这些运算符

但是expr 命令却有算数运算的功能

Linux运维:Shell编程_第1张图片

#! /bin/bash

a=1
b=2
echo `expr $a + $b`
echo `expr $a - $b`
echo `expr $a \* $b`
echo `expr $a \/ $b`

注意:用反引号,且变量和运算符之间需要有空格,乘法和除法需要转义

可以用$()来替换反引号,这样shell脚本的通用性更好。

小脚本:

#! /bin/bash
ip=`ifconfig | egrep 'broadcast' | awk '{print $2}'`
echo $ip

#for

for 变量 in ...

do

    ....

done

例如:

#! /bin/bash

for i in 1 2 3 4 5
do 
	echo $i
done

#! /bin/bash

for i in {a..z} 
do 
	echo $i
done

例2:

#! /bin/bash
username=('liudehua' 'liming' 'zhangxueyou')
for i in {0..2} 
do 
	echo ${username[i]}
done

例3:

Linux运维:Shell编程_第2张图片

例4:批量创建文件夹

Linux运维:Shell编程_第3张图片

例5:列出某文件夹下所有的目录:

Linux运维:Shell编程_第4张图片

删除当前目录下的所有目录:

Linux运维:Shell编程_第5张图片

#while

while condition

do

  ...

done

例1:

#! /bin/bash

while true
do 
	echo 'hello world'
done

例2:

#! /bin/bash

while read name 
do 
	echo 'hello world '$name
done

Linux运维:Shell编程_第6张图片

read 会等待用户输入,当用户输入并回车,就会将输入的内容传给read,read将其赋值给变量name

#case

case 值 in

      情况1)

      ;;

      情况2)

       ;;

       *)

       ;;

esac

*表示default

例1:启动脚本大体框架

#! /bin/bash

action=$1
case $action in
	start)
		echo 'start'
	;;
	stop)
		echo 'stop'
	;;
	restart)
		echo 'restart'
	;;
	*)
		echo 'start|stop|restart'
	;;
esac

#Shell函数

函数的定义:

法一:

function 函数名(){

}

法二:

函数名(){

}

函数调用

函数调用要在函数定义之后,才可以调用,调用只用函数名即可。

#! /bin/bash

function getUserName(){
	echo 'this is function getUserName'
}
getUserName

函数的返回值:

#! /bin/bash

function getUserName(){
	return 255
}
getUserName
echo $? #用来接收函数的返回值

注意返回值只能是数字,并且正数不能超过256,否则会发生溢出。

#! /bin/bash

function getUserName(){
	echo $(expr $1 + $2)
}
getUserName 2 3

如果参数超过10,不能用$10来接受,必须用$[10] $[11] …这种

#文件引入

方法一:

. 文件的绝对路径

方法二:

source 文件的绝对路径

例如:

include.sh

#! /bin/bash

function mk_dir(){
	dir=$1
	[ -e $dir ] || mkdir $dir
}

main.sh

#! /bin/bash
. /Users/mac/shellscript/include.sh

mk_dir /Users/mac/shellscript/Test

#输出带颜色的字体:

Linux运维:Shell编程_第7张图片

建议将其封装成函数:

# /bin/bash
function printColor(){
	echo -e "\033[$1m $2 \033[0m"
}
printColor 31 "hello world"
printColor 32 "hello world"
for i in {31..37}
do
	printColor $i "hello Shell"
done

Linux运维:Shell编程_第8张图片

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