第一章、shell脚本基础

第一章、shell脚本基础
shell的作用:人和机器交互的工具--》其实是一个程序。
shell里比较好用的程序是bash
默认情况下几乎所有的linux系统默认的shell都是bash
====
c语言为什么要编译。c语言是人认识的语言,根据某种编码进行翻译叫编译。


 
shell脚本编程的优势。
查看当前shell
  1. [oracle@oracle ~]$ echo $SHELL
  2. /bin/bash
  3. [oracle@oracle ~]

shell课程体系

Shell脚本编程

Shell基础

变量的使用

算术运算、数组应用

排序、提取、组合命令

条件测试

if语句、for循环、while循环、case分支和函数应用

正则表达式

expect

dialog


sed

Awk

案例



1-2

3-4

5-6

7-8


知识要点

掌握Shell脚本的基础知识
学会使用Shell变量
学会编写简单的Shell脚本 

shell脚本的运行环境

学习shell脚本的基本流程

看、想、写

shell脚本用在什么地方

编写常用系统维护工具菜单
重要的性能参数、进程和日志分析
自动实现数据备份计划
自动批量搭建特定系统环境
防火墙自动配置脚本
服务器的配置文件安全比对
对批量设备进行远程巡检

shell脚本的组成元素

shell脚本的基本组成
声明和注释
系统命令
文本处理工具(grep、cut、sed、awk…)
各种变量
各种条件判断
循环结构语句
各种函数

shell的作用

shell的作用---命令解释器,“翻译官”
介于系统内核与用户之间,负责解释命令行
 

shell脚本的优势

编译型语言
编写-编译-链接-运行(edit-compile-link-run)
CC++、Ada、Java、C#
脚本语言
解释器读入脚本程序代码,将其转换成内部的形式执行
解释器本身则是编译型程序
Shell脚本编程的优势
语法和结构通常比较简单
学习和使用通常比较简单
通常以容易修改程序的“解释”作为运行方式,而不需要“编译”

登陆shell的种类和切换

登陆shell
指定用户每次登陆系统后自动加载的shell程序,大多数linux系统采用/bin/bash 作为默认登陆shell
/etc/shells 文件记录了系统支持的有效登陆shell。
  1. [root@oracle ~]# cat /etc/shells
  2. /bin/sh ---》最小化安装都有
  3. /bin/bash ---》推荐使用
  4. /sbin/nologin
  5. /bin/dash
  6. /bin/tcsh
  7. /bin/csh
  8. /bin/ksh
  9. [root@oracle ~]#
如何切换shell环境
临时切换:直接执行其他shell程序,例如ksh、zsh等
返回到原来的shell环境时可以执行‘exit'命令或者按ctrl+d快捷键
更改用户登陆shell:
需要修改/etc/passwd 文件中用户登陆的最后一个字段
或执行:usermod -s shell程序路径 用户名

shell初始化

bash初始化
登陆shell
指的是输入用户名、密码,从系统登陆时执行的第一个程序。
非登陆shell
登陆系统后,在login shell里启动的shell是非login shell
如执行bash命令、在图形中打开终端均是打开一个非登陆shell。

bash初始化

bash的启动脚本初始化
 
 bash启动时,会进行初始化,初始化就是执行一些脚本。会执行哪些脚本分两种情况。
1、登陆时启动的bash,登陆shell
初始化脚本执行顺序:/etc/profile-->/etc/profile.d/*.sh-->~/.bash_profile-->~/.bashrc-->/etc/bashrc
如果这些脚本中的变量发出冲突,那么以最后一个脚本的设置生效。
2、登陆后,启动的bash,非登陆shell
初始化脚本执行顺序:~/.bashrc--->/etc/bashrc-->/etc/profile.d/*.sh
注意:这些脚本中不要乱增加内容。例如:在脚本中增加echo。

shell启动配置文件的区别
/etc/profile:配置全局环境变量,影响所有用户。
~/.bash_profile:配置个人环境,影响一个用户。
/etc/bashrc:配置全局的别名或者shell选项,影响所有用户。
~/.bashrc:配置个人别名或者shell选项,影响一个用户。

登陆和非登陆shell的区别
登陆shell负责系统全局环境初始化,会读取所有启动配置文件。
非登陆shell默认会继承登陆shell的环境变量,为了加快速度,无需读取所有启动配置文件,只需读取少量局部配置文件。
退出登陆shell:~/.bash_logout
  1. env 查看环境变量
  2. set 查看当前用户可以使用的所有的变量

bash的命令历史

命令历史
保存用户曾经执行过的命令操作。
存放位置:~/.bash_history文件

查看命令历史
使用上箭头和下箭头 逐条翻看,允许编辑并重新执行
执行:history

清除历史命令
执行:history -c

查看命令历史
  1. [root@oracle ~]# history
  2. 1 cd /etc
  3. 2 ls
  4. 3 cd sysconfig
  5. 4 ls
  6. 5 cd network-scripts
  7. 6 ls

调用名利历史
!n:执行历史命令中的第n条命令。
!str:执行历史记录中以str开头的命令
  1. [root@oracle ~]# !2
  2. ls
  3. anaconda-ks.cfg Documents install.log Music Public tmp
  4. Desktop Downloads install.log.syslog Pictures Templates Videos
  5. [root@oracle ~]# !cd
  6. cd /backup
  7. [root@oracle backup]#

设置记录历史命令的条数
修改histsize参数(默认为1000条)


  1. [root@oracle ~]# vi /etc/profile
  2. # /etc/profile
  3. # System wide environment and startup programs, for login setup
  4. # Functions and aliases go in /etc/bashrc
  5. HISTSIZE=1000

bash的命令别名


命令别名
为使用频率较高的复杂命令行设置简短的调用名称
存放位置:~/.bashrc

查看命令别名
格式:alias [别名]

设置命令别名
执行alias 别名=’实际执行的命令‘

取消已经设置的命令别名
格式:unalias 别名
            unalias -a

查看命令别名
  1. [root@oracle ~]# alias
  2. alias cp='cp -i'
  3. alias l.='ls -d .* --color=auto'
  4. alias ll='ls -l --color=auto'
  5. alias ls='ls --color=auto'
  6. alias mv='mv -i'
  7. alias rm='rm -i'
  8. alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
  9. [root@oracle ~]#


shell中命令的执行

无条件运行多个命令
cmd1;cmd2;cmd3

在子shell中执行命令
(cmd1;cmd2)
不影响父shell的环境

编写第一个shell脚本


编写脚本代码

使用vi文本编辑器
每行一条linux命令,按执行顺序依次编写
  1. [root@localhost ~]# vi first.sh
  2. cd /boot/
  3. pwd
  4. ls -lh vml*

赋予可执行权限

使脚本具有可执行属性
  1. [root@localhost ~]# chmod +x first.sh
  2. [root@localhost ~]# ls -l first.sh
  3. -rwxr-xr-x 1 root root 144 04-26 15:02 first.sh

执行脚本文件

第一种方法:脚本文件路径
第二种方法:bash 脚本文件路径
第三种方法:source或者. 脚本文件路径(使用.执行脚本,必须有执行权限)
 
更完善的脚本结构
1、脚本声明
2、注释信息
3、可执行语句

  1. ====
  2. 声明:以#!开头
  3. 注释:以#开头
  4. #!/bin/bash  ---》申明使用bash作为默认shell来执行脚本
  5. #########################################
  6. #Function:    auto fdisk
  7. #Usage:       bash auto_fdisk.sh
  8. #Author:      Customer service department
  9. #Company:     Alibaba Cloud Computing
  10. #Version:     2.0
  11. #########################################
  12. ===========
注释:
1.给人看的
2.脚本不会执行
3.方便不熟悉的人,快速了解代码的作用
4.linux shell里以#开头的行是注释行


使用lftp命令下载文件和文件夹

[root@chinaitsoft lianxi]# lftp 172.16.1.1  登录ftp服务器

  1. lftp 172.16.1.1:~> ls
  2. -rwxr-xr-x    1 0        0        17921378 Sep 09 18:19 PotPlayer视频播放器.zip
  3. drwxr-xr-x    8 0        0            4096 Nov 20 19:10 linux-video
  4. drwxr-xr-x    2 0        0            4096 Feb 29 13:46 mysql
  5. drwxr-xr-x    4 0        0            4096 Sep 12 20:42 python
  6. drwxr-xr-x    7 0        0            4096 Mar 04 16:16 software
  7. drwxr-xr-x    4 0        0            4096 Jan 23 15:10 teacher_feng
  8. drwxr-xr-x    7 0        0            4096 Jan 05 13:44 video
  9. drwxr-xr-x    2 0        0            4096 Dec 13 22:56 xiang
  10. lftp 172.16.1.1:/> cd teacher_feng/
  11. lftp 172.16.1.1:/teacher_feng> ls
  12. drwxr-xr-x   10 0        0            4096 Dec 21 15:16 9_class
  13. drwxr-xr-x   10 0        0            4096 Mar 05 14:05 califeng
  14. -rw-r--r--    1 0        0           13990 Oct 31 23:56 mysql_plan.xlsx
  15. lftp 172.16.1.1:/teacher_feng> cd 9_class/linux-shell-course/
  16. lftp 172.16.1.1:/teacher_feng/9_class/linux-shell-course> get yuli_admin_system_user-v2.sh 
  17. 6886 bytes transferred                                    
  18. lftp 172.16.1.1:/teacher_feng/9_class/linux-shell-course> 
  19. [root@chinaitsoft lianxi]# lftp 172.16.1.1
  20. lftp 172.16.1.1:~> bye
  21. [root@chinaitsoft lianxi]# lftp 172.16.1.1
  22. lftp 172.16.1.1:~> exit
  23. [root@chinaitsoft lianxi]# lftp 172.16.1.1
  24. lftp 172.16.1.1:~> quit
  25. [root@chinaitsoft lianxi]#
  26. ====
  27. get是下载文件
  28. mirror 下载文件夹
  29. 退出 quit bye exit
  30. 默认情况下下载的文件或者文件夹存放在当前目录
  31. lftp 172.16.1.1:/> !ls  在本机上执行ls命令
  32. aa  frist.sh  sed  yuli_admin_system_user-v2.sh
  33. lftp 172.16.1.1:/> 
  34. lftp 172.16.1.1:/> !pwd
  35. /lianxi
  36. lftp 172.16.1.1:/> lcd /root  切换本地路径  local 
  37. lcd 成功, 本地目录=/root
  38. lftp 172.16.1.1:/> 
  39. ====


shell变量的作用、类型

变量的作用
为灵活管理linux系统提供特定参数了,有两层意思:
变量名:使用固定的名称,有系统预设或者用户定义
变量值:能够根据用户设置、系统环境变量的变化而变化。
变量的类型
自定义变量:由用户自己定义、修改和使用。
环境变量:由系统维护,用于设置工作环境。
位置变量:通过命令行给脚本程序传递参数。
预定义变量:bash中内置的一类变量,不能直接修改。

按变量使用的范围。
局部变量:只在当前的shell中有效。
全局变量:子shell会从父shell中继承变量。

自定义变量

定义新的变量
变量名要求以英文字母或下划线开头,不能以数字开头,区分大小写,约定俗称为大写(IP_addr),但是不强制。
等号两边不要空格。
格式:变量名=变量值

查看变量的值
格式:echo $变量名
  1. [root@oracle ~]# day=sunday
  2. [root@oracle ~]# echo $day
  3. sunday
  4. [root@oracle ~]# DAY=sun
  5. [root@oracle ~]# echo $day
  6. sunday
  7. [root@oracle ~]# echo $DAY
  8. sun
  9. [root@oracle ~]#
通过$符号引用指定名称的变量值
变量值有空格用双引号括起来。
  1. [root@oracle ~]# name="hai lian tian"
  2. [root@oracle ~]# echo $name
  3. hai lian tian
  4. [root@oracle ~]#

如果变量名容易和后面的字符和下划线连在一起导致混淆,则应该使用大括号将变量括起来${变量名}
  1. [root@oracle ~]# DAY=Sunday
  2. [root@oracle ~]# echo "Today is Sunday" >$DAY_file.txt
  3. [root@oracle ~]# ls -a
  4. .txt
  5. [root@oracle tmp]# echo "today is sunday " >${DAY}_file.txt
  6. [root@oracle tmp]# ls -a
  7. . .. .esd-0 .ICE-unix Sunday_file.txt .X0-lock .X11-unix
  8. [root@oracle tmp]#

可以将命令的执行结果直接赋值给变量
  1. var2=$(rpm -qf $(which fdisk))
  2. [root@oracle tmp]# var2=$(rpm -qf $(which fdisk))
  3. [root@oracle tmp]# echo $var2
  4. util-linux-ng-2.17.2-12.14.el6.x86_64
  5. [root@oracle tmp]#

readonly可以将变量设置为只读,变量一旦设置为只读,任何用户不能对此变量进行重新赋值。
variable=value  #先对一个变量进行赋值
readonly variable #将variable设置为只读
利用unset命令可以清除变量的值
格式:unsettling 变量名


shell命令行替换

bash shell在解释命令前替换某些命令行元字符
通配符替换:*    、?  、[a-z]
历史命令替换:!! 、!n 、 !str
代字号替换: ~  、~用户名
变量替换:$变量名 、${变量名}
大括号替换:{a,b,c}file、{aa,bb}/{aa,bb}   
算数替换:+、-、*、/

{a,b,c}file        afile/bfile/cfile
{aa,bb}/{aa,bb}    aa/bb      aa/aa     bb/aa   bb/bb

shell中引号

引用和转义字符
使用特殊字符时,就是表示本身,不使用其特殊意义
:避免下一个字符被shell解释
双引号 " " :避免双引号内除了$、! 和 `(反引号)以外的其他字符被shell解释。
单引号 ’ ’ :避免单引号内的任何字符被shell解释
反引号 `` :命令替换,提取命令执行后的输出结果  和$()相同
单引号、双引号、反引号的区别。
shell替换发生在命令运行之前。

实验案例1


编写脚本显示如下图所示效果,分析显示的结果。
name="hello"
myname0='My name is $name'
myname1="My name is '$name'"
myname2='My name is "$name"'
myname3="My $name is "$name""         #就近配对  my hello is hello
myname4='My $name is '$name''           #就近配对  my $name is hello
echo $myname0
echo $myname1
echo $myname2
echo $myname3
echo $myname4
  1. [root@oracle tmp]# name="hello"
  2. [root@oracle tmp]# myname0='My name is $name'
  3. [root@oracle tmp]# myname1="My name is '$name'"
  4. [root@oracle tmp]# myname2='My name is "$name"'
  5. [root@oracle tmp]# myname3="My name is "$name""
  6. [root@oracle tmp]# myname4='My name is '$name''
  7. [root@oracle tmp]# echo $myname0
  8. My name is $name
  9. [root@oracle tmp]# echo $myname1
  10. My name is 'hello'
  11. [root@oracle tmp]# echo $myname2
  12. My name is "$name"
  13. [root@oracle tmp]# echo $myname3
  14. My name is hello
  15. [root@oracle tmp]# echo $myname4
  16. My name is hello
  17. [root@oracle tmp]#


echo命令

echo命令的-e选项表示将转义符后跟字符形成的特殊字符解释成特殊意义。
符号意义
新的一行
表示tab键
  1. [root@oracle ~]# echo -e " abc123"
  2. abc123
  3. [root@oracle ~]# echo -e " abc 123"
  4. abc
  5. 123
  6. [root@oracle ~]#

自定义变量
从键盘输入内容为变量赋值
格式:read [选项] 变量名
选项
-p:提示信息
-s:隐藏输入(密码时用)
-t:指定超时时间
-n:指定读取的长度      //密码结束  //y/n        //按任意键结束。

[root@db11g touch1]# read -s -p "please input passwd:" passwd
please input passwd:
  1. [root@oracle tmp]# cat read.sh
  2. #!/bin/bash
  3. ##############################
  4. #Function: read using
  5. #Us
  6. #Author: wangyu
  7. #Company: haitianjingyu
  8. #Version: 1.0
  9. ##############################
  10. read -p "please input you name:" name
  11. read -n3 -s -p "input password:" pwd
  12. echo -e " you username is $name ,password is $pwd"
  13. [root@oracle tmp]# bash read.sh
  14. please input you name:hai
  15. input password:
  16. you username is hai ,password is hai
  17. [root@oracle tmp]#

[root@db11g touch1]# echo -n "please:" && read var1
please:
-n:表示不换行。

实验案例2

编写脚本显示如下图所示效果,要求选择一个菜单后,不用按回车马上显示结果
 脚本代码:
[root@oracle tmp]# vi menu.sh
  1. #!/bin/bash
  2. ##############################
  3. #Function: menu
  4. #Author: wangyu
  5. #Company: haitianjingyu
  6. #Version: 1.0
  7. ##############################
  8. clear
  9. echo -e " ***system menager tool***"
  10. echo -e " 1. show disk space info"
  11. echo -e " 2. show network connector info"
  12. echo -e " 3. show memory using info"
  13. echo -e " 0. exit menu"
  14. echo -en " input option:"
  15. read -n1 num
  16. echo -e " you option is $num"
运行效果:

 

实验案例3

编写脚本,根据输入的用户名和密码(密码不显示出来)自动新建用户并配置密码,脚本运行如下图所示(不能显示多余的提示)
 脚本如下
  1. [root@oracle tmp]# cat adduser.sh
  2. #!/bin/bash
  3. ##########################
  4. #Function: create new user
  5. #Author: wangyu
  6. #Company: haitianjingyu
  7. #Version: 1.0
  8. ##########################
  9. read -p "add new user:" name
  10. read -s -p "user $name password:" pwd
  11. useradd $name
  12. echo $pass|passwd --stdin $name &>/dev/null
  13. echo -e " user $name is ok"
  14. [root@oracle tmp]# bash adduser.sh
  15. add new user:hai2
  16. user hai2 password:
  17. user hai2 is ok
  18. [root@oracle tmp]#


自定义变量
设置变量的作用范围
格式1: export 变量名...
格式2:export 变量名=变量值...
-----两种格式可以混合使用
export 查看全局变量



全局变量
查看全局变量
set命令可以查看所有的shell变量,其中包括全局变量。
env命令只查看全局变量。

环境变量
由系统提前创建,用来设置用户的工作环境。
配置文件:/etc/profile、~/.bash_profile
常见的环境变量:
pwd、path
user、logname、uid、ppid、shell、home
ps1、$ps2

位置变量
表示为$n ,n为1~9之间的数字。
大于9的位置参数要用{},例如${10}.
 
实验4编写脚本实现统计目录数目。


预定义变量
$#:命令中位置变量的个数
$*:所有变量的内容(不常用)
$@:所有变量的内容
$0:当前执行的进程名
$$:当前shell的pid
$?:上一条命令的执行返回状态,当返回状态值为0时,表示执行正常,非0时表示执行异常或者出错。
$RANDOM:随机数,可以作为临时文件名。
touch abc$RANDOM.txt


有条件运行多个命令
 
 
备份脚本的使用









bash的重定向操作
改变标准输入、标准输出、标准错误输出的方向。
程序名和进程名可能不同。

正确输出可以重定向到不同的文件。
 

 
创建oracle 表空间

#!/bin/bash
read -p "请输入表空间的名字:"  name
sqlplus / as sysdba<<eof
CREATE BIGFILE TABLESPACE ${name}
DATAFILE '${name}.dbf'
SIZE 20M AUTOEXTEND ON;
eof >> /dev/null
echo "成功!"




统计文件夹下后缀名。

#!/bin/bash

read -p "请输入查找的文件夹: " DIR

for i in "$@"

do

if(i!=0){

NUM=$(find $DIR -type f -name "*$i" | wc -l)

echo "$i结尾的文件的数目是: " $NUM

}

fi

done




yum 的安装

#!/bin/bash

read -p "请输入一个挂载点的目录绝对路径:" DIR

mkdir -p $DIR

umount /dev/sr0 &> /dev/null

mount /dev/sr0 $DIR &> /dev/null

(cd /etc/yum.repos.d; tar *.repo *repo.tar  &> /dev/null)

cat << EOF > /etc/yum.repos.d/yumlocal.repo

[Server]

name=Server

baseurl=file:///$DIR

enabled=1

gpgcheck=0

EOF

yum clean all &> /dev/null &&  echo yum is ok

 

 
 
 
原文地址:https://www.cnblogs.com/haitianjingyu/p/6973709.html