shell脚本(一)基础知识,shell脚本基础知识


shell

一、简介

1.作用:与内核进行交互

2.语言类型:解释性语言,给内核解释用

3.脚本中第一行内容:

#!/bin/bash                       这是shell脚本的第一行内容,表示用bash这个解释器去解释下面的内容

#!/bin/sh                            这也可以是shell脚本的第一行内容,表示用sh这个解释器去解释下面的内容

#!/usr/bin/env bash        env表示使用相对路径,自动找bash解释器所在位置。可以解决不同版本的系统bash不一定在/usr/bin/bash这个路径下的问题

4.为了使脚本方便其他人阅读,一般会在开头加上作者、创建时间、邮箱、版本、描述等内容,可以使用以下设置快捷键的方法在脚本中增加这些信息

vim /etc/vimrc

map <F4> ms:call WESTOS()<cr>'s
function WESTOS()
        call append(0,"######################################")
        call append(1,"# Author     :vaon                   #")
        call append(2,"# Create Date:".strftime("%Y-%m-%d")."             #")
        call append(3,"# Email      :vaoner@163.com         #")
        call append(4,"# Version    :1.0                    #")
        call append(5,"# Description:                       #")
        call append(6,"######################################")
        call append(7,"                          ")
        call append(8,"#!/usr/bin/env bash")
endfunction

#map表示影射-->F4时调用(呼叫)WESTOS函数

#0代表第一行,1第二行...

#黄色部分strftime是一个系统自带的函数,表示显示当前时间   .是分隔符,表示这个函数与其他两段内容互不影响

#下面是设定函数的方法:

    Fucton 函数名()

    内容

    Endfunction

然后创建一个脚本使用F4键就会在脚本最前面自动加上以下内容:


二、基础知识

1.变量的声明${a}b

设定a=1

echo $a 会出现1

echo $ab就不会出现1b,因为系统把ab当成一个变量了。

可以echo ${a}b,会出现1b,把作为一个已定义的1


2.转义、弱引用、强引用

1)\表示转义

echo ###不会出现结果,但是加上 echo \#\#\#就会出现###

2)“”表示弱引用,也可以输出###

3)‘’表示强引用,可以输出###


4)强引用和弱引用的区别

例如 $  !  \  ``  这些强引用会把他们当作普通内容打印到屏幕上

而弱引用会把他们当成系统变量,执行变量里的内容


还例如在弱引用中`hostname`表示执行hostname命令

而在强引用中表示输出`hostname`这个内容


3.diff、patch

1)diff

【1】.


[root@server mnt]# cat file1
abcd
1234
[root@server mnt]# cat file2
abcd
[root@server mnt]# diff file1 file2
2d1
< 1234
#表示file1删除1234就和file2一样了

【2】.比较目录

diff -r 目录一 目录二

2)打补丁

建立hello文件:

vim hello

westos

建立hello.new文件:

vim hello.new

westos

456

安装自动更新工具包:

yum install patch -y

hello.newhello文件比较,多出的内容做成hello.path补丁包:

diff -u hello hello.new > hello.path

path补丁包去更新hello文件:

patch hello hello.path

查看hello文件,已经被更新成和hello.new一样了:

cat hello

westos

456

注:如果patch后面加上-b参数表示在更新的同时备份原文件为hello.orig

4.grep

首先建立一个文件:

[root@shell mnt]# vim /mnt/passwd

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
hello
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
test:ROOT:test
test:test:root
test:root:test
test:roottest:test

1)查找包含root子段的行

[root@shell mnt]# grep root /mnt/passwd
root:x:0:0:root:/root:/bin/bash
test:test:root
test:root:test
test:roottest:test

2)查找包含root子段的行,不区分大小写

[root@shell mnt]# grep -i root /mnt/passwd
root:x:0:0:root:/root:/bin/bash
test:ROOT:test
test:test:root
test:root:test
test:roottest:test

3)只要root开头的

[root@shell mnt]# grep -i ^root /mnt/passwd
root:x:0:0:root:/root:/bin/bash

4)只要root结尾的

[root@shell mnt]# grep -i root$ /mnt/passwd
test:test:root

5)以root开头和结尾的行都不要。-E表示后面两个条件同时筛选,-v表示不要筛选出的行

[root@shell mnt]# grep -i root /mnt/passwd|grep -i -E "^root|root$" -v
test:ROOT:test
test:root:test
test:roottest:test

6)表示只要包含只有root子段的行,root前后只要有字母都不要,如roottest这行就不要

[root@shell mnt]# grep -i "\<root\>" /mnt/passwd|grep -i -E "^root|root$" -v
test:ROOT:test
test:root:test
问题:

查看所有能登陆系统的用户

解答:

[root@shell mnt]# grep "\<bash\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
可见只有root能登陆
7)grep -n 表示显示搜索出的字符串所在行号

[root@shell mnt]# grep -n hello /mnt/passwd
4:hello

8)gep -n2 表示显示搜索出的行以及它的上面2行和下面2行,并且显示各自在文件中的行号

注:如果-n和2之间有空格则表示除了上面显示的内容还会在每行开头显示出文件名

[root@shell mnt]# grep -n2 hello /mnt/passwd
2-bin:x:1:1:bin:/bin:/sbin/nologin
3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:hello
5-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
6-games:x:12:100:games:/usr/games:/sbin/nologin

9)grep -B2 表示显示搜索出的行以及这行的上两行内容
[root@shell mnt]# grep -B2 hello /mnt/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
hello
10)grep -A2 表示下两行

[root@shell mnt]# grep -A2 hello /mnt/passwd
hello
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
11)表示搜索/mnt目录下包含root字符的文件
[root@shell mnt]# grep -r hello /mnt/
/mnt/passwd:hello

5.cut

用法:cut -d 分隔符 -f 第几列 文件

-c指定字符

-d指定分隔符

-f指定第几列

cut -d : -f 2 /mnt/psswd     #以:为分隔符,显示passwd文件第二列

cut -d : -f 2,7 /mnt/psswd   #,表示第二和第七列,如果是-表示2到第7

cut -c 3 /mnt/passwd      #显示第三列的字符,不使用分隔符

cut -c 1,3 /mnt/passwd     #显示一和三列的字符,不使用分隔符

题目:

显示eth0网卡的ip

解答:

[root@shell mnt]# ifconfig eth0|grep "\<inet\>"|cut -d " " -f 10
172.25.254.1

6.awk

-v表示给变量赋予内容:

[root@shell mnt]# name=hello
[root@shell mnt]# awk -F : -v name=$name 'BEGIN {print name} {print $1}END {print "end"}' /mnt/passwd
hello
root
bin
daemon
hello
mail
games
test
test
test
test
end
7.sed

-i      #这个参数表示写入文件

sed ‘s/old/new/g’ passwd       #passwd文件中的所有old字符替换为new

sed ‘s/old/new/g’ passwd       #passwd文件中的所有old字符替换为new,并写入passwd文件

sed ‘2,5s/old/new/g’ passwd      #替换25

sed ‘/adm/,/gdm/s/old/new/g’ passwd   #adm字符一直到gdm字符的内容中将old替换为new

sed -e ‘s/old/new/g’ -e ‘s/old1/new1/g’ passwd   #将old替换为new同时将old1替换为new1

sed 5d passwd    #删除第5行

sed 5p passwd    #复制第5行

sed -n 5p passwd    #只显示第5行

-p    #表示直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作

vim file

s/sbin/westos/g
s/nologin/linux/g

sed -f file passwd


题目:

将httpd服务端口改为8080

解答:

############################
# Author     :vaon                           #
# Create Date:2017-12-16             #
# Email      :vaoner@163.com       #
############################

#!/bin/bash
PORT=`grep ^Listen /etc/httpd/conf/httpd.conf`
sed "s/$PORT/Listen $1/g" -i /etc/httpd/conf/httpd.conf
systemctl restart httpd

8.设置变量

1)临时设置(环境级)

在当前环境生效,当前环境关闭,变量失效

先看一个例子:

[root@shell mnt]# a=1
[root@shell mnt]# echo $a
1
[root@shell mnt]# vim test.sh
#!/bin/bash
echo $a
[root@shell mnt]# sh test.sh 


[root@shell mnt]#

#由于a=1是在当前使用的shell里面赋的值,当进入脚本执行时,脚本使用的是子shell,这个子shell中并没有设定a=1,所以结果为空

[root@shell mnt]# export a=1
[root@shell mnt]# sh test.sh
1

#可以临时设定a=1给所有shell,一旦登出就会失去这个临时设定

2)永久设置

【1】.系统级

对所有用户生效

[root@shell mnt]# vim /etc/profile

export a=1

[root@shell mnt]# source /etc/profile

[root@shell mnt]# logout
Connection to 172.25.254.1 closed.
[root@station Desktop]# ssh root@172.25.254.1
root@172.25.254.1's password:
Last login: Sat Dec 16 09:12:16 2017 from 172.25.254.10
[root@shell ~]# cd /mnt/
[root@shell mnt]# sh test.sh
1

#这样所有shell都可以使用a=1这个变量,登出系统再登陆依然存在a=1

【2】.用户级

只针对配置过的用户生效,其他用户无法使用

vim /root/.bash_profile

export a=1

source /root/.bash_profile

现在a=1只对root用户生效

9.将脚本加到系统命令中去
[root@shell mnt]# vim /etc/profile

export PATH=$PATH:/mnt

注:这里同样存在系统级或用户级的设置,在这里使用的是系统级设置。如果只允许root可以设置/root/.bash_profile文件

[root@shell mnt]# source /etc/profile

[root@shell mnt]# chmod +x test.sh 

然后退出/mnt目录,直接把test.sh脚本当成系统命令去执行,发现也可以:

[root@shell mnt]# cd
[root@shell ~]# test.sh
1
10.命令别名

1)使用别名

[root@shell ~]# vim /etc/bashrc
alias kan='cat'             #表示执行'kan'的时候相当于执行'cat'命令

[root@shell ~]# source /etc/bashrc

查看别名列表:

[root@shell ~]# alias

         ...

alias kan='cat'

         ...

执行kan这个单词就相当于执行cat命令

[root@shell ~]# kan /mnt/test.sh
######################################
# Author     :vaon                   #
# Create Date:2017-12-16             #
# Email      :vaoner@163.com         #
######################################
                          
#!/bin/bash
echo $a
2)删除别名
删除/etc/bashrc中的alias kan='cat'

然后在删除kan信息:

unalias kan

现在查看alias列表,里面已经没有kan的信息了

11.*和@区别

vim test.sh

#!/bin/bash
echo '$1 Is' $1
echo '$2 Is' $2
echo '$3 Is' $3
echo '$* Is' $*
echo '$# Is' $#
echo '$@ Is' $@
[root@shell mnt]# sh test.sh 1 2 3
$1 Is 1                                                   #显示第1个字符
$2 Is 2                                                   #显示第1个字符
$3 Is 3                                                   #显示第1个字符
$* Is 1 2 3                                             #显示所有字符
$# Is 3                                                   #显示最后一个字符
$@ Is 1 2 3                                           #显示所有字符
*和@都表示所有内容,但实际上一个是所有内容方到“”里面。而@是每个数据都加引号

$*   “1 2 3”

&@  “1” “2” “3”

12.shell脚本中函数的定义

READ()

{

        echo hello word

}

13.变量对比

1)test

2)[ ]

[root@shell mnt]# a=1
[root@shell mnt]# b=1
[root@shell mnt]# test "$a" == "$b" && echo yes || echo no
yes
[root@shell mnt]# [ "$a" == "$b" ] && echo yes || echo no
yes
3)[ 条件1 -a 条件2 ] 表示条件1和2都满足
4)[ 条件1 -o 条件2 ] 表示条件1和2任一个满足

5)[ 条件1 -eq 条件2 ]  等于

6)[ 条件1 -ne 条件2 ]  不等于

7)[ 条件1 -gt 条件2 ]  大于

8)[ 条件1 -ge 条件2 ]  大于等于

9)[ 条件1 -lt 条件2 ]  小于

10)[ 条件1 -le 条件2 ]  小于等于

[root@shell mnt]# [ "$a" -eq "$b" ] && echo yes || echo no
yes

11)[ -n ]   变量内容不为空

12)[ -z ]    变量内容为空

[root@shell mnt]# a=8
[root@shell mnt]# [ -n "$a" ] && echo yes || echo no
yes
[root@shell mnt]# [ -z "$a" ] && echo yes || echo no
no

13)[ -b ]  是否为块设备文件

14)[ -c ]  是否为字符设备文件

[root@shell mnt]# [ -b /dev/sda ] && echo yes || echo no
yes
[root@shell mnt]# [ -c /dev/vfio/vfio ] && echo yes || echo no
yes

15)[ -f ]  是否为常规文件

16)[ -S ]  是否为套接字文件

17)[ -L  ]  是否为链接文件

18)[ -d ]  是否为目录

19)[ -e ] 文件是否存在

20)[ -r ]  是否可读

21)[ -w ]  是否可写

22)[ -x ]  是否可执行

18)[ filename1 -nt filename2 ]  如果 filename1 比 filename2 新,则为真

19)[ filename1 -ot filename2 ]  如果 filename1 比 filename2 旧,则为真

[root@shell mnt]# touch file
[root@shell mnt]# [ /mnt/check_ip -ot file ] && echo yes || echo no
yes

题目:

显示输入的文件类型

解答:

#!/bin/bash
[ -e $1 ] && (
        [ -f $1 ] && echo "$1 Is File"
        [ -d $1 ] && echo "$1 Is Directory"
        [ -b $1 ] && echo "$1 Is Block File"
        [ -L $1 ] && echo "$1 Is Link"
        [ -S $1 ] && echo "$1 Is Socket"
)
14.四则运算


15.语句

case语句:
并发的去匹配所有条件,所有条件同一时间去配置,效率比if语句高

if语句是逐行去匹配,第一行不匹配再去匹配下一行,效率较低


exit 退出脚本。后面加数字1|0则表示退出后$?的值为1|0

break 退出循环








相关内容

    暂无相关文章