欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

脚本学习

程序员文章站 2024-03-18 16:57:22
...

一、初识脚本

shell:
    一类介于系统内核与用户之间的解释程序。
脚本:
    一类使用特定语言,按预设顺序执行的文件,批处理、宏、解释型程序

二、编写shell脚本

1)如何建立一个shell脚本

1)
vim test.sh
#一般情况下脚本的结尾为".sh"这不是系统规定的,但是是一种业界规范

2#!/bin/bash
#脚本头的写法,这是脚本使用的解释器,也就是脚本运行时默认开启的子shell

3)
脚本内容是用命令和命令执行的逻辑关系组成

4)
脚本执行的方式
方法一:
    bash/sh 脚本名称
方法二:
    chmod +x 脚本                    ##脚本名称调用

举例:
[aaa@qq.com test]# vim hello.sh
#!/bin/bash
echo hello
[aaa@qq.com test]# ls
hello.sh
[aaa@qq.com test]# chmod +x hello.sh 
[aaa@qq.com test]# bash hello.sh 
hello
[aaa@qq.com test]# sh hello.sh 
hello
[aaa@qq.com test]# /test/hello.sh 
hello

2)规范要求

1)脚本中应添加脚本的说明信息
Author      :hx                           
Email       :hx@westos.com
Create_Date :2017-08-21
Vesion      :1.0
Description :test scripts

2)脚本中尽量不要使用中文,哪怕用拼音代替

3)脚本中出现的()|[]|{}|<>等等成对出现的符号要一次打出,并且
内容中的字符与这些符号要有空格

4)脚本中的语句要边写边丰富内容,一气呵成的脚本绝对是少数

5)语句中使用的动作要缩进写入,使脚本易读

6)如何让vim自动添加脚本说明
方法一:
脚本中加入子脚本(不推荐)
#!/bin/bash
cat > $1 <<EOF
############################################ 
# Author                :hx 
# Email                 :hx.westos.com 
# Version               : 
# Create_Date           : 2017-08-22
# Description           : 
############################################# 
EOF
vim $1

方法二:
编辑配置文件(推荐)
vim /etc/vimrc
map <F4> ms:call AddTile()<cr>'s        ##设定快捷键
function AddTile()                      ##设定函数内容
        call append(0,"# Author         :Lee")
        call append(1,"# Email          :aaa@qq.com")
        call append(2,"# Version        :")
        call append(3,"# Create_Date    :".strftime("%Y-%m-%d"))
        call append(4,"# Description    :")
endfunction

3)常用命令

1.diff

比较两个文件的不同
diff
[num1,num2][a|c|d][num3,num4]
a       添加
c       改变
d       删除
num1,num3   第一个文件的内容
num3,num4   第二个文件的内容

脚本学习

[root@shell-script test]# vimdiff file1 file2
##这种方法的比较会比较明显,不同的地方高亮显示,而且,背景是粉红色,非常的少女心哦~

脚本学习

diff -r dir1 dir2         ##递归比较子目录
##recursively compare any subdirectories found         
举例:
[root@shell-script linux]# cat /test/westos/haha
/test/westos/haha
[root@shell-script linux]# cat /test/linux/heihei
/test/linux/heihei
[root@shell-script linux]# diff -r /test/westos/ /test/linux/
Only in /test/westos/: haha
Only in /test/linux/: heihei
diff -u file1 file2 
##output unified (default 3) lines of unified context

举例:
[aaa@qq.com linux]# cd /test/
[aaa@qq.com test]# ls
file1  file2  linux  westos
[aaa@qq.com test]# diff -u file1 file2
--- file1   2017-08-22 21:24:43.366365584 -0400
+++ file2   2017-08-22 21:23:15.493365584 -0400
@@ -1,2 +1,2 @@
 hello world
-124
+123

[aaa@qq.com test]# diff -u file1 file2 > file.path
##将此文件内容重定向到一个新的文件中,以便后续作布丁使用
patch  file file.path                     ##需要安装patch软件

脚本学习

patch -b file file.path     #-b标示备份原文件为file.orig

脚本学习

2.grep

    Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
    grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

参数:

-i :忽略大小写
## Ignore  case  distinctions  in  both  the PATTERN and the input files.  (-i is specified by POSIX.)

举例:
[root@shell-script test]# vim file1
[root@shell-script test]# cat file1
hello world
HELLO WORLD
[root@shell-script test]# grep hello file1           ##默认情况下,按标准输出查找
hello world
[root@shell-script test]# grep HELLO file1
HELLO WORLD
[root@shell-script test]# grep -i hello file1        ##加上-i参数后,则会
hello world
HELLO WORLD
[root@shell-script test]# grep -i HELLO file1
hello world
HELLO WORLD

为了使下面的实验效果更加明显,先创建一个新的文件/test/passwd:

脚本学习

-c :打印匹配的行数

打印匹配nologin的行数
举例:
[root@shell-script test]# grep -c nologin passwd 
11
-l :从多个文件中查找包含匹配项

从多个文件中查找包含匹配有ntp的文件
举例:
[aaa@qq.comscript test]# ls
file1  file2  file.path  passwd
[aaa@qq.comscript test]# grep -l ntp passwd 
passwd
-v :查找不包含匹配项的行

假如我们现在要查询除了有关键字nologin的信息:
举例:
[root@shell-script test]# grep -v nologin passwd 
root:x:0:0:root:/root:/bin/bash
-n:打印包含匹配项的行和行标

假如我们现在要查询匹配有关键字ntp的具体的在哪一行:
举例:
[root@shell-script test]# grep -n ntp passwd         ##打印关键字所在行
6:ntp:x:38:38::/etc/ntp:/sbin/nologin

[root@shell-script test]# grep -n3 ntp passwd       ##打印关键字所在上下三行,数字可看需求定
3-unbound:x:995:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
4-qemu:x:107:107:qemu user:/:/sbin/nologin
5-saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
6:ntp:x:38:38::/etc/ntp:/sbin/nologin
7-rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
8-radvd:x:75:75:radvd user:/:/sbin/nologin
9-pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin

[root@shell-script test]# grep -A3  ntp passwd      ##打印关键字所在下三行,数字可看需求定
ntp:x:38:38::/etc/ntp:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin

[root@shell-script test]# grep -B3  ntp passwd      ##打印关键字所在上三行,数字可看需求定
unbound:x:995:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
3.cut
    按列切分文件,你可以指定分隔每列的定界符。
    在cut的术语中,每列都是一个字段,就是有时候说第一列,可能表述称第一个字段。
cut -c 1 | 1-4 | 1,4  filename

脚本学习

cut -d : -f 1,7 | -f 1-3 | 1 filename

脚本学习

4.echo
echo -n                          ##do not output the trailing newlin
echo -e                          ##enable interpretation of backslash escapes

脚本学习

echo -e "\r \r"                         ##新出的字符串会覆盖前面的字符串
##carriage return

脚本学习

5.awk
awk [-F  field-separator]  'commands'  input-file(s)

其中,commands 是真正awk命令,[-F域分隔符]是可选的:--field-separator。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

TEST="#################################"
awk -F 分隔符 -v TEST=$TEST  'BEGIN {print TEST} {print $2} END{print TEST}' /etc/passwd

awk -F ":" -v TEST=$TEST 'BEGIN {print TEST ":"} {print $2} END{print TEST}' /etc/passwd

##参数解释
-F fs
--field-separator fs
  Use fs for the input field separator (the value of  the  FS  predefined variable)

-v var=val
--assign var=val
  Assign  the value val to the variable var, before execution of the pro‐gram begins.  Such variable values are available to the BEGIN block of an AWK program.

6.sed
  sed 是一种在线编辑器,它一次处理一行内容。sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。
  sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。
   前面说到sed不会修改文件,那么现在我们可以知道是为什么了?是因为sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。 在使用sed的过程中,我们经常会听到“定址”,那么什么是“定址”呢?
  定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。

sed 's/sbin/westos' passwd                           ##将全文的sbin转换为westos
sed '1,5s/sbin/westos/g' passwd                      ##1-5行所以的sbin转换为westos
sed '/lp/,/shutdown/s/sbin/westos/g' passwd          ##以lp开头,shutdown结尾的所有sbin转换为westos
sed -e 's/sbin/westos/g' -e 's/nologin/redhat/g' passwd  ##在一个文件中需要同时修改多处时,必须要加上-e参数
sed xd filename                    ##输出时,将filename中第x行删除
sed xp filename                    ##输出时,将filename中第x行复制 
sed -n xp filename                 ##仅输出filename中第x行

脚本学习

vim file
s/sbin/westos/g
s/nologin/lee/g

sed -f file passwd                   ##直接执行文件中的动作
sed -i 
##-i[SUFFIX], --in-place[=SUFFIX]
  edit files in place (makes backup if SUFFIX supplied)

脚本学习

7.sleep
 sleep 1                             ##一秒后执行
 sleep - delay for a specified amount of time

4)逻辑分隔符

    && --> 
    || --> 
    :: --> 顺序执行

举例:

5)变量

1)
作用:
当数据改变时,直接使用数据的时候不能够灵活的根据数据改变而随着变化,而变量只需改变最初赋予的值,便可完成了这一整套操作。
2)
变量的命名规则
首字母不能是数字,变量中只能包含 字母 数字和"_"

定义与赋值:
   变量名=变量值
引用变量:
   $变量名 、${变量名}

TEST
TEST_REDHAT
Test_Redhat
tesTRedhat

例子:
[root@shell-script ~]# NUM=1
[root@shell-script ~]# echo $NUM
1
[root@shell-script ~]# echo ${NUM}
1
3)
Bash解析的个别参数或整个原始命令行。
指定的位置参数总数:$#
位置参数自身:$0、$1、$2、$3....
所有位置参数: aaa@qq.com、$*

脚本学习

脚本学习

4)
定界符号
单引号:允许引用,\转义
双引号:禁止引用、转义
反撇号(或者$):以命令输出进行替换

举例:
[root@shell-script ~]# Title=hx                    ##定义变量
[root@shell-script ~]# echo " $Title's blog "      ##双引号
 hx's blog 
[aaa@qq.com ~]# echo ' $Title's blog '      ##单引号
> ^C
[root@shell-script ~]# echo ' $Title blog '        ##单引号
 $Title blog 

[root@shell-script ~]# Ver=` uname -r `            ##反撇号
[root@shell-script ~]# echo $Ver
3.10.0-123.el7.x86_64
5)
变量设定方式

【环境级】
    shell和脚本使用变量来存储数据 ,有些变量可以连同它们的内容传递给子进程,使用env命令显示所有环境变量,使用set命令现实所有本地定义的shell变量

【用户级】
只针对配置过的用户生效,其他用户无法使用
vim /root/.bash_profile
export A=1
source /root/.bash_profile

【系统级】
6)
使用别名

Bash启动脚本
    在用户登录的时候,会运行全局变量文件/etc/profile,和用户自定义变量文件~/.bash_profile去初始化它们的环境变量。
    alias命令可以用来自定义属于自己的系统命令,写入~/.bashrc 文件永久生效;而,export A=1虽然也可以声明,但是,只在当前环境生效,当前环境关闭,变量失效

命令别名设定:
alias xie='vim'

vim ~/.bashrc
alias xie='vim'

vim /etc/bashrc
alias xie='vim'

unalias xie
7)
变量定义方式
方法一:
USER=root
方法二:
$0 $1 $2 $3 $n $* $# $?
方法三:
read -p "Please input your IP:" IP
##read -p "Please input xx"
    Display prompt on standard error, without a trailing new‐line, before attempting to read any input.  The prompt is displayed only if input is coming from a terminal.
8)
shell脚本中函数的定义
TEST()
{
    echo hello world
}

TEST                            ##函数名直接调用即可
9)
变量对比
test = []
test的官方定义 : check file types and compare values

test命令可用于评估bash脚本中的表达式。它评估其参数所指定的表达式,如果表达式为true,返回零退出状态,如果表达式为false,则返回非零退出状态。

test具有替代语法,使用方括号"[]"将表达式括起来,这样更易于阅读。

非零或零长度字符串运算符:test -{n|z} STRING

1>字符串比较运算符:=、!= 
官方解释:    
       STRING1 = STRING2
              the strings are equal
       STRING1 != STRING2
              the strings are not equal

2>数字比较运算符:-eq、-ne、-lt、-le、-gt、-ge
官方解释:
       INTEGER1 -eq INTEGER2
              INTEGER1 is equal to INTEGER2

       INTEGER1 -ge INTEGER2
              INTEGER1 is greater than or equal to INTEGER2

       INTEGER1 -gt INTEGER2
              INTEGER1 is greater than INTEGER2

       INTEGER1 -le INTEGER2
              INTEGER1 is less than or equal to INTEGER2

       INTEGER1 -lt INTEGER2
              INTEGER1 is less than INTEGER2

       INTEGER1 -ne INTEGER2
              INTEGER1 is not equal to INTEGER2

3>文件比较运算符:-ef、-nt、-ot
官方解释:
       FILE1 -ef FILE2
              FILE1 and FILE2 have the same device and inode numbers

       FILE1 -nt FILE2
              FILE1 is newer (modification date) than FILE2

       FILE1 -ot FILE2
              FILE1 is older than FILE2


4>文件状态运算符:test -{b|c|e|f|d|r|w|x|s|L} FILE/DIRECTORY
官方解释:
       -b FILE
              FILE exists and is block special

       -c FILE
              FILE exists and is character special

       -d FILE
              FILE exists and is a directory

       -e FILE
              FILE exists

       -f FILE
              FILE exists and is a regular file

       -g FILE
              FILE exists and is set-group-ID

       -G FILE
              FILE exists and is owned by the effective group ID

       -h FILE
              FILE exists and is a symbolic link (same as -L)

       -k FILE
              FILE exists and has its sticky bit set

       -L FILE
              FILE exists and is a symbolic link (same as -h)

       -O FILE
              FILE exists and is owned by the effective user ID

       -p FILE
              FILE exists and is a named pipe

       -r FILE
              FILE exists and read permission is granted

       -s FILE
              FILE exists and has a size greater than zero

       -S FILE
              FILE exists and is a socket

       -t FD  file descriptor FD is opened on a terminal

       -u FILE
              FILE exists and its set-user-ID bit is set

       -w FILE
              FILE exists and write permission is granted

       -x FILE
              FILE exists and execute (or search) permission is granted
10)
变量的声明
a=1
$ab = 空
${a}b = 1b

6)四则运算


1.运算法则
++    i++       i=i+1
--    i--       i=i-1
+=    j+=i      j=j+i
-=    j-=i      j=j-1
+     
-
*
/
**
%
2.运算命令
$[3+2]
let A=3+2
expr 3+2

7)脚本中的常用语句

1.
for
do
done

2.
while
do
done

3.
if
then
elif
then
else
fi

4.
case

esac
5
.expect

8)举例

例一:

创建用户:试写一个简单的脚本,可以创建新用户,并将其初始密码设置为:123456

##先在shell中执行一遍创建用户及赋予密码的过程,确保梳理清楚后,然后,再着手编写脚本,养成好的习惯~
[root@shell-script mnt]# useradd usertest
[root@shell-script mnt]# echo 123456 | passwd --stdin usertest
Changing password for user usertest.
passwd: all authentication tokens updated successfully.
[root@shell-script mnt]# su - usertest

脚本内容:
脚本学习

执行脚本:
脚本学习

例二:

抓取出系统中所有可以登录的用户的用户名:

step1:
查看系统中都有哪些登录方式
[aaa@qq.com test]# cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

step2:
明确用户信息记录在/etc/passwd中

step3:
编写脚本文件进行抓取:
grep -E "\<sh$|\<tch$|\<bash\>|\<csh$" /etc/passwd | cut -d : -f 1

例三:

问题:抓取出主机IP

方法一:

优点:简单易懂
缺点:cut使用时,需要人为参与去数想要抓取的关键字到底在哪~
脚本学习
实验结果:
脚本学习

方法二:

优点:使用了awk强大的功能
脚本学习
实验结果:
脚本学习

方法三:

优点:可以查多网卡的IP
脚本学习

例四:

问题:查看1-10号各台主机的hostname,如果连不上的话,要进行提示。

例五:

问题:创建某名单上的用户,并将随之附带的密码赋予给相应的用户

要求:如果文件输入的个数小于2,则提示“请输入一个用户文件或密码文件“;如果文件不存在,则提示“用户名单或者密码文件不存在“;如果用户人数和密码个数不匹配,则提示“请认真核对用户信息,操作不允许!“;如此,即可。

例六:

问题:检验某台主机是否可以ping通,如果可以,显示"xx is up";否则,显示"xx is down"

脚本学习