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