linux实验之shell编程基础
Posted 小阿宁的猫猫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux实验之shell编程基础相关的知识,希望对你有一定的参考价值。
这世间,青山灼灼,星光杳杳,秋风渐渐,晚风慢慢
shell编程基础
- 熟悉shell编程的有关机制,如标准流。
- 学习Linux环境变量设置文件及其内容
- 熟悉编程有关基础命令技巧和规则
- 掌握shell 程序执行的三种基本方式,注意调试shell程序的命令书写方式有什么不同?
- 使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub, b_sub子目录下的所有C程序文件及其目标文件的列表。
- 编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及格、及格60、中70、良80和优秀90等)。
- 为便于系统管理员对磁盘分配的管理,请编写一段B-shell程序,当文件系统/home占用空间改变时给出相应的信息提示。要求/home占用量在系统磁盘中为:
- 假设score.txt文件中保存了三个班级的学生的某门课程考试成绩,请编写一段shell程序计算每个班级的学生人数与平均分。
熟悉shell编程的有关机制,如标准流。
如果当前目录下有文件f1,但是没有f2,解释命令ls f1 f2 2>ef1 1>&2的运行结果。
1 . ls f1 f2 2>ef1 1>&2
(1)
0 表示 stdin , 标准输入 ; 1 表示 stdout , 标准输出 ; 2 表示 strerr , 标准错误输出
1>&2 表示 将标准输出重定向至标准错误输出; 2>&1 表示 将标准错误输出
(2) 所以这里是把ls f1 f2命令的报错信息写入ef1, 又把命令的输出的正常信息当成报错信息写入ef1
如果没有把结果重定向, 就是直接输出
学习Linux环境变量设置文件及其内容
根据实验系统查看/etc/profile,/etc/bashrc,/.bash_profile,/.bashrc等有关文件。
/etc/profile
在系统启动后第一个用户登录时运行,并从/etc/profile.d目录的配置文件中搜集shell的设置,使用该文件配置的环境变量将应用于登录到系统的每一个用户。
/etc/bashrc
(Ubuntu和Debian中是/etc/bash.bashrc)
在 bash shell 打开时运行,修改该文件配置的环境变量将会影响所有用户使用的bash shell。
/etc/environment
在系统启动时运行,用于配置与系统运行相关但与用户无关的环境变量,修改该文件配置的环境变量将影响全局。
~/.profile
当用户登录时执行,每个用户都可以使用该文件来配置专属于自己使用的shell信息。
~/.bashrc
当用户登录时以及每次打开新的shell时该文件都将被读取,不推荐在这里配置用户专用的环境变量,因为每开一个shell,该文件都会被读取一次,效率肯定受影响。
熟悉编程有关基础命令技巧和规则
如变量的命名,引用,位置变量及使用,输出语句及输出格式控制,输入语句和变量存储,从命令输出中提取字段值等。
##熟悉常见外部工具,如awk,sed,bc等的基本用法。
awk
逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,用于在无交互的情况下实现相当复杂的文本操作。
用法:
1 . 过滤并输出文件中符合条件的内容
awk 选项 ‘模式或条件 编辑指令’ 文件 1 文件 2 …
( 1 ) 按行输出文本
awk 'print' demo.txt //输出所有内容,等同于 cat demo.txt
awk 'print $0' demo.txt //输出所有内容,等同于 cat demo.txt
awk 'NR==1||NR==3print' demo.txt //输出第 1 行、第 3 行内容
awk '(NR>=1)&&(NR<=3)print' demo.txt //输出第 1~3 行内容
awk '(NR%2)==1print' demo.txt //输出所有奇数行的内容
awk '(NR%2)==0print' demo.txt //输出所有偶数行的内容
awk '/^root/print' /etc/passwd //输出以root 开头的行awk
awk '/nologin$/print' /etc/passwd //输出以 nologin 结尾的行
( 2 )按字段输出文本
awk 'print $3' test.txt //输出每行中(以空格或制表位分隔)的第 3 个字段
awk 'print $1,$3' test.txt //输出每行中的第 1、3 个字段
awk -F ":" '$2==""print' /etc/shadow //输出密码为空的用户的shadow 记录
awk 'BEGIN FS=":"; $2==""print' /etc/shadow //输出密码为空的用户的shadow 记录
awk -F ":" '$7~"/bash"print $1' /etc/passwd //输出以冒号分隔且第 7 个字段中包含/bash 的行的第 1 个字段
awk '($1~"nfs")&&(NF==8)print $1,$2' /etc/services //输出包含 8 个字段且第 1 个字段中包含 nfs 的行的第 1、2 个字段
awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin")print' /etc/passwd //输出第 7 个字段既不为/bin/bash 也不为/sbin/nologin 的所有行
2 . 从脚本中调用编辑指令,过滤并输出内容
awk -f 脚本文件 文件 1 文件 2 …
awk -F: '/bash$/print | "wc -l"' /etc/passwd //调用wc -l 命令统计使用 bash 的用户个数,等同于 grep -c "bash$" /etc/passwd
awk 'BEGIN while ("w" | getline) n++ ; print n-2' //调用w 命令,并用来统计在线用户数
awk 'BEGIN "hostname" | getline ; print $0' //调用hostname,并输出当前的主机名
sed
( 1 ) 输出符合条件的文本
sed -n 'p' demo.txt //输出所有内容
sed -n 'p;n' demo.txt //输出所有奇数行,n表示读入下一行
sed -n 'n;p' demo.txt //输出所有偶数行,n 表示读入下一行
sed -n '10,$n;p' demo.txt //输出第 10 行至文件尾之间的偶数行
sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围。
sed -n '/the/p' demo.txt //输出包含the 的行
sed -n '4,/the/p' demo.txt //输出从第 4 行至第一个包含 the 的行
sed -n '/^PI/p' demo.txt //输出以PI 开头的行
sed -n '/[0-9]$/p' demo.txt //输出以数字结尾的行
sed -n '/\\<wood\\>/p' demo.txt //输出包含单词wood 的行,\\<、\\>代表单词边界
( 2 ) 删除符合条件的文本
sed '1,3d' 1.txt #删除第1-3行
sed '/acb/d' 1.txt #删除所有包含acb的行
sed '/aaa/!d' 1.txt #删除不包含aaa的行
sed '/^abc/d' 1.txt #删除以abc开头的行
sed '/\\.$/d' demo.txt //删除以"."结尾的行
sed '/^$/d' demo.txt //删除所有空行
( 3 ) 替换符合条件的文本
sed 's/the/THE/' demo.txt //将每行中的第一个the 替换为 THE
sed 's/l/L/2' demo.txt //将每行中的第 2 个 l 替换为 L
sed 's/the/THE/g' demo.txt //将文件中的所有the 替换为 THE
sed 's/^/#/' demo.txt //在每行行首插入#号
sed '/the/s/^/#/' demo.txt //在包含the 的每行行首插入#号
sed '/the/s/o/O/g' demo.txt //将包含the 的所有行中的 o 都替换为 O
sed '3,5s/the/THE/g' demo.txt //将第3~5行中所有the替换为 THE
sed 's/$/NO/' demo.txt //在每行行尾插入字符串NO
( 4 ) 迁移符合条件的文本
在使用 sed 命令迁移符合条件的文本时,常用到以下参数.
- H:复制到剪贴板。
- g、G:将剪贴板中的数据覆盖/追加至指定行。
- w:保存为文件。
- r:读取指定文件。
- a:追加指定内容。
sed '/the/H;d;$G' test.txt //将包含the 的行迁移至文件末尾,;用于多个操作
sed '1,5H;d;17G' test.txt //将第 1~5 行内容转移至第 17 行后
sed '/the/w out.file' test.txt //将包含the 的行另存为文件 out.file
sed '/the/r /etc/hostname' test.txt //将文件/etc/hostname 的内容添加到包含 the 的每行以后
sed '3aNew' test.txt //在第 3 行后插入一个新行,内容为New
sed '/the/aNew' test.txt //在包含the 的每行后插入一个新行,内容为 New
sed '3aNew1\\nNew2' test.txt //在第 3 行后插入多行内容,中间的\\n 表示换行
sed '1,5H;d;17G' test.txt //将第 1~5 行内容转移至第 17 行后
bc
- +:加
- -:减
- *:乘
- /:除
- ^:指数
- %:求余数
- sqrt:开方
- ibase:输入进制
- obase:输出进制
- ;要计算多个结果用分号分隔
- scale:小数部分位数
比如:
-
3除以2保留3位小数:echo ‘scale=3; 3/2’ | bc
-
10进制的3转换为2进制:echo “obase=2;3” |bc
-
10进制的11转换为16进制:echo “obase=16;11” |bc
-
2进制转16进制:echo “obase=16;ibase=2;11” |bc
-
2进制转10进制:echo “obase=10;ibase=2;11” |bc
-
100开方: echo “sqrt(100)” |bc
-
10的3次方,10的2次方,3的5次方: echo “103;102;3^5” |bc
掌握shell 程序执行的三种基本方式,注意调试shell程序的命令书写方式有什么不同?
(1)输入重定向的执行方式
Shell从文件test中读取命令行并执行它们,
Shell执行到文件末尾就会终止执行
sh < test.sh
(2)脚本名文件执行
可以将参数值传递给文件中的命令,使shell程序可以处理更多的情况
sh test.sh [参数.]
(3)添加执行权限,直接进行执行
chmod u+x test.sh
./test.sh
(4)调试shell程序的命令
在脚本头部添加
set -euxo pipefail
或执行时传⼊参数
bash -euxo pipefail xxx.sh
使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub, b_sub子目录下的所有C程序文件及其目标文件的列表。
考虑如何验证实验结果。
用户注册目录: $HOME查看
#!/bin/bash
d="$HOME/a_sub $HOME/b_sub" #找到这两个目录
for i in $d
do
cd $i #然后进入目录
ls -l *.c #分别输出
done
编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及格、及格60、中70、良80和优秀90等)。
如果输入的数据不是合法的怎么处理?
11.sh
#!/bin/bash
while :
do
read -p "输入成绩:" s
case "$s" in
q|Q)
exit
;;
*)
if ! [[ "$s" =~ ^[0-9]+$ ]] ; then
echo "请输入数字"
continue
fi
if [ $s -ge 90 -a $s -le 99 ] ; then
echo "优秀"
fi
if [ $s -ge 80 -a $s -le 89 ] ; then
echo "良"
fi
if [ $s -ge 70 -a $s -le 79 ] ; then
echo "中"
fi
if [ $s -ge 60 -a $s -le 69 ] ; then
echo "及格"
fi
if [ $s -ge 0 -a $s -le 59 ] ; then
echo "不及格"
fi
;;
esac
done
为便于系统管理员对磁盘分配的管理,请编写一段B-shell程序,当文件系统/home占用空间改变时给出相应的信息提示。要求/home占用量在系统磁盘中为:
①小于50%时,提示“用户文件系统磁盘使用负荷量小”。
②大于50%,小于90%时,提示“用户文件系统磁盘使用负荷量正常”。
③大于等于90%时,提示“用户文件系统磁盘使用负荷量偏大。
思路:怎么获取磁盘的空间情况?注意题目是需要知道一个目录的空间占用情况,和磁盘的占用不是一个问题。
df -h /home > homespace1.txt
单独运行df和du命令,查看用户注册目录的空间使用情况,然后再根据此二命令的输出,决定编程的方法。
#!/bin/bash
df -h /home > homespace1.txt
#将/home目录占用磁盘空间的情况输出重定向到一个txt文件中去
s=`sed -n '2p' homespace1.txt`
#把homespace.txt文件里的第二行赋值给temp变量
#sed命令是利用脚本来处理文件
#-n:仅显示script处理后的结果
l=$s%'%'*
#从右往左,把第一次出现%的右边截掉,保留左边,因为%符号有特殊含义,所以加上单引号'%',把截取后的字符串片段先赋值给m变量
r=$l##*G
#从左往右,把字符串最后一个出现字符G的左边截掉,保留右边。这样就把占用空间百分比的数字给截取出来了,把它赋值给r变量
for i in $r
do
if [ $i -le 50 ] ; then
echo "用户文件系统磁盘使用负荷量小"
fi
if [ $i -ge 50 -a $i -le 90 ] ; then
echo "用户文件系统磁盘使用负荷量正常"
fi
if [ $i -ge 90 ] ; then
echo "用户文件系统磁盘使用负荷量偏大"
fi
done
假设score.txt文件中保存了三个班级的学生的某门课程考试成绩,请编写一段shell程序计算每个班级的学生人数与平均分。
学习读取文件的方法。
#!/bin/bash
class="class1 class2 class3"
for i in $class
do
total=`grep -F $i score.txt|wc -l`
average=`grep -F $i score.txt|awk -F: 'sum+=$3ENDprint ":",sum/NR'`
#在之前检索出来的一个班级的内容中截取第三列所在的内容,并进行累加得到sum,sum再除以内置变量NR(行数)就得到平均值了。
echo "$i班:$total人,平均分$average。"
done
如果数据文件的内容是3个班级5门不同课程的内容,程序应该怎么调整?
#!/bin/bash
class="class1 class2 class3"
for i in $class
do
total=`grep -F $i score1.txt|wc -l`
echo "$i班:$total人"
for j in 2 3 4 5 6 7
do
x=`sed -n '1p' score1.txt|awk -F" " 'print $'$j''`
#获取第一行的内容,读取科目,便于简化操作。
average=`grep -F $i score1.txt|awk -F" " 'sum+=$'$j'ENDprint sum/NR'`
echo "$i班$x平均分:$average"
done
done
linux基础学习-17-linux操作系统之Shell编程基础讲解
1,前言
1.1 为什么学习shell编程
Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具,Linux/UNIX系统的底层及基础应用软件的核心大部分涉及Shell脚本的内容。每一个合格的Linux系统管理员或运维工程师,都需要熟练的编写Shell脚本语言,并能够阅读系统及各类软件附带的Shell脚本内容。只有这样才能提升运维人员的工作效率,适应日益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础。
1.2 学好Shell编程所需的基础知识
- 能够熟练使用vim编辑器,熟悉SSH终端
- 有一定的Linux命令基础,至少需要掌握80个以上Linux常用命令,并能够熟练使用它。
- 要熟练掌握Linux正则表达式及三剑客命令(grep,sed,awk)
1.3 如何学好Shel编程
- 学好Shel编程的核心:多练-->多思考-->再练-->再思考,坚持如此循环即可!
- 新手大忌:不可拿来主义,可以模仿,但是要自己嚼烂了吃下去,否则会闹肚子。
- 格言:你觉得会了并不一定会了,你认为对的并不一定对的。
大家要勤动手,自行完成学习笔记和代码的书写。通过每一个小目标培养自己的兴趣以及成就感
2,Shell脚本入门
2.1 什么是Shell
- Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出屏幕返回给用户。
- 这种对话方式可以是:
1)交互的方式:从键盘输入命令,通过/bin/bash的解释器,可以立即得到shell的回应
2)非交互的方式:脚本
下图黄色部分就是命令解释器shell
Shell的英文意思是贝壳的意思,命令解释器Shell像一个贝壳一样包住系统核心。
Shell执行命令分为两种方式:
- 内置命令:如讲过的cd,pwd,exit和echo等命令,当用户登录系统后,shell以及内置命令就被系统载入内存,并且一直运行。
- 一般命令:如ls,磁盘上的程序文件-->调入-->执行命令
2.2 什么是Shell 脚本
当linux命令或语句不在命令行下执行(严格说,命令行也是shell),而是通过一个程序文件执行时,该程序就被称为Shell脚本或Shell程序
用户可以在Shell脚本中敲入一系列的命令及语句组合。这些命令,变量和流程控制语句等有机的结合起来就形成一个功能强大的Shell脚本。
首先先带领大家写一个清空/var/log/messages日志的脚本
我们需要先想明白几个问题:
1)日志文件在哪?
/var/log/messages
2)用什么命令可以清空文件?
> 重定向
3)写一个简单的shell脚本。
#!/bin/env bash
# -*- coding:utf-8 -*-
# author:Mr.chen
cd /var/log/
>messages
4)怎样执行脚本?[[email protected] ~]# sh /server/scripts/chensiqi.sh
有没有考虑到:
- 有没有脚本放在统一的目录
/server/scripts目录下
- 权限:用哪个用户执行文件
需要对用户做判断
-
清空错文件怎么办,该如何办?
-
错误提示:有没有成功知不知道?
-
脚本的通用性
范例:包含命令,变量和流程控制的清空/var/log/messages日志的shell脚本
[[email protected] ~]# mkdir -p /server/scripts #要有规范的存放脚本目录
[[email protected] ~]# vim /server/scripts/chensiqi.sh
[[email protected] ~]# cd /server/scripts/
[[email protected] scripts]# cat /server/scripts/clear_log.sh
#!/bin/env bash
# -*- coding:utf-8 -*-
# author:Mr.chen
LOG_DIR=/var/log
if [ $UID -ne 0 ] #root用户的UID是0
then
echo "Must be root to run this script"
exit 1 #退出脚本,返回值1
fi
cd $LOG_DIR 2>/dev/null || {
echo "Cannot chage to necessary directory."
exit 1
} #如果第一个语句执行失败,那么执行||后边的
cat /dev/null > messages && echo "Logs cleaned up." #打开一个空文件然后重定向日志文件做为清空处理
exit 0
清空日志的三种方法:
echo >test.log
>test.log
cat /dev/null >test.log
#清空内容,保留文件
小结:
- Shell就是命令解释器。==>翻译官
- Shell脚本==>命令放在脚本里
2.3,Shell脚本在运维工作中的作用地位
Shell脚本擅长处理纯文本类型的数据,而Linux中几乎所有的配置文件,日志文件等都是纯文本类型文件。
3,Shell脚本的建立和执行
3.1 Shell脚本的建立
推荐使用vim编辑器编辑脚本,可以事先做个别名。
[[email protected] scripts]# echo "alias vi=vim">>/etc/profile
[[email protected] scripts]# source /etc/profile
3.1.1脚本开头第一行
规范的Shell脚本第一行会指出由哪个程序(解释器)来执行脚本中的内容。在linux bash编程中一般为:
#!/bin/bash
或
#!/bin/sh
其中开头的“#!”又称为幻数,在执行Shell脚本的时候,内核会根据“#!”后的解释器来确定哪个程序解释脚本中的内容。注意:这一行必须在每个脚本顶端的第一行,如果不是第一行则为脚本注释行。
3.1.2 sh和bash的区别
[[email protected] scripts]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Dec 23 20:25 /bin/sh -> bash
#sh是bash的软链接,推荐标准写法#!/bin/bash
可以看一下系统自带的脚本的写法
head -1 /etc/init.d/*
3.1.3 bash版本
[[email protected] scripts]# bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
3.1.4 bash漏洞【破壳漏洞】
如果是比较老的系统,需要注意shell的版本太低,有漏洞,需要升级shell
[[email protected] scripts]# yum -y update bash
#验证方法
[[email protected] scripts]# env x=‘(){ :;};echo be careful‘ bash -c "echo this is a test"
this is a test
如果返回2行
be careful
this is a test
这样的结果的话,请尽快升级
3.1.5 不同语言脚本的开头写法
#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/tcl
#!/usr/bin/expect
#!/usr/bin/perl
#!/usr/bin/env python
如果脚本开头不指定解释器,就要用对应的解释器执行脚本。例如bash test.sh和python.test.py
要求:养成一个好习惯,开头加上相应的解释器标识。
3.1.6 脚本注释
在Shell脚本中,跟在#后面的内容表示注释。注释部分不会被执行,仅给人看。注释可以自成一行,也可以跟在命令后面,与命令同行。要养成写注释的习惯,方便自己与他人。
最好不用中文注释,因为在不同字符集的系统会出现乱码。
3.2 Shell脚本的执行
3.2.1 Shell脚本执行的四种方式
1)bash scripts-name或sh script-name(推荐使用)
这种方法是当脚本本身没有可执行权限时常使用的方法。
2)path /script-name 或./scripts-name(全路径或当前路径执行脚本)
这种方法首先需要给脚本文件可执行权限。
3)source scripts-name或. scripts-name #注意“.”点号,且点号后有空格。
source 或.在执行这个脚本的同时,可以将脚本中的函数和变量加载到当前Shell。不会产生子shell。又有点像nginx的include功能。
3.3 Shell脚本开发的规范和习惯
1)开头指定脚本解释器
2)开头加版本版权等信息,可配置~/.vimrc文件自动添加
3)脚本不要用中文注释,尽量用英文注释
4)脚本以.sh为扩展名
5)放在统一的目录
6)代码书写优秀习惯
a,成对的内容一次性写出来,防止遗漏,如[],‘‘,""等
b,[]两端要有空格,先输入[]退格,输入2个空格,再退格写。
c,
流程控制语句一次书写完,再添加内容。
if 条件
then
内容
fi
d,通过缩进让代码易读
f,脚本中的引号都是英文状态下的引号,其他字符也是英文状态。
好的习惯可以让我们避免很多不必要的麻烦,提高工作效率。
4,Shell环境变量
4.1 什么是变量
变量就是用一个固定的字符串(也可能是字符数字等的组合),替代更多更复杂的内容,这个内容里可能还会包含变量和路径,字符串等其他内容。变量的定义是存在内存中。
x=1
y=2
4.2 变量类型
变量分为两类:
1)环境变量(也可称为全局变量);可以在创建他们的Shell及派生出来的子shell中使用。环境变量又可以分为自定义环境变量和bash内置的环境变量。
2)局部变量(普通变量):只能在创建他们的shell函数或shell脚本中使用,还记得前面的$user?我们创建的一般都是普通变量。
4.2.1 环境变量
- 环境变量用于定义Shell的运行环境,保证Shell命令的正确执行,Shell通过环境变量来确定登录用户名,命令路径,终端类型,登录目录等,所有的环境变量都是全局变量,可用于所有子进程中,包括编辑器,shell脚本和各类应用。但crond计划任务除外,还需要重新定义环境变量。
- 环境变量可以在命令行中设置,但用户退出时这些变量值也会丢失,因此最好在用户家目录下的.bash_profile文件中或全局配置/etc/bashrc,/etc/profile文件或者/etc/profile.d/目录中定义。将环境变量放入profile文件中,每次用户登录时这些变量值都将被初始化。
- 通常,所有环境变量均为大写。环境变量应用于用户进程前,都应该用export命令导出。例如:export chensiqi=1
- 有一些环境变量,比如HOME,PATH,SHELL,UID,USER等,在用户登录之前就已经被/bin/login程序设置好了。通常环境变量定义并保存在用户家目录下的.bash_profile或/etc/profile文件中。
#显示环境变量
[[email protected] scripts]# echo $HOME
/root
[[email protected] scripts]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[[email protected] scripts]# echo $SHELL
/bin/bash
[[email protected] scripts]# echo $UID
0
[[email protected] scripts]# echo $USER
root
[[email protected] scripts]# env #查看系统环境变量
HOSTNAME=chensiqi1
SELINUX_ROLE_REQUESTED=
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=500
SSH_CLIENT=192.168.197.1 49592 22
SELINUX_USE_CURRENT_RANGE=
OLDPWD=/root
SSH_TTY=/dev/pts/1
LC_ALL=C
USER=root
#中间省略部分内容....
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/server/scripts
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
CVS_RSH=ssh
SSH_CONNECTION=192.168.197.1 49592 192.168.197.133 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=/bin/env
#当前终端变量
[[email protected] scripts]# echo $PS1
[\[email protected]\h \W]\$
4.2.1 局部变量
定义局部变量
局部变量在用户当前的shell生存期的脚本中使用。例如,局部变量chensiqi取值为chensiqi098,这个值只在用户当前shell生存期中有意义。如果在shell中启动另一个进程或退出,局部变量chensiqi值将无效。
普通字符串变量定义
变量名=value
变量名=‘value’
变量名=“value”
shell中变量名及变量内容的要求
-
一般是字母,数字,下划线组成,且以字母开头。如chensiqi,chensiqi123,chensiqi-training。变量的内容,可以使用单引号或双引号印起来,或不加引号。
-
虽然变量可以以下划线开头,但类似这种变量都是比较特殊的,都是系统自己用的。我们尽量少用。
[[email protected] scripts]# _123=eeee
[[email protected] scripts]# echo $_123
eeee
普通字符串变量定义测试
[[email protected] scripts]# a=192.168.1.2
[[email protected] scripts]# b=‘192.168.1.2‘
[[email protected] scripts]# c="192.168.1.2"
[[email protected] scripts]# echo "a=$a"
a=192.168.1.2
[[email protected] scripts]# echo "b=$b"
b=192.168.1.2
[[email protected] scripts]# echo "c=${c}"
c=192.168.1.2
[[email protected] scripts]# a=192.168.1.2-$a
[[email protected] scripts]# b=‘192.168.1.2-$a‘
[[email protected] scripts]# c="192.168.1.2-$a"
[[email protected] scripts]# echo "a=$a"
a=192.168.1.2-192.168.1.2
[[email protected] scripts]# echo "b=$b"
b=192.168.1.2-$a
[[email protected] scripts]# echo "c=${c}"
c=192.168.1.2-192.168.1.2-192.168.1.2
把一个命令做为变量
[[email protected] scripts]# ls
chensiqi.sh clear_log.sh
[[email protected] scripts]# CMD=`ls`
[[email protected] scripts]# echo $CMD
chensiqi.sh clear_log.sh
[[email protected] scripts]# CMD1=$(pwd)
[[email protected] scripts]# echo $CMD1
/server/scripts
变量名=`ls` <==反引号
变量名=$(ls)
小结:
1)CMD=ls
的ls两侧的符号是键盘tab键上面的,不是单引号。
2)在变量名前加$,可以取得此变量的值,使用echo或printf命令可以显示变量的值,$A和$(A)写法不同,效果一样,推荐后面的写法。
3)${WEEK}DAY若变量和其他字符组成新的变量就必须给变量加上大括号{}.
4)养成将所有字符串变量用双引号括起来使用的习惯,减少编程遇到的怪异错误。“$A”和“${A}”
4.3 变量名及变量内容定义小结
-
变量名只能由字母,数字,下划线组成,且以字母开头。
-
规范的变量名写法定义:见名知意
a,ChensiqiAge=1 <==每个单词首字母大写
b,chensiqi_age=1 <==每个单词之间用“-”
c,chensiqiAgeSex=1 <==驼峰语法:首个单词字母小写,其余单词首字母大写 - =号的知识,a=1中的等号是赋值的意思,比较是不是相等为“==”
-
打印变量,变量名前接$符号,变量名后接字符的时候,要用大括号括起来
[[email protected] ~]# word="big"
[[email protected] ~]# echo ${word}ger
bigger
[[email protected] ~]# echo $wordger
[[email protected] ~]#
- 注意变量内容引用方法,一般为双引号,简单连续字符可以不加引号,希望原样输出,使用单引号。
- 变量内容是命令,要用反引号``或者$()把变量括起来使用
5,Shell特殊变量
5.1 位置变量
$0 获取当前执行的shell脚本的文件名,如果执行脚本带路径那么就包括脚本路径。
$n 获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9用大括号括起来{10},参数以空格隔开。
$# 获取当前执行的shell脚本后面接的参数的总个数
$0 获取当前执行的shell脚本的文件名,包括路径
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
echo $0
[[email protected] scripts]# sh chensiqi.sh
chensiqi.sh
[[email protected] ~]# sh /server/scripts/chensiqi.sh
/server/scripts/chensiqi.sh
#参观系统脚本使用$0
[[email protected] ~]# grep -i usage /etc/init.d/crond
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
[[email protected] ~]# /etc/init.d/crond
Usage: /etc/init.d/crond {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
$n $1 $2...$n命令脚本后面的参数的内容$1第一个参数$2是第二个参数....
[[email protected] scripts]# echo \${1..15}
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
[[email protected] scripts]# sh chensiqi.sh {a..z}
chensiqi.sh
a b c d e f g h i j k l m n o
$# 获取当前shell命令行中参数的总个数,用于判断传参的参数个数是否符合要求
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo $#
[[email protected] scripts]# sh chensiqi.sh
chensiqi.sh
0
[[email protected] scripts]# sh chensiqi.sh ee tt
chensiqi.sh
ee tt
2
5.2 进程状态变量
$? 获取执行上一个指令的返回值(0为成功,非零为失败)
查找方法man bash,然后搜索Special Parameters
5.2.1 $?测试
[[email protected] scripts]# echo $?
0
[[email protected] scripts]# cd /rrr
-bash: cd: /rrr: No such file or directory
[[email protected] scripts]# echo $?
1
$?返回值参考
0 表示运行成功
2 权限拒绝
1~125 表示运行失败,脚本命令,系统命令错误或参数传递错误;
126 找到该命令,但无法执行
127 未找到要运行的命令
128 命令被系统强制结束
生产环境:
1)用于判断命令,脚本或函数等程序是否执行成功。
2)若在脚本中调用执行“exit数字”,则会返回这个数字给“$?”变量
3)如果在函数中使用“return 数字”,则会以函数返回值的形式传给“$?”.
#!/bin/bash
/etc/init.d/network restart >/dev/null 2>&1
if [ $? -ne 0 ]
then
echo "Mynetwork is bad!"
exit 1
fi
6,变量的数值计算
6.1 (())用法(常用于简单的整数运算)
算数运算符号
运算符 | 意义 |
---|---|
++ -- | 增加及减少,可前置也可放在结尾 |
+ - ! ~ | 一元运算的正负号,非,逻辑与位的取反 |
* / % | 乘法,除法,取余 |
+ - | 加法,减法 |
< <= > >= | 比较符号 |
== 1+= | 相等,不相等 |
<< >> | 向左移动,向右移动 |
& | 位的AND |
^ | 位的异或 |
| | 位的或 |
&& | 位的AND |
|| | 位的OR |
?: | 条件表达式 |
= += -= *=等 | 赋值运算符 |
** | 幂运算 |
使用方法:
[[email protected] scripts]# ((a=1+2**3-4%3))
[[email protected] scripts]# echo $a
8
[[email protected] scripts]# b=$((1+2**3-4%3))
[[email protected] scripts]# echo $b
8
[[email protected] scripts]# echo $((1+2**3-4%3))
8
小结:
1)“(())”在命令行执行时不需要$符号,但是输出需要$符号
2)“(())”里所有字符之间有无或多个空格没有任何影响
一个比较绕的知识点:
[[email protected] scripts]# a=8
[[email protected] scripts]# echo $a
8
[[email protected] scripts]# echo $((a+=1)) #相当于a=a+1
9
[[email protected] scripts]# echo $((a++)) #a在前,先输出a的值,在加1
9
[[email protected] scripts]# echo $a
10
[[email protected] scripts]# echo $((a--))
10
[[email protected] scripts]# echo $a
9
[[email protected] scripts]# echo $((++a))
10
[[email protected] scripts]# echo $a
10
[[email protected] scripts]# echo $((--a))
9
[[email protected] scripts]# echo $a
9
记忆方法:++,--
变量a在前,表达式的值为a,然后a自增或自减,变量a在符号后,表达式值自增或自减,然后a值自增或自减。
数值判断:
[[email protected] scripts]# echo $((3>2))
1
[[email protected] scripts]# echo $((3<2))
0
6.2 练习:实现一个计算器
结合前边的知识:
方法一:
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
echo $(($1))
[[email protected] scripts]# sh calculator.sh 3+2
5
[[email protected] scripts]# sh calculator.sh 3**2
9
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
echo $(($1$2$3))
[[email protected] scripts]# sh calculator.sh 3 - 2
1
方法二:传参并计算
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
a=6
b=2
echo "a-b =$(($a - $b))"
echo "a+b =$(($a + $b))"
echo "a*b =$(($a * $b))"
echo "a/b =$(($a / $b))"
echo "a**b =$(($a ** $b))"
echo "a%b =$(($a % $b))"
[[email protected] scripts]# sh calculator.sh
a-b =4
a+b =8
a*b =12
a/b =3
a**b =36
a%b =0
#传参数
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
a=$1 #不需要把后面的$a,$b都改
b=$2
echo "a-b =$(($a - $b))"
echo "a+b =$(($a + $b))"
echo "a*b =$(($a * $b))"
echo "a/b =$(($a / $b))"
echo "a**b =$(($a ** $b))"
echo "a%b =$(($a % $b))"
[[email protected] scripts]# sh calculator.sh 3 8
a-b =-5
a+b =11
a*b =24
a/b =0
a**b =6561
a%b =3
6.2 $[]的用法
[[email protected] scripts]# echo $[2+3]
5
[[email protected] scripts]# echo $[2*3]
6
7,脚本中定义变量
7.1 脚本中直接赋值
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
a=6
b=2
echo "a-b =$(($a - $b))"
echo "a+b =$(($a + $b))"
echo "a*b =$(($a * $b))"
echo "a/b =$(($a / $b))"
echo "a**b =$(($a ** $b))"
echo "a%b =$(($a % $b))"
7.2 命令行传参
[[email protected] scripts]# cat calculator.sh
#!/bin/env bash
a=$1 #不需要把后面的$a,$b都改
b=$2
echo "a-b =$(($a - $b))"
echo "a+b =$(($a + $b))"
echo "a*b =$(($a * $b))"
echo "a/b =$(($a / $b))"
echo "a**b =$(($a ** $b))"
echo "a%b =$(($a % $b))"
8,条件测试
什么是条件测试呢?
简单理解,判断某些条件是否成立,成立执行一种命令,不成立执行另外一种命令。
8.1 条件测试语法
格式:[ <测试表达式> ] 大家要掌握着一种,注意测试表达式两边要留空格
8.2 测试表达式
好习惯:先敲一对[],然后退格输入2个空格[],最后再回退一个空格开始输入[ -f file ]
[[email protected] ~]# [ -f /etc/hosts ] && echo 1 || echo
1
[[email protected] ~]# [ -f /etc/hosts1 ] && echo 1 || echo 0
0
[[email protected] ~]# [ ! -f /etc/hosts1 ] && echo 1 || echo 0
1
#在做测试判断时,不一定用上面的方法,用下面的写一半方法更简洁
[[email protected] ~]# [ -f /etc/hosts ] && echo 1
1
[[email protected] ~]# [ -f /etc/hosts1 ] || echo 0
0
#系统脚本
[[email protected] ~]# vi /etc/init.d/nfs
....
[ -x /usr/sbin/rpc.nfsd ] || exit 5
[ -x /usr/sbin/rpc.mountd ] || exit 5
[ -x /usr/sbin/exportfs ] || exit 5
8.3 常用文件测试操作符号
常用文件测试操作符号 | 说明 |
---|---|
-f文件,英文file | 文件存在且为普通文件则真,即测试表达式成立 |
-d文件,英文directory | 文件存在且为目录文件则真,即测试表达式成立 |
-s文件,英文size | 文件存在且文件大小不为0则真,即测试表达式成立。 |
-e文件,英文exist | 文件存在则真,即测试表达式成立。只要有文件就行,区别-f |
-r文件,英文read | 文件存在且可读则真,即测试表达式成立 |
-w文件,英文write | 文件存在且可写则真,即测试表达式成立 |
-x文件,英文executable | 文件存在且可执行则真,即测试表达式成立。 |
-L文件,英文link | 文件存在且为链接文件则真,即测试表达式成立 |
f1 -nt f2,英文newer than | 文件f1比文件f2新则真,即测试表达式成立,根据文件修改时间计算。 |
f1 -ot f2,英文older than | 文件f1比文件f2旧则真,即测试表达式成立,根据文件修改时间计算 |
8.4 字符串测试操作符
字符串测试操作符的作用:比较两个字符串是否相同,字符串长度是否为零,字符串是否为NULL。Bash区分零长度字符串和空字符串。
|常用字符串测试操作符|说明|
|--|--|
|-z "字符串"|若串长度为0则真,-z理解为zero|
|-n “字符串”|若串长度不为0则真,-n理解为no zero|
|“串1”=“串2”|若串1等于串2则真,可以使用“==”代替“=”|
|“串1”!="串2"|若串1不等于串2则真,但不能使用“!==”代替“!=”|
特别注意,以上表格中的字符串测试操作符号务必要用“”引起来。[ -z "$string"]字符串比较,比较符号两端最好有空格,参考系统脚本。
[ "$password" = "john" ]
提示:
[,"password",=,"join",]之间必须存在空格
[[email protected] ~]# sed -n ‘30,31p‘ /etc/init.d/network
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 6
8.5 整数二元比较操作符
在[]中使用的比较符 | 说明 |
---|---|
-eq | equal等于 |
-ne | not equal不等于 |
-gt | greater than大于 |
-ge | greater equal大于等于 |
-lt | less than小于 |
-le | less equal小于等于 |
在[]中可以用>和<,但需要用\转义,虽然不报错,但结果不对。但还是不要混用!
8.6 逻辑操作符
在[]中使用的逻辑操作符 | 说明 |
---|---|
-a | 与and,两端都为真则真 |
-o | 或or,有一个真就真 |
! | 非not,相反则为真 |
小结:
1)多个[]之间的逻辑操作符是&&或||
2)&&前面成功执行后面
3)||前面不成功执行后面
8.7 其他
有的时候用[]比if要简单
[ -f "$file" ] && echo 1 || echo 0
if [ -f "file" ];then echo 1;else echo 0;fi
9,if条件语句
9.1 if单分支条件语句
if [ 条件 ]
then
指令
fi
或
if [ 条件 ];then
指令
fi
提示:分号相当于命令换行,上面两种语法等同
特殊写法:if [ -f "$file1" ];then echo 1;fi
相当于[-f "$file1" ] && echo 1
9.1.1 输入2个数字,比较大小
#!/bin/bash
#no1
if [ $# -ne 2 ]
then
echo "USAGE $0 num1 num2"
exit 1
fi
a=$1
b=$2
if [ $a -lt $b ];then
echo "yes,$a less than $b"
exit
fi
if [ $a -eq $b ];then
echo "yes,$a equal $b"
exit
fi
if [ $a -gt $b ];then
echo "yes,$a greater than $b"
exit
fi
9.1.2 如果/server2/scripts下面有if3.sh就输出if3.sh到屏幕,如果没有自动创建
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
path=/server2/scripts
file=if3.sh
if [ ! -d $path ]
then
mkdir -p $path
echo "directory is not exsist!"
fi
if [ ! -f $path/$file ]
then
touch $path/$file
echo "file is not exsist!"
else
echo "file is exsist!"
fi
9.2 if 双分支条件语句
if [ 条件 ]
then
指令
else
指令
fi
特殊写法:if [ -f "$file1" ];then echo 1;else echo 0;fi
相当于[ -f "file1" ] && echo 1 ||echo 0
9.2.1 如果/server2/scripts下面有if3.sh就输出if3.sh到屏幕,如果没有就自动创建
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
file=/server2/scripts/if3.sh
path=`dirname $file`
if [ -f $file ];then
cat $file
exit 0
else
if [ ! -d $path ];then
mkdir -p $path
echo "$path is not exist,already created it."
echo "1234" >> $file
fi
if [! -f $file ];then
echo "1234" >> $file
echo "$file is not exist,already created it."
fi
fi
9.3 多分支if语句
if [ 条件1 ];then
指令1
elif [ 条件2 ];then
指令2
elif [ 条件3 ];then
指令3
elif [ 条件4 ];then
指令4
else
指令n
fi
9.3.1 判断两个整数大小
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
if [ $# -ne 2 ];then
echo "USAGE $0 num1 num2"
exit 1
else
num1=`echo $1 | sed ‘s#[0-9]##g‘`
num2=`echo $2 | sed ‘s#[0-9]##g‘`
fi
if [ ${#num1} -eq 0 -a ${#num2} -eq 0 ];then
if [ $1 -lt $2 ];then
echo "$1 less than $2!"
exit
elif [ $1 -eq $2 ];then
echo "$1 equal $2!"
exit
else
echo "$1 great than $2!"
exit
fi
else
echo "num1 num2 must be digit!"
fi
10 case 结构条件句
10.1 case结构条件句语法
case "字符串变量" in
值1)
指令1
;;
值2)
指令2
;;
*)
指令
esac
注意:case语句相当于一个if的多分支结构语句
值1的选项
apple)
echo -e "@RED_COLOR apple $RES"
;;
也可以这样写,输入2种格式找同一个选项
apple|APPLE)
echo -e "$RED_COLOR apple $RES"
;;
case 语句小结
1)case语句就相当于多分支的if语句。case语句的优势是更规范,易读。
2)case语句适合变量的值少,且为固定的数字或字符串集合。
3)系统服务启动脚本传参的判断多用case语句
10.2 给指定文本加颜色
以传参为例,在脚本命令行传2个参数,给指定内容(第一个参数)加指定颜色(第二个参数)
11 循环语句(while/for)
11.1 循环语句语法
11.1.1 while条件语句
while 条件
do
指令
done
11.1.2 for循环结构语法
for 变量名 in 变量取值列表
do
指令...
done
11.2 while语句
休息命令:sleep 1 休息一秒,usleep 1000000休息1秒单位微妙
11.2.1 守护进程
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
while true
do
uptime >> /var/log/uptime.log
sleep 2
done
#while true 表示条件永远为真,因此会一直运行,像死循环一样。
[[email protected] scripts]# cat /var/log/uptime.log
23:01:57 up 8:33, 2 users, load average: 0.04, 0.03, 0.05
23:01:59 up 8:33, 2 users, load average: 0.04, 0.03, 0.05
23:02:01 up 8:33, 2 users, load average: 0.04, 0.03, 0.05
11.2.2 从1加到100
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
i=1
sum=0
while [ $i -lt 100 ]
do
((sum=sum+i))
((i++))
done
echo $sum
11.2.3 倒计时
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
i=10
while [ $i -gt 0 ]
do
echo $i
sleep 1
((i--))
done
11.3 防止脚本执行中断的方法
1)sh while01.sh & #放在后台执行
2)screen 分离 ctrl+a+d 查看screen -ls进入screen -r num
3)nohup while01.sh &
11.4 for循环语句
11.4.1 打印列表元素
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
for i in 5 4 3 2 1 #用空格隔开
do
echo $i
done
[[email protected] scripts]# sh chensiqi.sh
5
4
3
2
1
[[email protected] scripts]# for i in {5..1};do echo $i;done
5
4
3
2
1
[[email protected] scripts]# echo 10.1.1.{1..10}
10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4 10.1.1.5 10.1.1.6 10.1.1.7 10.1.1.8 10.1.1.9 10.1.1.10
[[email protected] scripts]# for i in `seq 5 -1 1`;do echo $i;done
5
4
3
2
1
#循环执行命令n次
[[email protected] scripts]# for i in `seq 100`;do curl -I baidu.com;done
11.4.2 开机启动项优化
[roo[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
LANG=en
for i in `chkconfig --list|grep "3:on"|awk ‘{print $1}‘`
do
chkconfig $i off
done
for name in sshd rsyslog crond network sysstat
do
chkconfig $name on
done
11.4.3 在/chensiqi目录批量创建文件
#!/bin/bash
Path=/chensiqi
[ -d "$Path" ] || mkdir -p $Path
for i in `seq 10`
do
touch $Path/chensiqi_$i.html
done
11.4.4 批量改名
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
$Path=/chensiqi
[ -d "$Path" ] || mkdir -p $Path
for file in `ls $Path`
do
mv $file `echo $file|sed -r ‘s#chensiqi(.*).html#linux\1.HTML#g‘`
done
11.4.5 批量创建用户并设置密码
[[email protected] scripts]# cat chensiqi.sh
#!/bin/bash
User=chensiqi
Path=/tmp
for user in ${User}{01..10}
do
useradd $user >/dev/null 2>&1
if [ ! $? -eq 0 ];then
echo "$user created faile!"
echo "scripts begin to rollback!"
for i in ${User}{01..10}
do
userdel -r $i >/dev/null 2>&1
[ $? -eq 0 ] || exit 1
done
echo >$Path/user_passwd
exit 1
else
passWD=`echo $RANDOM|md5sum|cut -c1-8`
[ -d $Path ] || mkdir $Path
echo $passWD | passwd --stdin $user
echo "$user:$passWD">>$Path/user_passwd
fi
done
11.4.6 获取当前目录下的目录名做为变量列表打印输出
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
Path=`pwd`
echo $Path
for filename in `ls`
do
[ -d ${Path}/${filename} ] && echo $filename
done
11.4.7 九九乘法表
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
for ((i=1;i<10;i++))
do
for ((j=1;j<=i;j++))
do
echo -n "$i * $j = $((i*j))"
echo -n " "
done
echo " "
done
[[email protected] ~]# sh /server/scripts/chensiqi.sh
1 * 1 = 1
2 * 1 = 2 2 * 2 = 4
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16
5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25
6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36
7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49
8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64
9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81
11.5 各种语句小结
1)while循环的特长是执行守护进程以及我们希望循环不退出持续执行,用于频率小于1分钟循环处理(crond),其他的while循环几乎都可以被for循环替代。
2)case语句可以被if语句替换,一般在系统启动脚本传入少量固定规则字符串用case语句,其他普通判断多用if
3)一句话,if,for语句最常用,其次while(守护进程),case(服务启动脚本)
11.6 获取随机数的几种方法。
11.6.1 通过系统环境变量$RANDOM
[[email protected] ~]# echo $RANDOM
6178
[[email protected] ~]# echo $RANDOM
30890
[[email protected] ~]# echo $((RANDOM%9)) #输出0~9之间随机数
2
[[email protected] ~]# echo $((RANDOM%9))
[[email protected] ~]# echo $((RANDOM%9))$((RANDOM%9)) #输出00~99 随机数
64
[[email protected] ~]# echo $((RANDOM%9))$((RANDOM%9)) #输出00~99岁?随机数
10
[[email protected] ~]# echo $((RANDOM%9))$((RANDOM%9)) #输出00~99岁?随机数
51
[[email protected] ~]# echo $RANDOM|md5sum #随机数长短不一,可以用md5sum命令统一格式化
599e328a94329684ce5c92b850d32f26 -
11.6.2 通过openssl产生
[[email protected] ~]# openssl rand -base64 8
aND8WMRM6vQ=
[[email protected] ~]# openssl rand -base64 8
RsRdRq/9vi4=
[[email protected] ~]# openssl rand -base64 8|md5sum
b1108cafbc2291392e41d2c914360138 -
[[email protected] ~]# openssl rand -base64 10
1frkA2kIJODxqQ==
11.6.3 通过时间获得随机数
[[email protected] ~]# echo $(date +%N)
361599138
[[email protected] ~]# echo $(date +%N)
199271856
[[email protected] ~]# echo $(date +%t%N)
950526316
[[email protected] ~]# echo $(date +%t%N)
340140329
11.6.4 urandom
[[email protected] ~]# head /dev/urandom | cksum
621330951 2535
[[email protected] ~]# head /dev/urandom | cksum
404398617 2470
11.6.5 UUID
[r[email protected] ~]# cat /proc/sys/kernel/random/uuid
8a6c5bbe-2d42-44ac-9ef1-3e7683a613e3
[[email protected] ~]# cat /proc/sys/kernel/random/uuid
c828c209-5b5f-4bc7-917c-678ed4215988
[[email protected] ~]# uuidgen
961dc354-81b2-4564-9b85-6095ed4bc7b5
11.7 break continue exit return
11.7.1 break continue exit 对比
break continue exit用于循环结构中控制虚幻(for,while,if)的走向
命令 | 说明 |
---|---|
break n | n表示跳出循环的层数,如果省略n表示跳出整个循环 |
continue n | n表示退出到第n层继续循环,如果省略n表示跳过本次循环,忽略本次循环剩余代码,进入循环的下一次循环 |
exit n | 退出当前shell程序,n为返回值,n也可以省略,在下一个shell里通过$?接收这个n值 |
return n | 用在函数里,做为函数的返回值,用于判断函数执行是否正确。和exit一样,如果函数里有循环,也会直接退出循环,退出函数 |
11.7.2 break
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
for ((i=0;i<=5;i++))
do
[ $i -eq 3 ] && break
echo $i
done
echo "ok"
[[email protected] ~]# sh /server/scripts/chensiqi.sh
0
1
2
ok
11.7.3 continue
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
for ((i=0;i<=5;i++))
do
[ $i -eq 3 ] && continue
echo $i
done
echo "ok"
[[email protected] ~]# sh /server/scripts/chensiqi.sh
0
1
2
4
5
ok
11.7.4 exit
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
for ((i=0;i<=5;i++))
do
[ $i -eq 3 ] && exit 2
echo $i
done
echo "ok"
[[email protected] ~]# sh /server/scripts/chensiqi.sh
0
1
2
[[email protected] ~]# echo $?
2
11.7.5 return
[[email protected] ~]# cat /server/scripts/chensiqi.sh
#!/bin/bash
function xxxx {
for ((i=0;i<=5;i++))
do
[ $i -eq 3 ] && return 7
echo $i
done
echo "ok"
}
xxxx
echo $?
[[email protected] ~]# sh /server/scripts/chensiqi.sh
0
1
2
7
12,shell脚本的调试
- 使用dos2unix处理脚本
从windows编辑的脚本到Linux下需要使用这个命令
dos2unix windows.sh
- 使用echo命令调试
在变量读取或修改的前后假如echo $变量,也可在后面使用exit退出脚本,这样可以不用注释后边代码
- 利用bash的参数调试
sh [-nvx]
-n:不会执行该脚本,仅查询脚本语法是否有问题,并给出错误提示。可用于生产服务器那些只能执行一次不可逆的脚本。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示。(一般不用)
-x:将执行的脚本内容及输出显示到屏幕上,常用
shell脚本调试技巧小结:
1)要记得首先用dos2unix对脚本格式化
2)直接执行脚本根据报错来调试,有时报错不准确。
3)sh -x调试整个脚本,显示执行过程。
4)set -x和set +x调试部分脚本(在脚本中设置)
5)echo输出变量及相关内容,然后紧跟着exit退出,不执行后面程序的方式,一步步跟踪脚本,对于逻辑错误比较好用。
6)最关键的时语法熟练,编码习惯,编程思想,将错误扼杀在萌芽中,减轻调试负担,提高效率。
以上是关于linux实验之shell编程基础的主要内容,如果未能解决你的问题,请参考以下文章