第一章 Shell 脚本编程应用指南
1. 学习Shell编程需要掌握的基础。
- vi/vim的熟练使用
- Linux 常用命令的熟练使用
- 常见 Linux 网络服务部署排错
2. Shell 脚本概念原理介绍。
shell 是一个命令解释器。它在操作系统的外层,负责直接与用户的对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户。
3. 简单和复杂的两个 shell 脚本。
范例 1. 清除/var/log 下的 message 日志文件的简单命令脚本。
# 把所有命令放在一个文件堆积起来就形成了脚本。
# 要使用 root 身份来运行这个脚本
# 清除日志脚本
cd /var/log
cat /dev/null > messages
echo "Logs cleaned up."
# 提示:/var/log/messages 是系统的日志文件,很重要
问题:
(1) 不是 root 就无法执行清理日志。
(2) 没有任何的流程控制语句,简单的说就是顺序操作,没有成功判断和逻辑性。
范例2. 包含命令、变量和流程控制语句的清除 /var/log 下的 messages 日志文件的 shell 脚本。
#!/bin/bash
# 清除日志脚本
LOG_DIR=/var/log
ROOT_UID=0 # $UID为0的时候,用户才具有root用户的权限
# 要使用root用户来运行,中括号加空格隔开
if [ "$UID" -ne "$ROOT_UID" ]
then
echo "Must be root ro tun this script."
exit 1
fi
cd $LOG_DIR || {
echo "Cannot change to necessary directory." >&2
exit 1
}
cat /dev/null > messages && echo "Logs cleaned up."
exit 0
# 退出之前返回0表示成功返回1表示失败
扩展:清空日志及文件内容的三种方法:
[root@localhost day1]# echo >test.log # 有一空白行
[root@localhost day1]# > test.log # 重定向
[root@localhost day1]# cat /dev/null > test.log
4. Linux系统的默认脚本解释器?
Centos linux 系统默认的 shell 是 bash。
查看方法:echo $SHELL 或 grep root /etc/passwd
5. shell 脚本的建立和执行
- 脚本开头(第一行)
一个规范的 shell 脚本的第一行会指出由那个程序(解释器)来执行脚本中的内容,在linux bash 编程中一般为:
#!/bin/bash
或
#!bin/sh < ==255 个字符以内
“#!”又被称为幻数,在执行脚本时,内核会根据"#!"后的解释器确定该用哪个程序解释脚本中的内容。注意:这一行必须为每个脚本顶端的第一行。
sh 为bash的软链接。
如果为python,则第一行为,执行如:python test.py执行
#!/usr/bin/env python
6. shell脚本开发基本规范及习惯
(1) 开头指定脚本解释器
#!bin/sh 或 #!/bin/bash
(2) 开头加版权等信息
#Date: 16:29 2020-3-30
#Author: Created by oldboy
#Mail: 48000448@qq.com
#Function: This scripts function is....
#Version: 1.1
提示:可配置vim编辑文件时自动加上以上信息,方法是修改~/.vimrc 配置文件。
(3) 脚本不用中文注释
尽量使用英文注释防止本机或切换系统环境后中文乱码的困扰。
(4) 脚本以.sh为扩展名
(5) 代码书写习惯优秀
I. 成对的符号内容一次写出来,防止遗漏,如:{},[],’’,""
II. [] 中括号两端要有空格,书写时即可留出空格[ ]
III. 流程控制语句一次性书写完,在添加内容,如:
if 语句格式一次完成:
if 条件内容
then
内容
fi
for 循环格式一次完成:
for
do
内容
done
(6) 通过缩进让代码易读
第二章 Shell 变量基础及深入
1. 环境变量
环境变量用于定义 Shell 的运行环境,保证 Shell 命令的正确执执行。家目录下的.bash_profile文件中或全局配置/etc/bashrc,/etc/profile,/etc/profile.d中定义。
登录显示加载内容可以放在/etc/profile.d目录下。
传统上,所有的环境变量均为大写。环境变量应用于用户进程前,必须用export命令导出。
用 evn 或 set 显示默认环境变量。unset 消除本地变量和环境变量。
2. 局部变量
I. 普通字符串变量定义:
变量名=value; 变量名=‘value’; 变量名=’'value"
II. 命令变量:
变量名=``; 变量名=$()
习惯:数字不加引号,其他默认加双引号。
单引号:看到的是什么就会输出什么。
双引号:把双引号内的所有内容都输出出来,如果内容中有命令,变量,特殊转义,会先解析出命令结果,然后在输出最终内容来。
无引号:一般连续的字符串,数字i,路径等可以不加引号。不过最好情况用双引号替代之。
3. 特殊变量
I. 位置变量
$0 获取当前执行的 shell 脚本的文件名,包括脚本路径,如
dirname $0 # 文件路径
basename $0 # 文件名字
n 获 取 当 前 执 行 的 s h e l l 脚 本 的 第 n 个 参 数 值 , n = 1..9 , 当 n 为 0 时 表 示 脚 本 的 文 件 名 , 如 果 n 大 于 9 , 则 n 获取当前执行的 shell 脚本的第 n 个参数值,n=1..9, 当 n 为 0 时表示脚本的文件名,如果n 大于9,则 n获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9,则{10}
$# 获取当前 shell 脚本命令行中参数的总个数
企业案例:控制用户传的参数个数
[ $# -ne 2 ] && {
echo "must two"
exit 1
}
echo oldgirl
$$ 获取当前 shell 的进程号
$? 获取执行上一个指令的返回值(0为成功,非0为失败)
(1)应用案例:当系统中只能有某个脚本同时只能运行一个进程的时候
# pid.sh 脚本文件
[root@localhost scripts]# cat pid.sh
#!/bin/sh
pidPath=/tmp/a.pid
if [ -f "$pidPath" ]
then
kill -USR2 `cat $pidPath`
rm -f $pidPath
fi
# script pid write to $pidPath
echo $$ >$pidPath
sleep 300
# 查看进程
[root@localhost scripts]# ps -ef|grep pid.sh|grep -v grep
root 1758 1457 0 10:03 pts/0 00:00:00 sh pid.sh
4. 变量的数值计算
常用计算命令:(())、let、expr、bc(小数)、$[]
I. (()))用法
[root@localhost scripts]# ((a=1+2**3-4%3))
[root@localhost scripts]# echo $a
8
[root@localhost scripts]# b=$((1+2**3-4%3))
[root@localhost scripts]# echo $b
8
[root@localhost scripts]# echo $((3>2))
1
[root@localhost scripts]# echo $((3<2))
0
范例:一次计算一个(非混合运算),即传参传两个数,传一个计算符号,出结果。
[root@localhost scripts]# cat d.sh
echo $(($1$2$3))
[root@localhost scripts]# sh d.sh 3*2
6
II. let 用法
[root@localhost scripts]# i=2
[root@localhost scripts]# let i=i+8
[root@localhost scripts]# echo $i
10
[root@localhost scripts]# i=2
[root@localhost scripts]# i=i+8
[root@localhost scripts]# echo $i
i+8
III. expr 用法
[root@localhost scripts]# expr 2 + 2
4
[root@localhost scripts]# expr 2+2
2+2
[root@localhost scripts]# expr $[2*3]
6
[root@localhost scripts]# expr $[2/3]
0
IIII. read 用法
# -t timeout 设置输入等待的时间,单位默认为秒。
# -p prompt 设置提示信息
[root@localhost scripts]# read -t 5 -p "pls input:" a
pls input:1
[root@localhost scripts]# echo $a
1
第三章 分支与循环结构
1. if 条件句
# 单分支
if [条件]
then
指令
fi
# 双分支
if 条件
then
指令集
else
指令集
fi
# 多分支
if 条件
then
指令
elif 条件
then
指令
...
else
指令
fi
特殊写法:if [-f “$file1”]; then echo 1;fi 相当于: [-f “file1”] && echo 1
范例1:单分支 if 条件句两个整数比较大小。
[root@localhost scripts]# cat if-single.sh
#!/bin/sh
if [ 10 -lt 12 ]
then
echo "yes,10 is less than 12"
fi
范例2:使用 read 及脚本传参方式如何实现上述整数的比较?
#!/bin/sh
read -p "pls input two num:" a b
if [ $a -lt $b ];then
echo "yes,$a less than $b"
fi
if [ $a -eq $b ];then
echo "yes,$a equal $b"
fi
if [ $a -gt $b ];then
echo "yes,$a greater than $b"
fi
第四章 实例示范
1. 使用 for 循环在 /oldboy 目录下批量创建10个文件,名称依次为:
oldboy-1.html,oldboy-2.html,…,oldboy-10.html
[root@localhost oldboy]# cat /home/scripts/01.sh
[ ! -d /oldboy ] && mkdir -p /oldboy
for i in `seq 10`
do
touch /oldboy/oldboy-${i}.html
done
2. 用 for 循环实现将以上文件名中的 oldboy 全部改成 linux, 并且扩展名改成大写。要求:for 循环的循环体不能出现 oldboy字符串。
[root@localhost scripts]# cat 02.sh
#!/bin/sh
cd /oldboy
for f in `ls *.html`
do
mv $f `echo $f|sed 's#oldboy#linux#g'|sed 's#html#HTML#g'`
done
3. 批量创建 10 个系统账号 oldboy01-oldboy10 并设置密码(密码不能相同)。
#!/bin/sh
for n in `seq -w 10`
do
useradd oldboy$n&&\
echo "root$n"|passwd --stdin oldboy$n
done
4. 数组定义与增删改查
[root@localhost scripts]# array=(1 2 3)
[root@localhost scripts]# echo ${#array[@]}
3
[root@localhost scripts]# echo ${#array[*]}
3
[root@localhost scripts]# echo ${array[0]}
1