Shell高级程序设计基础
一. 关于Shell
- shell是一个命令解释器,是介于操作系统kernel与用户之间的一个绝缘层。它也是一种强力的计算机语言,一个shell程序,被称为一个脚本,可以通过将系统调用、公共程序、工具、和编译过的二进制程序粘合在一起来建立应用。
- Shell脚本对于管理系统任务和其它的重复工作的例程来说,表现的非常好
二. Vi编辑器的使用
1. Vi编辑器的三种模式
- Command mode 命令模式
- Edit mode 编辑模式
- ex mode 复杂命令模式
2 . Vi编辑器常用命令
1、在文件中移动光标
h:向左移动一个字符
l:向右移动一个字符
k:向上移动一行
j:向下移动一行
^(即Shift+6):移动到当前行的开头处
$(即Shift+4):移动到当前行的结尾处
H(大写):使光标移动到屏幕的顶部
M(大写):使光标移动到屏幕的中间
L(大写):使光标移动到屏幕的底部
Ctrl+b:上滚一屏。
Ctrl+f:下滚一屏。
Ctrl+d:下滚半屏。
Ctrl+u: 上滚半屏。
2、插入文本
(1)添加:
●输入a后,在光标的右边插入文本
●输入A,在一行的结尾处添加文本
(2)插入:
●通过在命令模式下输入i,在光标的左边插入文本
●通过在命令模式下输入I,在行首插入文本
(3)插入新行:
●输入o,在当前光标位置下面打开一行
●输入O,在当前光标位置上面打开一行
3、撤消更改
(1)撤消前一个命令:在最后一个命令之后立即输入u来撤消该命令
(2)重复某个命令:“.”
(3)撤消对一行的更改:输入U来撤消你对一行所做的所有更改,这个命令只有在你没将光标移动到该行以外时才生效。
4、删除文本
(1)删除一个字符:
●为删除一个字符,需将光标放置在要删除的字符上并输入x
●为删除光标之前(其左边)的一个字符,需输入X
(2)删除一个词或词的部分内容:
●为删除一个词,需将光标放置到该词的开头并输入dw
●为删除词的部分内容,需将光标放置到该词要保存部分的右边。输入dw来删除该词余下的部分
(3)删除一行:将光标放置到该行的任意处并输入dd
(4)删除多行:ndd
(5)删除行的部分内容:将光标放置到该行要保存部分的右边,并输入D。为删除光标左边的所有内容,须将光标放置到该行要删除部分的右边,并输入d0(d-零)。
(6)删除到文件的结尾:为删除从当前行到文件结尾的所有内容,需输入dG
5、复制和移动文本
●复制一行命令:yy
●粘贴命令:p
●移动文本:先将要移动的部分用删除命令删除,然后再粘贴就可以了
●复制指定文件的内容 : r filename
6、查找一个字符串
●输入/,并在/后面输入要查找的串,然后按下回车
●输入“n”跳转到该串的下一个出现处
●输入“N”跳转到该串的上一个出现处
7、替换一个字符串
●在一行内替换头一个字符串old为新的字符串new :s/old/new
●在一行内替换所有的字符串old为新的字符串new :s/old/new/g
●在两行内替换所有的字符串old为新的字符串new :#,#s/old/new/g
●在文件内替换所有的字符串old为新的字符串new :%s/old/new/g
●进行全文替换时询问用户确认每个替换需添加c选项 :%s/old/new/gc
8、设置vi
●显示行号 :set number
●取消行号显示 :set nonumber
●设置显示用户模式 :set showmode
●设置文件只读 :set readonly
9、退出Vi
10、快捷键一览
3 . 激活脚本的三种方法
方法一:
- 脚本不必标示为可执行,但必须可读
- Bash在一个子shell中激活脚本
$ cat script1
date
$ bash script1
方法二:
- 用chmod来使脚本可执行,然后像运行命令一样运行脚本
- 脚本将在子shell中运行
$ chmod 755 ./script1
$ ./script1
方法三:
- 使用.(dot) 或者source命令在当前shell环境中执行脚本
- 例如,为了不重起而让环境变量修改立即生效——可以使用source或者dot命令 (例如 #source /etc/profile)
$ .script1
$ source script1
注意:在脚本的第一行加入如下语句
#!/bin/bash
- 脚本将总是在bash中运行,即使用户的默认shell是其它的shell
此时,使用dot在当前的shell中激活shell脚本不再可行了
4 . Shell脚本参数
1, 2,$3 指向每个参数- $#表示参数的个数
- $*表示所有参数的整体
例如:
如果有很多参数(例如,文件名),则可以用shift切换参数,例如:
三. Shell基本编程技术
- 条件循环判断语句
条件语句:
While do命令
For循环
例子:如何写个程序输出/home下所有的不够安全的文件?
for file in `find /home -perm 777`
do
echo Dangerous File Permissions on $file
done
2 . 特殊字符$
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
例子:
//看下面脚本执行以后各个变量的意义
# touch variable; vi variable
#!/bin/bash
echo “number:$#”
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@”
echo "show parm list:$*"
echo "show process id:$$”
echo "show precomm stat: $?"
//保存退出
//赋予脚本执行权限
# chmod +x variable
//执行脚本
# ./variable aa bb
number:2
scname:./variable
first:aa
second:bb
argume:aa bb
show parm list:aa bb
show process id:24544
show precomm stat:0
3 . 输入重定向
文件描述符:
重定向的例子:
4 . 标准Shell变量
$:当前shell的PID
PATH:用于搜索可执行程序的路径
PS1:主shell提示符
PS2:第二shell提示符
PWD: 当前工作目录
HOME:用户的主目录
LANG:用户的语言环境
5 . 命令替换
命令替换是指将命令的标准输出作为值赋给某个变量,bash Shell定义了两种形式进行命令的替换,两种形式的语法格式如下:
方式一: `Linux命令`
方式二: $(Linux命令)
例子:
注意:尽管
bash Shell中,反引号与$()在处理双反斜线符号时存在区别。
[root@CentOS6 tmp]#echo \\
[root@CentOS6 tmp]#\ #输出转义符
[root@CentOS6 tmp]#echo `echo \\`
[root@CentOS6 tmp]# #输出空白行
[root@CentOS6 tmp]#echo $(echo \\)
[root@CentOS6 tmp]#\ #输出单斜线
6 . 生成审计报告的例子
用法:
./Auditfilter ./audit0118.log
#!/bin/bash
# auditfilter
if [ $# != 1 ] #如果参数个数不为1,则显示当前命令的语法信息提示,并
then
echo “`basename $0` <audit_log>” #$0显示当前脚本的路径,而basename $0则显示当前脚本的名字
exit 1 #非正常退出
fi
if [ ! -f $1 ] #如果参数所指定的文件不存在,则也退出
then
echo "file does not exist"
exit 1
fi
host=$(hostname) #打印出当前的主机名称
# extract the date part of the filename for the report
report=$(basename $1) #basename $1和 $1相同
echo $report #显示报告的文件名称
# filename ie: audit0118.log
date_rep=$(echo $report | sed –e ‘s/audit//g’ -e ‘s/.log//g’) # -e多重编辑, 将管道输出中”audit”删除,将”.log”删除。本例中,将留下“0118”
echo "date is..."
echo $date_rep #结果应为0118
mth=$(echo $date_rep | cut -c 1,2) #取出月份,即01
echo "month is..."
echo $mth
day=$(echo $date_rep | cut -c 3,4) #取出日,即18
echo "day is..."
echo $day
Datex=$day$mth #重新规划日期的格式
# email list here
list="root"
mailit2()
{
sendmail -t <<mayday
To:$list
Subject:audit report on $host
Content-Type: text/html
Content-Transfer-Encoding: 7bit
<body>
<body bgcolor="#C0C0C0">
Generated: `date`
<br>
Date of Audit : $datex
<hr>
<br>
<pre>
$(cat $1)
</pre>
</body>
mayday
}
echo '$1 is...'
echo $1
# do header and join lines
# do header and join lines
# filter out
# filter out
awk '
!($1 ==“USER_SU” && $2 ==$10) && #为了排除用户su到自己
!($1==“USER_SU” && $2==“root” && $9==“su” && $10==“poppy”) && #为了不包含root用户(他通过su将用户id变成了poppy)
!($1==“PASSWORD_Change” && $2 == $10) && #为了忽略用户修改自己密码的事件
!($1==“USER_SU” && $10==“operator”) && #如果不关心用户su到某个特定用户
!($1=="USER_SU" && $10=="genrep1") &&
!/xntpd/ #要忽略包含字符串“xntpd”的所有记录 network time protocol daemon
END {print "\t\t\t\t--- end of report ---"}' $1 >$1.rep
# cat $1.rep
mailit2 $1.rep