key words: bash編程
轉(zhuǎn)自 這里
另一篇 詳解Bash命令行處理
bash編程教學(xué)實(shí)例
bash編程
--------------------------------------------------------------------------------
時(shí)間:2004/03/02 來源:不詳
Shell Script(bash)簡介
眾所皆知地,UNIX上以小工具著名,利用許多簡單的小工具,來完成原本需要大量軟體開發(fā)的工作,這一點(diǎn)特色,使得UNIX成為許多人心目中理想的系統(tǒng)平臺(tái)。
在眾多的小工具中,Shell Script算得上是最基本、最強(qiáng)大、運(yùn)用最廣泛的一個(gè)。它運(yùn)用圍之廣,不但從系統(tǒng)啟動(dòng)、程式編譯、定期作業(yè)、上網(wǎng)連線,甚至安裝整個(gè)Linux系統(tǒng),都可以用它來完成。
因?yàn)镾hell Script是利用您平日在使用的一些指令,將之組合起來,成為一個(gè)"程式"。如果您平日某些序列的指令下得特別頻繁,便可以將這些指令組合起來,成為另 一個(gè)新的指令。這樣,不但可以簡化并加速操作速度,甚至還可以干脆自動(dòng)定期執(zhí)行,大大簡化系統(tǒng)管理工作。
*************************
Bash(GNU Bourne-Again SHell)是許多Linux平臺(tái)的內(nèi)定Shell,事實(shí)上,還有許多傳統(tǒng)UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等, Shell Script大致都類同,當(dāng)您學(xué)會(huì)一種Shell以后,其它的Shell會(huì)很快就上手,大多數(shù)的時(shí)候,一個(gè)Shell Script通常可以在很多種Shell上使用。
這里我介紹您bash的使用方法。事實(shí)上,當(dāng)您"man bash"時(shí),就可以看到bash的說明書,不過對(duì)許多人來說,這份說明書猶如"無字天書"一樣難懂。這份文件,主要資料來源為"man bash",我加上一些實(shí)際日常的應(yīng)用例來說明。希望這樣能讓那些始終不得其門而入的人們,多多少少能有點(diǎn)概念。
教學(xué)例子
"Hello world" Shell Script
照傳統(tǒng)程式教學(xué)例,這一節(jié)介紹Shell Script的"Hello World"如何撰寫。
*************************
#!/bin/sh
# Filename : hello
echo "Hello world!"
*************************
大家應(yīng)該會(huì)注意到第一行的"#!/bin/sh"。在UNIX下,所有的可執(zhí)行Script,不管是那一種語言,其開頭都是"#!",例如Perl是 "#!/usr/bin/perl",tcl/tk是"#!/usr/bin/wish",看您要執(zhí)行的Script程式位置在那里。您也可以用"#! /bin/bash"、"#!/bin/tcsh"等等,來指定使用特定的Shell。
echo是個(gè)bash的內(nèi)建指令。
*************************
接下來,執(zhí)行hello這個(gè)script:
要執(zhí)行一個(gè)Script的方式有很多種。
*************************
第一種 : 將hello這個(gè)檔案的權(quán)限設(shè)定為可執(zhí)行。
[foxman@foxman bash]# chmod 755 hello
執(zhí)行
[foxman@foxman bash]# ./hello
hello world
*************************
第二種 : 使用bash內(nèi)建指令"source"或"."。
[foxman@foxman bash]# source hello
hello world
或
[foxman@foxman bash]# . hello
hello world
*************************
第三種 : 直接使用sh/bash/tcsh指令來執(zhí)行。
[foxman@foxman bash]# sh hello
hello world
或
[foxman@foxman bash]# bash hello
hello world
*************************
Bash執(zhí)行選項(xiàng)
*************************
-c string : 讀取string來當(dāng)命令。
-i : 互動(dòng)介面。
-s : 由stdin讀取命令。
- : 取消往后選項(xiàng)的讀取。
-norc : 不要讀~/.bashrc來執(zhí)行。
-noprofile : 不要讀/etc/profile、~/.bash_profile、~/.bash_login、~/.profile等等來執(zhí)行。
-rcfile filename : 執(zhí)行filename,而非~/.bashrc
-version : 顯示版本。
-quiet : 啟動(dòng)時(shí)不要哩唆。
-login : 確保bash是個(gè)login shell。
-nobraceexpansion : 不要用curly brace expansion({}符號(hào)展開)。
-nolineediting : 不用readline來讀取命令列。
-posix : 改采Posix 1003.2標(biāo)準(zhǔn)。
用于自動(dòng)備份的Shell Script
一個(gè)用于自動(dòng)備份的Shell Script
我們先前提到,可利用Shell Script搭配crond來作定期的工作。要作定期性的工作,在UNIX上,就是與crond的搭配運(yùn)用。
*************************
首先我們先來研究如何對(duì)系統(tǒng)進(jìn)行備份。
要對(duì)系統(tǒng)進(jìn)行備份,不外乎便是利用一些壓縮工具。在許多UNIX系統(tǒng)上,tar及gzip是de facto的資料交換標(biāo)準(zhǔn)。我們經(jīng)常可以看見一些tar.gz或tgz檔,這些檔案,被稱為tarball。當(dāng)然了,您也可以用bzip2、zip等等壓 縮工具來進(jìn)行壓縮,不必限定于gzip。但tar配合gzip是最普遍的,也是最方便的方式。
要將我們想要的資料壓縮起來,進(jìn)行備份,可以結(jié)合tar及gzip一起進(jìn)行。方式有很多種,最常用的指令是以下這一種:
tar -c file/dir ... | gzip -9 > xxxx.tar.gz
您也可以分開來做:
tar -r file/dir ... -f xxxx.tar
gzip -9 xxxx.tar
或
tar -r file/dir ... -f xxxx.tar
gzip -9 < xxxx.tar > xxxx.tar.gz
*************************
在解過Linux下檔案備份的基本知識(shí)后,我們來寫一個(gè)將檔案備份的Script。
#!/bin/sh
# Filename : backup
DIRS="/etc /var /your_directories_or_files"
BACKUP="/tmp/backup.tgz"
tar -c $DIRS | gzip -9 > $BACKUP
其中DIRS放的是您要備份的檔案及目錄,BACKUP是您的備份檔。可不要將/tmp放進(jìn)DIRS中,那樣做,您是在做備份的備份,可能將您的硬碟塞爆。
*************************
接下來測試
[foxman@foxman bash]# chmod 755 backup
[foxman@foxman bash]# ./backup
執(zhí)行完成后在/tmp就會(huì)有一個(gè)backup.tgz,里面儲(chǔ)存了您重要的資料。您可用
gzip -dc /tmp/backup.tgz | tar -vt
或
tar vtfz /tmp/backup.tgz
來看看里面的檔案列表。
要解開時(shí),可用以下指令來完成復(fù)原:
gzip -dc /tmp/backup.tgz | tar -xv
或
tar xvfz /tmp/backup.tgz
備份通常是僅備份系統(tǒng)通常最重要的部份,/etc可說是不可缺少的一部份。另外,看您系統(tǒng)中有那些重要的資料需要備份。通常來說,您沒有必要備份 /bin、/sbin、/usr/bin、/usr/sbin、/usr/X11R6/bin等等這些執(zhí)行檔目錄。只要備份您重要的檔案即可,別把整個(gè)硬 碟備份,那是蠻呆的動(dòng)作。
*************************
如果您有許多臺(tái)機(jī)器,可利用其中一臺(tái)任務(wù)較輕的內(nèi)部網(wǎng)路主機(jī),做為主要備份主機(jī)。將所有機(jī)器都自動(dòng)執(zhí)行備份,然后利用NFS/Coda/Samba等網(wǎng)路檔案系統(tǒng),將備份的資料放到該備份機(jī)器中,該機(jī)器則定時(shí)收取備份資料,然后您再由該機(jī)器中進(jìn)行一次備份。
這里是整個(gè)系統(tǒng)備份方案的圖示。
在您進(jìn)行之前,先解一下,系統(tǒng)中那些是要備份的,那些是不需要的。
*************************
新的backup
#!/bin/sh
HOSTNAME=`hostname`
DIRS="/etc /var /your_important_directory"
BACKUP="/tmp/$HOSTNAME.tgz"
NFS="/mnt/nfs"
tar -c $DIRS | gzip -9 > $BACKUP
mv -f $BACKUP $NFS
*************************
備份主機(jī)內(nèi)的Script : collect_backup
#!/bin/sh
NFS="/mnt/nfs"
BACKUP="/backup"
mv -f $NFS/*.tgz $BACKUP
在此,您不能夠?qū)⑺袀浞荻贾苯臃旁?mnt/nfs,這是危險(xiǎn)的。萬一任一臺(tái)機(jī)器不小心將/mnt/nfs所有內(nèi)容刪除,那么備份就會(huì)消失。因此,您需要將/mnt/nfs移到一個(gè)只有該備份主機(jī)可存取的目錄中。
*************************
當(dāng)這些個(gè)別的Script都測試好以后,接下來我們將他們放到crontab里面。找到您的crontab,它的位置可能在/var/spool/cron/crontabs/root、/etc/crontab、/var/cron/tabs/root。
在crontab中選擇以下之一加入(看您定期的時(shí)間):
Slackware : /var/spool/cron/crontabs/root
01 * * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每小時(shí)(太過火一點(diǎn))
30 16 * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每日16:30,下班前備份
30 16 * * 0 /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每周一16:30
0 5 1 * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每月一號(hào)5:0
RedHat/Debian : /etc/crontab
RedHat可直接將backup放入/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly。或采用如上加入/etc/crontab的方式:
有關(guān)crontab的用法,可查"man 5 crontab",在此不詳述。
備份主機(jī)的設(shè)定類同。
注意: 所有機(jī)器不要同時(shí)進(jìn)行備份,否則網(wǎng)路會(huì)大塞車。備份主機(jī)收取備份的時(shí)間要設(shè)為最后,否則會(huì)收不到備份資料。您可以在實(shí)作后,將時(shí)間間隔調(diào)整一下。
*************************
看看,兩個(gè)小小不到三行的Shell Script,配合cron這個(gè)定時(shí)工具。可以讓原本需要耗時(shí)多個(gè)小時(shí)的人工備份工作,簡化到不到十分鐘。善用您的想像力,多加一點(diǎn)變化,可你讓您的生活變得輕松異常,快樂悠哉。
檔案系統(tǒng)檢查
系統(tǒng)安全一向是大多數(shù)電腦用戶關(guān)心的事,在UNIX系統(tǒng)中,最重視的事,即系統(tǒng)中有沒有"木馬"(Trojan horse)。不管Trojan horse如何放進(jìn)來的,有一點(diǎn)始終會(huì)不變,即被放置木馬的檔案,其檔案日期一定會(huì)被改變,甚至?xí)衅渌臓顟B(tài)改變。此外,許多狀況下,系統(tǒng)會(huì)多出一些不 知名的檔案。因此,平日檢查整個(gè)檔案系統(tǒng)的狀態(tài)是否有被改變,將所有狀態(tài)有改變的檔案,以及目前有那些程式正在執(zhí)行,自動(dòng)報(bào)告給系統(tǒng)管理員,是個(gè)避免坐上 "木馬"的良方。
*************************
#!/bin/sh
# Filename : whatever_you_name_it
DIRS="/etc /home /bin /sbin /usr/bin /usr/sbin /usr/local /var /your_directory"
ADMIN="email@your.domain.com"
FROM="admin@your.domain.com"
# 寫入Sendmail的標(biāo)頭
echo "Subject: $HOSTNAME filesystem check" > /tmp/today.mail
echo "From: $FROM" >> /tmp/today.mail
echo "To: $ADMIN" >> /tmp/today.mail
echo "This is filesystem report comes from $HOSTNAME" >> /tmp/today.mail
# 報(bào)告目前正在執(zhí)行的程式
ps axf >> /tmp/today.mail
# 檔案系統(tǒng)檢查
echo "File System Check" >> /tmp/today.mail
ls -alR $DIRS | gzip -9 > /tmp/today.gz
zdiff /tmp/today.gz /tmp/yesterday.gz >> /tmp/today.mail
mv -f /tmp/today.gz /tmp/yesterday.gz
# 寄出信件
sendmail -t < /tmp/today.mail
然后把它放到一個(gè)不顯眼的地方去,讓別人找不到。
把它加入crontab中。
30 7 * * * /full_check_script_path/whatever_you_name_it 1> /dev/null 2> /dev/null #上班前檢查
有些檔案是固定會(huì)更動(dòng)的,像/var/log/messages、/var/log/syslog、/dev/ttyX等等,不要太大驚小怪。
控制圈for
演示了幾個(gè)簡單的Shell Script,相信您應(yīng)該對(duì)Shell Script有點(diǎn)概念了。現(xiàn)在我們開始來仔細(xì)研究一些較高等的Shell Script寫作。一些進(jìn)一步的說明,例如"$"、">"、"<"、">>"、"1>"、"2>"符號(hào)的使用,會(huì)在 稍后解釋。
*************************
for name [ in word; ] do list ; done
控制圈。
word是一序列的字,for會(huì)將word中的個(gè)別字展開,然后設(shè)定到name上面。list是一序列的工作。如果[in word;]省略掉,那么name將會(huì)被設(shè)定為Script后面所加的參數(shù)。
*************************
例一:
#!/bin/sh
for i in a b c d e f ; do
echo $i
done
它將會(huì)顯示出a到f。
*************************
例二: 另一種用法,A-Z
#!/bin/sh
WORD="a b c d e f g h i j l m n o p q r s t u v w x y z"
for i in $WORD ; do
echo $i
done
這個(gè)Script將會(huì)顯示a到z。
*************************
例三 : 修改副檔名
如果您有許多的.txt檔想要改名成.doc檔,您不需要一個(gè)一個(gè)來。
#!/bin/sh
FILES=`ls /txt/*.txt`
for txt in $FILES ; do
doc=`echo $txt | sed "s/.txt/.doc/"`
mv $txt $doc
done
這樣可以將*.txt檔修改成*.doc檔。
*************************
例四 : meow
#!/bin/sh
# Filename : meow
for i ; do
cat $i
done
當(dāng)您輸入"meow file1 file2 ..."時(shí),其作用就跟"cat file1 file2 ..."一樣。
*************************
例五 : listbin
#!/bin/sh
# Filename : listbin
for i in /bin/* ; do
echo $i
done
當(dāng)您輸入"listbin"時(shí),其作用就跟"ls /bin/*"一樣。
*************************
例六 : /etc/rc.d/rc
拿一個(gè)實(shí)際的例來說,Red Hat的/etc/rc.d/rc的啟動(dòng)程式中的一個(gè)片斷。
for i in /etc/rc.d/rc$runlevel.d/S*; do
# Check if the script is there.
[ ! -f $i ] && continue
# Check if the subsystem is already up.
subsys=${i#/etc/rc.d/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] || \
[ -f /var/lock/subsys/${subsys}.init ] && continue
# Bring the subsystem up.
$i start
done
這個(gè)例中,它找出/etc/rc.d/rcX.d/S*所有檔案,檢查它是否存在,然后一一執(zhí)行。
流程控制case
case word in [ pattern [ | pattern ] ... ) list ;; ] ... esac
case/esac的標(biāo)準(zhǔn)用法大致如下:
case $arg in
pattern | sample) # arg in pattern or sample
;;
pattern1) # arg in pattern1
;;
*) #default
;;
esac
arg是您所引入的參數(shù),如果arg內(nèi)容符合pattern項(xiàng)目的話,那么便會(huì)執(zhí)行pattern以下的程式碼,而該段程式碼則以兩個(gè)分號(hào)";;"做結(jié)尾。
可以注意到"case"及"esac"是對(duì)稱的,如果記不起來的話,把"case"顛倒過來即可。
*************************
例一 : paranoia
#!/bin/sh
case $1 in
start | begin)
echo "start something"
;;
stop | end)
echo "stop something"
;;
*)
echo "Ignorant"
;;
esac
執(zhí)行
[foxman@foxman bash]# chmod 755 paranoia
[foxman@foxman bash]# ./paranoia
Ignorant
[foxman@foxman bash]# ./paranoia start
start something
[foxman@foxman bash]# ./paranoia begin
start something
[foxman@foxman bash]# ./paranoia stop
stop something
[foxman@foxman bash]# ./paranoia end
stop something
*************************
例二 : inetpanel
許多的daemon都會(huì)附上一個(gè)管理用的Shell Script,像BIND就附上ndc,Apache就附上apachectl。這些管理程式都是用shell script來寫的,以下示一個(gè)管理inetd的shell script。
#!/bin/sh
case $1 in
start | begin | commence)
/usr/sbin/inetd
;;
stop | end | destroy)
killall inetd
;;
restart | again)
killall -HUP inetd
;;
*)
echo "usage: inetpanel [start | begin | commence | stop | end | destory | restart | again]"
;;
esac
*************************
例三 : 判斷系統(tǒng)
有時(shí)候,您所寫的Script可能會(huì)跨越好幾種平臺(tái),如Linux、FreeBSD、Solaris等等,而各平臺(tái)之間,多多少少都有不同之處,有時(shí)候需要判斷目前正在那一種平臺(tái)上執(zhí)行。此時(shí),我們可以利用uname來找出系統(tǒng)資訊。
#!/bin/sh
SYSTEM=`uname -s`
case $SYSTEM in
Linux)
echo "My system is Linux"
echo "Do Linux stuff here..."
;;
FreeBSD)
echo "My system is FreeBSD"
echo "Do FreeBSD stuff here..."
;;
*)
echo "Unknown system : $SYSTEM"
echo "I don't what to do..."
;;
esac
流程控制select
select name [ in word; ] do list ; done
select顧名思義就是在word中選擇一項(xiàng)。與for相同,如果[in word;]省略,將會(huì)使用Script后面所加的參數(shù)。
例:
#!/bin/sh
WORD="a b c"
select i in $WORD ; do
case $i in
a)
echo "I am A"
;;
b)
echo "I am B"
;;
c)
echo "I am C"
;;
*)
break;
;;
esac
done
執(zhí)行結(jié)果
[foxman@foxman bash]# ./select_demo
1) a
2) b
3) c
#? 1
I am A
1) a
2) b
3) c
#? 2
I am B
1) a
2) b
3) c
#? 3
I am C
1) a
2) b
3) c
#? 4
返回狀態(tài)Exit
在繼續(xù)下去之前,我們必須要切入另一個(gè)話題,即返回狀態(tài)值 - Exit Status。因?yàn)閕f/while/until都遷涉到了使用Exit Status來控制程式流程的問題。
*************************
許多人都知道,在許多語言中(C/C++/Perl....),都有一個(gè)exit的函數(shù),甚至連Bash自己都有個(gè)exit的內(nèi)建命令。而exit后面所帶的數(shù)字,便是返回狀態(tài)值 - Exit Status。
返回狀態(tài)值可以使得程式與程式之間,利用Shell script來結(jié)合的可能性大增,利用小程式,透過Shell script,來完成很雜的工作。
在shell中,返回值為零表示成功(True),非零值為失敗(False)。
*************************
舉例來說,以下這個(gè)兩個(gè)小程式y(tǒng)es/no分別會(huì)返回0/1(成功/失敗):
/* yes.c */
void main(void) { exit(0); }
/* no.c */
void main(void) { exit(1); }
那么以下這個(gè)"YES"的shell script便會(huì)顯示"YES"。
#!/bin/sh
# YES
if yes ; then
echo "YES"
fi
而"NO"不會(huì)顯示任何東西。
#!/bin/sh
# NO
if no ; then
echo "YES"
fi
*************************
test express
[ express ]
在Shell script中,test express/[ express ]這個(gè)語法被大量地使用,它是個(gè)非常實(shí)用的指令。由于它的返回值即Exit Status,經(jīng)常被運(yùn)用在if/while/until的場合中。而在后面,我們也會(huì)大量運(yùn)用到,在進(jìn)入介紹if/while/until之前,有必要 先解一下。
其返回值為0(True)或1(False),要看表述(express)的結(jié)果為何。
express格式
-b file : 當(dāng)檔案存在并且屬性是Block special(通常是/dev/xxx)時(shí),返回True。
-c file : 當(dāng)檔案存在并且屬性是character special(通常是/dev/xxx)時(shí),返回True。
-d file : 當(dāng)檔案存在并且屬性是目錄時(shí),返回True。
-e file : 當(dāng)檔案存在時(shí),返回True。
-f file : 當(dāng)檔案存在并且是正常檔案時(shí),返回True。
-g file : 當(dāng)檔案存在并且是set-group-id時(shí),返回True。
-k file : 當(dāng)檔案存在并且有"sticky" bit被設(shè)定時(shí),返回True。
-L file : 當(dāng)檔案存在并且是symbolic link時(shí),返回True。
-p file : 當(dāng)檔案存在并且是name pipe時(shí),返回True。
-r file : 當(dāng)檔案存在并且可讀取時(shí),返回True。
-s file : 當(dāng)檔案存在并且檔案大小大于零時(shí),返回True。
-S file : 當(dāng)檔案存在并且是socket時(shí),返回True。
-t fd : 當(dāng)fd被開啟為terminal時(shí),返回True。
-u file : 當(dāng)檔案存在并且set-user-id bit被設(shè)定時(shí),返回True。
-w file : 當(dāng)檔案存在并且可寫入時(shí),返回True。
-x file : 當(dāng)檔案存在并且可執(zhí)行時(shí),返回True。
-O file : 當(dāng)檔案存在并且是被執(zhí)行的user id所擁有時(shí),返回True。
-G file : 當(dāng)檔案存在并且是被執(zhí)行的group id所擁有時(shí),返回True。
file1 -nt file2 : 當(dāng)file1比file2新時(shí)(根據(jù)修改時(shí)間),返回True。
file1 -ot file2 : 當(dāng)file1比file2舊時(shí)(根據(jù)修改時(shí)間),返回True。
file1 -ef file2 : 當(dāng)file1與file2有相同的device及inode number時(shí),返回True。
-z string : 當(dāng)string的長度為零時(shí),返回True。
-n string : 當(dāng)string的長度不為零時(shí),返回True。
string1 = string2 : string1與string2相等時(shí),返回True。
string1 != string2 : string1與string2不相等時(shí),返回True。
! express : express為False時(shí),返回True。
expr1 -a expr2 : expr1及expr2為True。
expr1 -o expr2 : expr1或expr2其中之一為True。
arg1 OP arg2 : OP是-eq[equal]、-ne[not-equal]、-lt[less-than]、-le[less-than-or-equal]、-gt [greater-than]、-ge[greater-than-or-equal]的其中之一。
*************************
在Bash中,當(dāng)錯(cuò)誤發(fā)生在致命信號(hào)時(shí),bash會(huì)返回128+signal number做為返回值。如果找不到命令,將會(huì)返回127。如果命令找到了,但該命令是不可執(zhí)行的,將返回126。除此以外,Bash本身會(huì)返回最后一個(gè) 指令的返回值。若是執(zhí)行中發(fā)生錯(cuò)誤,將會(huì)返回一個(gè)非零的值。
Fatal Signal : 128 + signo
Can't not find command : 127
Can't not execute : 126
Shell script successfully executed : return the last command exit status
Fatal during execution : return non-zero
流程控制if
if list then list [ elif list then list ] ... [ else list ] fi
幾種可能的寫法
*************************
第一種
if list then
do something here
fi
當(dāng)list表述返回值為True(0)時(shí),將會(huì)執(zhí)行"do something here"。
例一 : 當(dāng)我們要執(zhí)行一個(gè)命令或程式之前,有時(shí)候需要檢查該命令是否存在,然后才執(zhí)行。
if [ -x /sbin/quotaon ] ; then
echo "Turning on Quota for root filesystem"
/sbin/quotaon /
fi
例二 : 當(dāng)我們將某個(gè)檔案做為設(shè)定檔時(shí),可先檢查是否存在,然后將該檔案設(shè)定值載入。
# Filename : /etc/ppp/settings
PHONE=1-800-COLLECT
#!/bin/sh
# Filename : phonebill
if [ -f /etc/ppp/settings ] ; then
source /etc/ppp/settings
echo $PHONE
fi
執(zhí)行
[foxman@foxman ppp]# ./phonebill
1-800-COLLECT
*************************
第二種
if list then
do something here
else
do something else here
fi
例三 : Hostname
#!/bin/sh
if [ -f /etc/HOSTNAME ] ; then
HOSTNAME=`cat /etc/HOSTNAME`
else
HOSTNAME=localhost
fi
*************************
第三種
if list then
do something here
elif list then
do another thing here
fi
例四 : 如果某個(gè)設(shè)定檔允許有好幾個(gè)位置的話,例如crontab,可利用if then elif fi來找尋。
#!/bin/sh
if [ -f /etc/crontab ] ; then
CRONTAB="/etc/crontab"
elif [ -f /var/spool/cron/crontabs/root ] ; then
CRONTAB="/var/spool/cron/crontabs/root"
elif [ -f /var/cron/tabs/root ] ; then
CRONTAB="/var/cron/tabs/root"
fi
export CRONTAB
*************************
第四種
if list then
do something here
elif list then
do another thing here
else
do something else here
fi
例五 : 我們可利用uname來判斷目前系統(tǒng),并分別做各系統(tǒng)狀況不同的事。
#!/bin/sh
SYSTEM=`uname -s`
if [ $SYSTEM = "Linux" ] ; then
echo "Linux"
elif [ $SYSTEM = "FreeBSD" ] ; then
echo "FreeBSD"
elif [ $SYSTEM = "Solaris" ] ; then
echo "Solaris"
else
echo "What?"
fi
控制圈while/until
while list do list done
當(dāng)list為True時(shí),該圈會(huì)不停地執(zhí)行。
例一 : 無限回圈寫法
#!/bin/sh
while : ; do
echo "do something forever here"
sleep 5
done
例二 : 強(qiáng)迫把pppd殺掉。
#!/bin/sh
while [ -f /var/run/ppp0.pid ] ; do
killall pppd
done
*************************
until list do list done
當(dāng)list為False(non-zero)時(shí),該圈會(huì)不停地執(zhí)行。
例一 : 等待pppd上線。
#!/bin/sh
until [ -f /var/run/ppp0.pid ] ; do
sleep 1
done
參數(shù)與變數(shù)
在繼續(xù)下去介紹function之前,我們必須停下來介紹"參數(shù)與變數(shù)"。
*************************
參數(shù)(Parameters)是用來儲(chǔ)存"值"的資料型態(tài),有點(diǎn)像是一般語言中的變數(shù)。它可以是個(gè)名稱(name)、數(shù)字(number)、或者是以下所列出來一些特殊符號(hào)(Special Parameters)。
在shell中,變數(shù)是由name形式的參數(shù)所構(gòu)成的。
*************************
在前面的許多例中,我們事實(shí)上已經(jīng)看到許多參數(shù)的運(yùn)用。要設(shè)定一個(gè)Parameter實(shí)際很簡單:
name=value
例如說:
MYHOST="foxman"
而要使用它時(shí),則是加個(gè)"$"符號(hào)。
echo $MYHOST
*************************
位置參數(shù)(Positional Parameters)
*************************
所謂的位置參數(shù)便是0,1,2,3,4,5,6,7,8,9...。使用時(shí),用$0,$1,$2...。
位置參數(shù)是當(dāng)script被載入時(shí),后面所附加的參數(shù)。$0是本身,$1則為第一個(gè)參數(shù),$2為第二個(gè),依此類推。而當(dāng)Positional Parameters被function所使用時(shí),它們會(huì)被暫時(shí)取代(下一節(jié)會(huì)介紹function)。
例如以下這個(gè)script:
#!/bin/sh
# Filename : position
echo $0
echo $1
執(zhí)行時(shí):
[foxman@foxman bash]# ./position abc
./position
abc
當(dāng)位置參數(shù)超過兩位數(shù)時(shí),有特別的方法來展開,稱為Expansion。
*************************
特殊參數(shù)(Speical Parameters)
這些符號(hào),非常不人性,對(duì)新手來說很困擾。但上手后,會(huì)覺得方便無比,有些如果您看不懂的話,就--算了,不用浪費(fèi)太多時(shí)間在上面。
*************************
* 星號(hào)
將Positional Parameters合成一個(gè)參數(shù),其間隔為IFS內(nèi)定參數(shù)的第一個(gè)字元(見內(nèi)建變數(shù)一節(jié))。
例:
#!/bin/sh
# starsig
echo $*
執(zhí)行:
[foxman@foxman bash]# starsig a b c d e f g
a b c d e f g
*************************
@ at符號(hào)
與*星號(hào)類同。不同之處在于不參照IFS。
例:
#!/bin/sh
# atsig
echo $@
執(zhí)行:
[foxman@foxman bash]# atsig a b c d e f g
a b c d e f g
*************************
# 井字號(hào)
展開Positional parameters的數(shù)量。
例:
#!/bin/sh
# poundsig
echo $#
執(zhí)行
[foxman@foxman bash]# poundsig a b c d e f g
7
*************************
? 問號(hào)
最近執(zhí)行的foreground pipeline的狀態(tài)。
*************************
- 減號(hào)
最近執(zhí)行的foreground pipeline的選項(xiàng)參數(shù)。
*************************
$ 錢錢錢
本身的Process ID。
[foxman@foxman bash]# ps ax | grep bash
1635 p1 S 0:00 /bin/bash
[foxman@foxman bash]# echo $$
1635
*************************
! 驚號(hào)
最近執(zhí)行背景命令的Process ID。
*************************
0 零
在Positional Parameters一部份已經(jīng)說明過了,是執(zhí)行的shell script本身。但如果是用"bash -c",則$0被設(shè)為第一個(gè)參數(shù)。
[foxman@foxman bash]# echo $0
/bin/bash
*************************
_ 底線符號(hào)
顯示出最后一個(gè)執(zhí)行的命令。
[foxman@foxman bash]# echo $_
bash
*************************
內(nèi)建變數(shù)(Shell Variables)
Bash有許多內(nèi)建變數(shù),像PATH、HOME、ENV......等等。這些內(nèi)建變數(shù)將在另一節(jié)中,專門一一說明。
函數(shù)function
[ function ] name () { list; }
function的參數(shù)是Positional Paraments。
例
#!/bin/sh
function func() {
echo $1
echo $2
return 1
}
func "Hello" "function"
局部變數(shù)可用local來宣告。
函數(shù)可export,使用下一層的shell可以使用。
函數(shù)可遞,沒有遞層數(shù)的限制。
Bash內(nèi)建指令集
以下的命令,大部份都沒有使用例,您可能會(huì)看不出所以然,摸不著頭腦。在我加入例說明前,建議您"man bash",然后自己實(shí)際操作一次。
*************************
: [arguments]
不做任何事,除了[arguments]一些參數(shù)展開及一些特定重導(dǎo)向的作業(yè)外。
永遠(yuǎn)返回零。它的用法跟true一樣。
*************************
. filename [arguments]
source filename [arguments]
由filename中讀取命令,并執(zhí)行。
您會(huì)在/etc/rc.d/*中發(fā)現(xiàn)很多
. /xxxx
的指令,而xxxx的permission都不是可執(zhí)行的。事實(shí)上,在tcsh中,需要用
source /xxxx
來做同樣的指令。
注意到"."的后面是有空格的(比較一下". /"跟"./",不一樣)。filename是內(nèi)含指令的純文字檔即可,無須chmod 755 filename。
例
filename : my_source
DEV=lo
IP=127.0.0.1
NETMASK=255.0.0.0
BROADCAST=127.255.255.255
ifconfig $IP netmask $NETMASK broadcast $BROADCAST dev $DEV
接下來
. my_source
或
source my_source
便可執(zhí)行該script,而不需要"chmod 755 my_source"
*************************
alias [name[=value] ...]
昵稱命令
例如您如果來自DOS的世界,對(duì)UNIX的指令不習(xí)慣,可用alias來修改,以符合您的習(xí)慣。
例
alias ls="ls --color"
alias dir="ls"
alias cd..="cd .."
alias copy="cp -f" # dangerous, recommend, "cp -i"
alias del="rm -f" # dangerous, recommend, "rm -i"
alias move="mv -f" # dangerous, recommend, "mv -i"
alias md="mkdir"
alias rd="rmdir"
*************************
unalias [-a] [name ...]
unalias取消alias的設(shè)定。"unalias -a"將全部alias取消。
例
unalias copy
*************************
bg [jobspec]
將指定任務(wù)放到背景中,如果jobspec未指定,內(nèi)定為目前的。
*************************
fg [jobspec]
將指定任務(wù)放到前景中,如果jobsepc沒有指定,那么內(nèi)定為目前的。
*************************
jobs [-lnp] [ jobspec ... ]
第一種形式列出目前正在工作的任務(wù)。
-l : 除了列出一般資訊外,還列出Process IDs。
-p : 僅列出該工作群"首腦"(Process group leader)的Process ID.
-n : 則僅列出有改變的jobs的狀態(tài)。
如果給定jobspec,輸出資訊則只有該jobspec。
返回值為零,除非有非法的選項(xiàng)發(fā)生。
jobs -x command [ args ... ]
如果使用第二種形式(-x),jobs取代指定的command及args,并執(zhí)行返回其Exit Status。
*************************
kill [-s sigspec | -sigspec] [pid | jobspec] ...
將sigspec的信號(hào)送到pid或jobspec。
sigspec可以是SIGKILL/KILL這種形式或是信號(hào)號(hào)碼。如果sigspec是signal name,則大小寫無關(guān),而且可以沒有SIG。
kill -l [signum]
列出信號(hào)名稱。
[foxman@foxman bash]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGIOT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR
*************************
wait [n]
等待指定的行程,并返回其結(jié)束狀態(tài)。n可以是個(gè)jobspec或Process ID。如果n未指定,則等待所有的子行程,及返回值為零。若n為不存在的job或process,則返回127。否則,返回值為最后一個(gè) job/process的Exit Status。
*************************
bind [-m keymap] [-lvd] [-q name]
bind [-m keymap] -f filename
bind [-m keymap] keyseq:function-name
顯示出目前readline的按鍵及鏈結(jié)函數(shù)設(shè)定或是巨集。
-m keymap : 設(shè)定keymap binding。
-l : 顯示出所有readline function的名稱。
-v : 顯示出目前的function name及bindings。
-d : 顯示出function name及bindings。
-f filename : 從filename讀取key bindings。
-q function : 詢問那個(gè)按鍵觸發(fā)function。
*************************
break [n]
跳出控制回圈for/while/until中使用。如果有指定n,則跳出n層。n必須是大于等于1。若n大于巢狀圈數(shù),則所有的圈都會(huì)跳離。返回值回零。
*************************
continue [n]
還原控制回圈for/while/until中使用。如果有指定n,則返回n層。n必須是大于等于1。若n大于巢狀圈數(shù),則還原到最上層。返回值回零。
*************************
exit [n]
離開程式。n是Exit Status。
*************************
return [n]
在function中使用。n為返回值,其作用與Exit Status一樣。
*************************
builtin shell-builtin [arguments]
執(zhí)行內(nèi)建函數(shù)。當(dāng)您定義了與內(nèi)建函數(shù)相同的指令時(shí),可用此命令來執(zhí)行內(nèi)建函數(shù)。
*************************
cd [dir]
更換目錄到dir。如果沒有指定,內(nèi)定為HOME所指定的目錄。
*************************
command [-pVv] command [arg ...]
用command指定可取消正常的shell function尋找。只有內(nèi)建命令及在PATH中找得到的才會(huì)被執(zhí)行。"-p"選項(xiàng),搜尋命令的方式是用PATH來找。"-V"或"-v"選項(xiàng),會(huì)顯示出該命令的一些簡約描述。
*************************
declare [-frxi] [name[=value]]
typeset [-frxi] [name[=value]]
宣告參數(shù)并給它們?cè)O(shè)定屬性。如果沒有給定名稱,將會(huì)顯示各參數(shù)值。
-f : 僅使用函數(shù)名稱。
-r : 將name設(shè)為readonly。
-x : 將name輸出給后續(xù)環(huán)境使用。
-i : 該參數(shù)被設(shè)為integer來使用,可用于算術(shù)表述。
用"+"時(shí),關(guān)閉該屬性。
*************************
dirs [-l] [+/-n]
顯示目前記憶的目錄。目錄可透過pushd/popd來操作。
+n : 顯示開始的記錄n個(gè)。
-n : 顯示結(jié)尾的記錄n個(gè)。
-l : 顯示較多的資訊。
*************************
echo [-neE] [arg ...]
輸出顯示args,由空白分隔。返回值永為零。
-n : 不跳行。
-e : 啟動(dòng)"\"符號(hào)的解譯。
-E : 將ESC解譯功能取消。
"\a" : alert(bell),發(fā)出聲響。
"\b" : backspace,倒退。
"\c" : suppress trailing newline,不跳行。
"\f" : form feed,跳行跳格。
"\n" : new line,新行。
"\r" : carriage return,回到行起點(diǎn)。
"\t" : horizontal tab,水平跳位。
"\v" : vertical tab,垂直跳位。
"\\" : 輸出"\"。
"\nnn" : 輸出ASCII Code號(hào)碼nnn(八進(jìn)位)。
*************************
enable [-n] [-all] [name ...]
啟動(dòng)或關(guān)閉內(nèi)建函數(shù)命令。使用"-n"將所有指定命令皆關(guān)閉,否則都是啟動(dòng)的。如果只有"-n"參數(shù),它將會(huì)顯示所有關(guān)閉的函數(shù)。如果只有"-all",它將會(huì)顯示所有內(nèi)建命令。
*************************
eval [arg ...]
讀取args,并將args合為一個(gè)命令,然后執(zhí)行。其返回值成為eval的返回值。如果沒有參數(shù),eval返回True。
*************************
exec [[-] command [arguments]]
當(dāng)命令執(zhí)行時(shí),該命令取代shell,沒有新的process產(chǎn)生。如果第一個(gè)參數(shù)是"-",shell會(huì)將"-"放入第零個(gè)參數(shù),傳給command。
*************************
export [-nf] [name[=word]] ...
export -p
將name輸出給環(huán)境,給往后的命令使用。"-f"選項(xiàng)表示name是函數(shù)。"-p"顯示出所有export的名稱。"-n"移除name。
*************************
set [--abefhkmnptuvxldCHP] [-o option] [arg ...]
-a : 自動(dòng)將變數(shù)標(biāo)記為可讓后面環(huán)境所使用。
-b : 立即報(bào)告被終結(jié)的背景程式狀態(tài)。
-e : 當(dāng)命令(simple-command,見后面)返回非零值時(shí),立即跳出。
-f : 取消pathname expansion。
-h : 找出所記憶的函數(shù)命令位置。
-k : 所有keyword參數(shù)都放到環(huán)境中。
-m : 監(jiān)督模式。
-n : 讀取命令,但不要執(zhí)行。可用于語法檢查。
-p : 打開privileged模式。
-t : 當(dāng)讀取一個(gè)命令并執(zhí)行后,立即離開。
-u : 當(dāng)參數(shù)展開時(shí),把unset參數(shù)當(dāng)成是錯(cuò)誤。
-v : 列出shell input lines。
-x : 在展開每個(gè)simple-command后,bash顯示展開值在PS4上。
-l : 儲(chǔ)存并還原name binding在for語法中。
-d : 關(guān)閉hasing command搜尋。
-C : 跟`noclobber=`一樣。請(qǐng)見內(nèi)定參數(shù)一節(jié)。
-H : 啟動(dòng)! style history substitution。
-P : 在使用像cd這種指令時(shí),不要跟隨symbolic links。
-- : "--"之后,沒有參數(shù)跟在后面。
- : 指定將所有后面的參數(shù)當(dāng)成是位置參數(shù)。
-o option-name : option-name可以是以下之一
allexport : 與"-a"相同。
braceexpand : 啟動(dòng)Brace Expansion。這是內(nèi)定設(shè)定。
emacs : 使用emacs-style命令列編輯界面。
errexit : 與"-e"相同。
histexpand : 與"-H"相同。
ignoreeof : 效果跟`IGNOREEOF=10`一樣。
interactive-commands : 允許#做為解。
monitor : 與"-m"相同。
noclobber : 與"-C"相同。
noexec : 與"-n"相同。
noglob : 與"-f"相同。
nohash : 與"-d"相同。
notify : 與"-b"相同。
nounset : 與"-u"相同。
physical : 與"-P"相同。
posix : Bash行為修改為Posix 1003.2標(biāo)準(zhǔn)。
privileged : 與"-p"相同。
verbose : 與"-v"相同。
vi : 使用vi-style命令列編輯程式。
xtrace : 與"-x"相同。
*************************
unset [-fv] [name ...]
移除對(duì)映于name的參數(shù)。要注意PATH、IFS、PPID、PS1、PS2、UID、EUID不能unset。若RANDOM、SECONDS、 LINENO、HISTCMD被unset,它們會(huì)喪失原有意義,既始它們后來被重設(shè)也一樣。返回值為True,除非name是不能被unset的。
*************************
fc [-e ename] [-nlr] [first] [last]
fc -s [pat=rep] [cmd]
修正命令。
*************************
getopts optstring name [args]
解析位置參數(shù)。
*************************
help [pattern]
顯示協(xié)助資訊。
*************************
history [n]
history -rwan [filename]
沒有參數(shù)時(shí),會(huì)顯示所下命令的歷史記錄。帶有參數(shù)"n"則顯示最后n個(gè)。
其它參數(shù)如下:
-a : 新增"新歷史"到歷史檔中。
-n : 讀取尚未讀到歷史中的記錄。
-r : 讀取filename做為歷史檔,并用它為目前歷史記錄。
-w : 將現(xiàn)有歷史記錄寫到filename中。
*************************
let arg [arg ...]
算術(shù)表述。請(qǐng)參考算術(shù)表述一節(jié)。
*************************
local [name[=value] ...]
產(chǎn)生一個(gè)局部參數(shù)。如果用于function,則其作用圍在function內(nèi)及其子函數(shù)。
*************************
logout
離開login shell。
*************************
popd [+/-n]
移除目錄堆疊。"+n"移除上面n個(gè),"-n"移除下面n個(gè)。
*************************
pushd [dir]
pushd +/-n
將目錄新增到目錄堆疊的最上面。"+n"旋轉(zhuǎn)該堆疊,使第n個(gè)目錄變成最上面。"-n"旋轉(zhuǎn)該堆疊,使倒數(shù)第n個(gè)目錄變成最上面。
*************************
pwd
列出目前工作目錄的絕對(duì)路徑。
*************************
read [-r] [name ...]
讀進(jìn)一行,然后第一個(gè)字設(shè)到第一個(gè)name,第二個(gè)設(shè)到第二個(gè)name,依此類推。如果沒有name在參數(shù)中,則read會(huì)將值設(shè)到REPLY。返回值為零,除非遇到End-Of-File。若有"-r"選項(xiàng),則"\n"被考慮為該行的一部份。
*************************
readonly [-f] [name ...]
readonly -p
將給定的name標(biāo)記為readonly。如果是"-f"選項(xiàng),則函數(shù)也一樣被標(biāo)記為readonly。"-p"會(huì)列出所有readonly的name。"--"取消檢查剩余的參數(shù)。
*************************
shift [n]
Positional Parameters從n+1...開始,會(huì)被改為$1...。n若為零,則沒有改變。n若未給定,則內(nèi)定為1。n必須是非負(fù)數(shù),并且小于或等于$#。若n大于$#,則沒有改變。返回值為零,除非n大于$#或小于零。
*************************
suspend [-f]
暫停這個(gè)shell的執(zhí)行,直到它收到SIGCONT信號(hào)。"-f"選項(xiàng)則是叫l(wèi)ogin shell不要抱怨,不過還是一樣暫停。返回狀態(tài)零,除非該shell是個(gè)login shell,而且沒有"-f"選項(xiàng)。
*************************
test expr
[ expr ]
我們?cè)贓xit Status的部份已經(jīng)說過了,不再重。
*************************
times
列出該shell的累積的使用者及系統(tǒng)時(shí)間及從shell執(zhí)行的process時(shí)間,返回值為零。
------------------------------------------------------------------------------
trap [-l] [arg] [sigspec]
當(dāng)收到sigspec信號(hào)時(shí),執(zhí)行arg命令。"-l"顯示出信號(hào)名稱及號(hào)碼。
*************************
type [-all] [-type | -path] name [name ...]
沒有參數(shù)的狀況下,它會(huì)顯示出shell如何解譯name做為命令。如果有"-type",它將會(huì)顯示alias、keyword、 function、builtin或file。如果有"-path"的參數(shù),它將會(huì)顯示該命令的路徑,找不到的話,不顯示任何東西。如果有"-all"的 參數(shù),它將會(huì)顯示所有可執(zhí)行name的可能路徑。type接受"-a"、"-t"、"-p"做為縮寫。
*************************
ulimit [-SHacdfmstpnuv [limit]]
ulimit提供了對(duì)shell的可獲取資源控制的功能。
-a : 報(bào)告目前所有限制。
-c : 設(shè)定最大可產(chǎn)生的core檔案。
-d : 行程資料段(process's data segment)最大值。
-f : 可被這個(gè)shell產(chǎn)生的最大檔案。
-m : resident set size最大值。
-s : 堆疊最大值。
-t : CPU TIME最大值(以秒計(jì)算)。
-p : pipe size in 512-byte blocks的最大值。
-n : 可開啟的file descriptors最大值。
-u : 單一使用者可使用的最大process數(shù)。
-v : 該shell最大虛擬記憶體可用值。
所有項(xiàng)目是以1024做為單位。
*************************
umask [-S] [mode]
將使用者的file-creation mask設(shè)為mode。"-S"選項(xiàng)將mask印成符號(hào)形式。
Bash內(nèi)建參數(shù)
PPID : 該bash的呼叫者process ID.
PWD : 目前的工作目錄。
OLDPWD : 上一個(gè)工作目錄。
REPLY : 當(dāng)read命令沒有參數(shù)時(shí),直接設(shè)在REPLY上。
UID : User ID。
EUID : Effective User ID。
BASH : Bash的完整路徑。
BASH_VERSION : Bash版本。
SHLVL : 每次有Bash執(zhí)行時(shí),數(shù)字加一。
RANDOM : 每次這個(gè)參數(shù)被用到時(shí),就會(huì)產(chǎn)生一個(gè)亂數(shù)在RANDOM上。
SECONDS : 從這個(gè)Shell一開始啟動(dòng)后的時(shí)間。
LINENO : Script的行數(shù)。
HISTCMD : 歷史記錄數(shù)。
OPTARG : getopts處理的最后一個(gè)選項(xiàng)參數(shù)。
OPTIND : 下一個(gè)要由getopts所處理的參數(shù)號(hào)碼。
HOSTTYPE : 機(jī)器種類。
OSTYPE : 作業(yè)系統(tǒng)名稱。
IFS : Internal Field Separator。
PATH : 命令搜尋路徑。
PATH="/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
HOME : 目前使用者的home directory;
CDPATH : cd命令的搜尋路徑。
ENV : 如果這個(gè)參數(shù)被設(shè)定,每次有shell script被執(zhí)行時(shí),將會(huì)執(zhí)行它所設(shè)定的檔名做為環(huán)境設(shè)定。
MAIL : 如果這個(gè)參數(shù)被設(shè)定,而且MAILPATH沒有被設(shè)定,那么有信件進(jìn)來時(shí),bash會(huì)通知使用者。
MAILCHECK : 設(shè)定多久時(shí)間檢查郵件一次。
MAILPATH : 一串的郵件檢查路徑。
MAIL_WARNING : 如果有設(shè)定的話,郵件被讀取后,將會(huì)顯示訊息。
PS1 : 提示訊息設(shè)定,內(nèi)定為"bash\$ "。(請(qǐng)?jiān)斠娞崾居嵪⒁还?jié)。)
PS2 : 第二提示訊息設(shè)定,內(nèi)定為"> "。
PS3 : select命令所使用的提示訊息。
PS4 : 執(zhí)行追蹤時(shí)用的提示訊息設(shè)定,內(nèi)定為"+ "。
HISTSIZE : 命令歷史記錄量,內(nèi)定為500。
HISTFILE : 歷史記錄檔,內(nèi)定~/.bash_history。
HISTFILESIZE : 歷史記錄檔行數(shù)最大值,內(nèi)定500。
OPTERR : 如果設(shè)為1,bash會(huì)顯示getopts的錯(cuò)誤。
PROMPT_COMMAND : 如果設(shè)定的話,該值會(huì)在每次執(zhí)行命令前都顯示。
IGNOREEOF : 將EOF值當(dāng)成輸入,內(nèi)定為10。
TMOUT : 如果設(shè)為大于零,該值被解譯為輸入等待秒數(shù)。若無輸入,當(dāng)成沒有輸入。
FCEDIT : fc命令的內(nèi)定編輯器。
FIGNORE : 請(qǐng)?jiān)斠奟EADLINE。
INPUTRC : readline的startup file,內(nèi)定~/.inputrc
notify : 如果設(shè)定了,bash立即報(bào)告被終結(jié)的背景程式。
history_control, HISTCONTROL : history使用。
command_oriented_history : 存入多行指令。
glob_dot_filenames : 如果設(shè)定了,bash將會(huì)把"."包含入檔案路徑中。
allow_null_glob_expansion : 如果設(shè)定了,bash允許路徑明稱為null string。
histchars : history使用。
nolinks : 如果設(shè)定了,執(zhí)行指令時(shí),不會(huì)跟隨symbolic links。
hostname_completion_file, HOSTFILE : 包含與/etc/hosts相同格式的檔名。
noclobber : 如果設(shè)定了,Bash不會(huì)覆寫任何由">"、">&"及"<>"所操作的檔案。
auto_resume : 請(qǐng)見任務(wù)控制一節(jié)。
no_exit_on_failed_exec : 如果該值存在,非互動(dòng)的shell不會(huì)因?yàn)閑xec失敗而跳出。
cdable_vars : 如果啟動(dòng),而cd命令找不到目錄,可切換到參數(shù)形態(tài)指定的目錄下。
提示符號(hào)
Bash使用PS1~PS4來顯示提示符號(hào),其格式如下:
*************************
\t : 現(xiàn)在時(shí)間。
\d : 現(xiàn)在日期。
\n : 新行。
\s : shell的名稱。
\w : 目前工作目錄。
\W : 目前工作目錄完整路徑。
\u : 使用者名稱。
\h : Hostname。
\# : 這個(gè)命令的號(hào)碼。
\! : 歷史號(hào)碼。
\$ : 如果EUID是0,則#,否則為$。
\nnn : 八進(jìn)位的字元。
\\ : "\"符號(hào)。
\[ : 開始一序列不可列印的字元。
\] : 結(jié)束一序列不可列印的字元。
算術(shù)表述
- +
! ~
* / %
+ -
<< >>
<= >= < >
== !=
&
^
|
&&
||
= *= /= %= += -= <<= >>= &= ^= |=
重導(dǎo)Redirection
>
>>
1>
.
.
語法
Simple Command
Pipelines
Lists
(list)
{ list; }
轉(zhuǎn)自 這里
另一篇 詳解Bash命令行處理
bash編程教學(xué)實(shí)例
bash編程
--------------------------------------------------------------------------------
時(shí)間:2004/03/02 來源:不詳
Shell Script(bash)簡介
眾所皆知地,UNIX上以小工具著名,利用許多簡單的小工具,來完成原本需要大量軟體開發(fā)的工作,這一點(diǎn)特色,使得UNIX成為許多人心目中理想的系統(tǒng)平臺(tái)。
在眾多的小工具中,Shell Script算得上是最基本、最強(qiáng)大、運(yùn)用最廣泛的一個(gè)。它運(yùn)用圍之廣,不但從系統(tǒng)啟動(dòng)、程式編譯、定期作業(yè)、上網(wǎng)連線,甚至安裝整個(gè)Linux系統(tǒng),都可以用它來完成。
因?yàn)镾hell Script是利用您平日在使用的一些指令,將之組合起來,成為一個(gè)"程式"。如果您平日某些序列的指令下得特別頻繁,便可以將這些指令組合起來,成為另 一個(gè)新的指令。這樣,不但可以簡化并加速操作速度,甚至還可以干脆自動(dòng)定期執(zhí)行,大大簡化系統(tǒng)管理工作。
*************************
Bash(GNU Bourne-Again SHell)是許多Linux平臺(tái)的內(nèi)定Shell,事實(shí)上,還有許多傳統(tǒng)UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等, Shell Script大致都類同,當(dāng)您學(xué)會(huì)一種Shell以后,其它的Shell會(huì)很快就上手,大多數(shù)的時(shí)候,一個(gè)Shell Script通常可以在很多種Shell上使用。
這里我介紹您bash的使用方法。事實(shí)上,當(dāng)您"man bash"時(shí),就可以看到bash的說明書,不過對(duì)許多人來說,這份說明書猶如"無字天書"一樣難懂。這份文件,主要資料來源為"man bash",我加上一些實(shí)際日常的應(yīng)用例來說明。希望這樣能讓那些始終不得其門而入的人們,多多少少能有點(diǎn)概念。
教學(xué)例子
"Hello world" Shell Script
照傳統(tǒng)程式教學(xué)例,這一節(jié)介紹Shell Script的"Hello World"如何撰寫。
*************************
#!/bin/sh
# Filename : hello
echo "Hello world!"
*************************
大家應(yīng)該會(huì)注意到第一行的"#!/bin/sh"。在UNIX下,所有的可執(zhí)行Script,不管是那一種語言,其開頭都是"#!",例如Perl是 "#!/usr/bin/perl",tcl/tk是"#!/usr/bin/wish",看您要執(zhí)行的Script程式位置在那里。您也可以用"#! /bin/bash"、"#!/bin/tcsh"等等,來指定使用特定的Shell。
echo是個(gè)bash的內(nèi)建指令。
*************************
接下來,執(zhí)行hello這個(gè)script:
要執(zhí)行一個(gè)Script的方式有很多種。
*************************
第一種 : 將hello這個(gè)檔案的權(quán)限設(shè)定為可執(zhí)行。
[foxman@foxman bash]# chmod 755 hello
執(zhí)行
[foxman@foxman bash]# ./hello
hello world
*************************
第二種 : 使用bash內(nèi)建指令"source"或"."。
[foxman@foxman bash]# source hello
hello world
或
[foxman@foxman bash]# . hello
hello world
*************************
第三種 : 直接使用sh/bash/tcsh指令來執(zhí)行。
[foxman@foxman bash]# sh hello
hello world
或
[foxman@foxman bash]# bash hello
hello world
*************************
Bash執(zhí)行選項(xiàng)
*************************
-c string : 讀取string來當(dāng)命令。
-i : 互動(dòng)介面。
-s : 由stdin讀取命令。
- : 取消往后選項(xiàng)的讀取。
-norc : 不要讀~/.bashrc來執(zhí)行。
-noprofile : 不要讀/etc/profile、~/.bash_profile、~/.bash_login、~/.profile等等來執(zhí)行。
-rcfile filename : 執(zhí)行filename,而非~/.bashrc
-version : 顯示版本。
-quiet : 啟動(dòng)時(shí)不要哩唆。
-login : 確保bash是個(gè)login shell。
-nobraceexpansion : 不要用curly brace expansion({}符號(hào)展開)。
-nolineediting : 不用readline來讀取命令列。
-posix : 改采Posix 1003.2標(biāo)準(zhǔn)。
用于自動(dòng)備份的Shell Script
一個(gè)用于自動(dòng)備份的Shell Script
我們先前提到,可利用Shell Script搭配crond來作定期的工作。要作定期性的工作,在UNIX上,就是與crond的搭配運(yùn)用。
*************************
首先我們先來研究如何對(duì)系統(tǒng)進(jìn)行備份。
要對(duì)系統(tǒng)進(jìn)行備份,不外乎便是利用一些壓縮工具。在許多UNIX系統(tǒng)上,tar及gzip是de facto的資料交換標(biāo)準(zhǔn)。我們經(jīng)常可以看見一些tar.gz或tgz檔,這些檔案,被稱為tarball。當(dāng)然了,您也可以用bzip2、zip等等壓 縮工具來進(jìn)行壓縮,不必限定于gzip。但tar配合gzip是最普遍的,也是最方便的方式。
要將我們想要的資料壓縮起來,進(jìn)行備份,可以結(jié)合tar及gzip一起進(jìn)行。方式有很多種,最常用的指令是以下這一種:
tar -c file/dir ... | gzip -9 > xxxx.tar.gz
您也可以分開來做:
tar -r file/dir ... -f xxxx.tar
gzip -9 xxxx.tar
或
tar -r file/dir ... -f xxxx.tar
gzip -9 < xxxx.tar > xxxx.tar.gz
*************************
在解過Linux下檔案備份的基本知識(shí)后,我們來寫一個(gè)將檔案備份的Script。
#!/bin/sh
# Filename : backup
DIRS="/etc /var /your_directories_or_files"
BACKUP="/tmp/backup.tgz"
tar -c $DIRS | gzip -9 > $BACKUP
其中DIRS放的是您要備份的檔案及目錄,BACKUP是您的備份檔。可不要將/tmp放進(jìn)DIRS中,那樣做,您是在做備份的備份,可能將您的硬碟塞爆。
*************************
接下來測試
[foxman@foxman bash]# chmod 755 backup
[foxman@foxman bash]# ./backup
執(zhí)行完成后在/tmp就會(huì)有一個(gè)backup.tgz,里面儲(chǔ)存了您重要的資料。您可用
gzip -dc /tmp/backup.tgz | tar -vt
或
tar vtfz /tmp/backup.tgz
來看看里面的檔案列表。
要解開時(shí),可用以下指令來完成復(fù)原:
gzip -dc /tmp/backup.tgz | tar -xv
或
tar xvfz /tmp/backup.tgz
備份通常是僅備份系統(tǒng)通常最重要的部份,/etc可說是不可缺少的一部份。另外,看您系統(tǒng)中有那些重要的資料需要備份。通常來說,您沒有必要備份 /bin、/sbin、/usr/bin、/usr/sbin、/usr/X11R6/bin等等這些執(zhí)行檔目錄。只要備份您重要的檔案即可,別把整個(gè)硬 碟備份,那是蠻呆的動(dòng)作。
*************************
如果您有許多臺(tái)機(jī)器,可利用其中一臺(tái)任務(wù)較輕的內(nèi)部網(wǎng)路主機(jī),做為主要備份主機(jī)。將所有機(jī)器都自動(dòng)執(zhí)行備份,然后利用NFS/Coda/Samba等網(wǎng)路檔案系統(tǒng),將備份的資料放到該備份機(jī)器中,該機(jī)器則定時(shí)收取備份資料,然后您再由該機(jī)器中進(jìn)行一次備份。
這里是整個(gè)系統(tǒng)備份方案的圖示。
在您進(jìn)行之前,先解一下,系統(tǒng)中那些是要備份的,那些是不需要的。
*************************
新的backup
#!/bin/sh
HOSTNAME=`hostname`
DIRS="/etc /var /your_important_directory"
BACKUP="/tmp/$HOSTNAME.tgz"
NFS="/mnt/nfs"
tar -c $DIRS | gzip -9 > $BACKUP
mv -f $BACKUP $NFS
*************************
備份主機(jī)內(nèi)的Script : collect_backup
#!/bin/sh
NFS="/mnt/nfs"
BACKUP="/backup"
mv -f $NFS/*.tgz $BACKUP
在此,您不能夠?qū)⑺袀浞荻贾苯臃旁?mnt/nfs,這是危險(xiǎn)的。萬一任一臺(tái)機(jī)器不小心將/mnt/nfs所有內(nèi)容刪除,那么備份就會(huì)消失。因此,您需要將/mnt/nfs移到一個(gè)只有該備份主機(jī)可存取的目錄中。
*************************
當(dāng)這些個(gè)別的Script都測試好以后,接下來我們將他們放到crontab里面。找到您的crontab,它的位置可能在/var/spool/cron/crontabs/root、/etc/crontab、/var/cron/tabs/root。
在crontab中選擇以下之一加入(看您定期的時(shí)間):
Slackware : /var/spool/cron/crontabs/root
01 * * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每小時(shí)(太過火一點(diǎn))
30 16 * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每日16:30,下班前備份
30 16 * * 0 /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每周一16:30
0 5 1 * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每月一號(hào)5:0
RedHat/Debian : /etc/crontab
RedHat可直接將backup放入/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly。或采用如上加入/etc/crontab的方式:
有關(guān)crontab的用法,可查"man 5 crontab",在此不詳述。
備份主機(jī)的設(shè)定類同。
注意: 所有機(jī)器不要同時(shí)進(jìn)行備份,否則網(wǎng)路會(huì)大塞車。備份主機(jī)收取備份的時(shí)間要設(shè)為最后,否則會(huì)收不到備份資料。您可以在實(shí)作后,將時(shí)間間隔調(diào)整一下。
*************************
看看,兩個(gè)小小不到三行的Shell Script,配合cron這個(gè)定時(shí)工具。可以讓原本需要耗時(shí)多個(gè)小時(shí)的人工備份工作,簡化到不到十分鐘。善用您的想像力,多加一點(diǎn)變化,可你讓您的生活變得輕松異常,快樂悠哉。
檔案系統(tǒng)檢查
系統(tǒng)安全一向是大多數(shù)電腦用戶關(guān)心的事,在UNIX系統(tǒng)中,最重視的事,即系統(tǒng)中有沒有"木馬"(Trojan horse)。不管Trojan horse如何放進(jìn)來的,有一點(diǎn)始終會(huì)不變,即被放置木馬的檔案,其檔案日期一定會(huì)被改變,甚至?xí)衅渌臓顟B(tài)改變。此外,許多狀況下,系統(tǒng)會(huì)多出一些不 知名的檔案。因此,平日檢查整個(gè)檔案系統(tǒng)的狀態(tài)是否有被改變,將所有狀態(tài)有改變的檔案,以及目前有那些程式正在執(zhí)行,自動(dòng)報(bào)告給系統(tǒng)管理員,是個(gè)避免坐上 "木馬"的良方。
*************************
#!/bin/sh
# Filename : whatever_you_name_it
DIRS="/etc /home /bin /sbin /usr/bin /usr/sbin /usr/local /var /your_directory"
ADMIN="email@your.domain.com"
FROM="admin@your.domain.com"
# 寫入Sendmail的標(biāo)頭
echo "Subject: $HOSTNAME filesystem check" > /tmp/today.mail
echo "From: $FROM" >> /tmp/today.mail
echo "To: $ADMIN" >> /tmp/today.mail
echo "This is filesystem report comes from $HOSTNAME" >> /tmp/today.mail
# 報(bào)告目前正在執(zhí)行的程式
ps axf >> /tmp/today.mail
# 檔案系統(tǒng)檢查
echo "File System Check" >> /tmp/today.mail
ls -alR $DIRS | gzip -9 > /tmp/today.gz
zdiff /tmp/today.gz /tmp/yesterday.gz >> /tmp/today.mail
mv -f /tmp/today.gz /tmp/yesterday.gz
# 寄出信件
sendmail -t < /tmp/today.mail
然后把它放到一個(gè)不顯眼的地方去,讓別人找不到。
把它加入crontab中。
30 7 * * * /full_check_script_path/whatever_you_name_it 1> /dev/null 2> /dev/null #上班前檢查
有些檔案是固定會(huì)更動(dòng)的,像/var/log/messages、/var/log/syslog、/dev/ttyX等等,不要太大驚小怪。
控制圈for
演示了幾個(gè)簡單的Shell Script,相信您應(yīng)該對(duì)Shell Script有點(diǎn)概念了。現(xiàn)在我們開始來仔細(xì)研究一些較高等的Shell Script寫作。一些進(jìn)一步的說明,例如"$"、">"、"<"、">>"、"1>"、"2>"符號(hào)的使用,會(huì)在 稍后解釋。
*************************
for name [ in word; ] do list ; done
控制圈。
word是一序列的字,for會(huì)將word中的個(gè)別字展開,然后設(shè)定到name上面。list是一序列的工作。如果[in word;]省略掉,那么name將會(huì)被設(shè)定為Script后面所加的參數(shù)。
*************************
例一:
#!/bin/sh
for i in a b c d e f ; do
echo $i
done
它將會(huì)顯示出a到f。
*************************
例二: 另一種用法,A-Z
#!/bin/sh
WORD="a b c d e f g h i j l m n o p q r s t u v w x y z"
for i in $WORD ; do
echo $i
done
這個(gè)Script將會(huì)顯示a到z。
*************************
例三 : 修改副檔名
如果您有許多的.txt檔想要改名成.doc檔,您不需要一個(gè)一個(gè)來。
#!/bin/sh
FILES=`ls /txt/*.txt`
for txt in $FILES ; do
doc=`echo $txt | sed "s/.txt/.doc/"`
mv $txt $doc
done
這樣可以將*.txt檔修改成*.doc檔。
*************************
例四 : meow
#!/bin/sh
# Filename : meow
for i ; do
cat $i
done
當(dāng)您輸入"meow file1 file2 ..."時(shí),其作用就跟"cat file1 file2 ..."一樣。
*************************
例五 : listbin
#!/bin/sh
# Filename : listbin
for i in /bin/* ; do
echo $i
done
當(dāng)您輸入"listbin"時(shí),其作用就跟"ls /bin/*"一樣。
*************************
例六 : /etc/rc.d/rc
拿一個(gè)實(shí)際的例來說,Red Hat的/etc/rc.d/rc的啟動(dòng)程式中的一個(gè)片斷。
for i in /etc/rc.d/rc$runlevel.d/S*; do
# Check if the script is there.
[ ! -f $i ] && continue
# Check if the subsystem is already up.
subsys=${i#/etc/rc.d/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] || \
[ -f /var/lock/subsys/${subsys}.init ] && continue
# Bring the subsystem up.
$i start
done
這個(gè)例中,它找出/etc/rc.d/rcX.d/S*所有檔案,檢查它是否存在,然后一一執(zhí)行。
流程控制case
case word in [ pattern [ | pattern ] ... ) list ;; ] ... esac
case/esac的標(biāo)準(zhǔn)用法大致如下:
case $arg in
pattern | sample) # arg in pattern or sample
;;
pattern1) # arg in pattern1
;;
*) #default
;;
esac
arg是您所引入的參數(shù),如果arg內(nèi)容符合pattern項(xiàng)目的話,那么便會(huì)執(zhí)行pattern以下的程式碼,而該段程式碼則以兩個(gè)分號(hào)";;"做結(jié)尾。
可以注意到"case"及"esac"是對(duì)稱的,如果記不起來的話,把"case"顛倒過來即可。
*************************
例一 : paranoia
#!/bin/sh
case $1 in
start | begin)
echo "start something"
;;
stop | end)
echo "stop something"
;;
*)
echo "Ignorant"
;;
esac
執(zhí)行
[foxman@foxman bash]# chmod 755 paranoia
[foxman@foxman bash]# ./paranoia
Ignorant
[foxman@foxman bash]# ./paranoia start
start something
[foxman@foxman bash]# ./paranoia begin
start something
[foxman@foxman bash]# ./paranoia stop
stop something
[foxman@foxman bash]# ./paranoia end
stop something
*************************
例二 : inetpanel
許多的daemon都會(huì)附上一個(gè)管理用的Shell Script,像BIND就附上ndc,Apache就附上apachectl。這些管理程式都是用shell script來寫的,以下示一個(gè)管理inetd的shell script。
#!/bin/sh
case $1 in
start | begin | commence)
/usr/sbin/inetd
;;
stop | end | destroy)
killall inetd
;;
restart | again)
killall -HUP inetd
;;
*)
echo "usage: inetpanel [start | begin | commence | stop | end | destory | restart | again]"
;;
esac
*************************
例三 : 判斷系統(tǒng)
有時(shí)候,您所寫的Script可能會(huì)跨越好幾種平臺(tái),如Linux、FreeBSD、Solaris等等,而各平臺(tái)之間,多多少少都有不同之處,有時(shí)候需要判斷目前正在那一種平臺(tái)上執(zhí)行。此時(shí),我們可以利用uname來找出系統(tǒng)資訊。
#!/bin/sh
SYSTEM=`uname -s`
case $SYSTEM in
Linux)
echo "My system is Linux"
echo "Do Linux stuff here..."
;;
FreeBSD)
echo "My system is FreeBSD"
echo "Do FreeBSD stuff here..."
;;
*)
echo "Unknown system : $SYSTEM"
echo "I don't what to do..."
;;
esac
流程控制select
select name [ in word; ] do list ; done
select顧名思義就是在word中選擇一項(xiàng)。與for相同,如果[in word;]省略,將會(huì)使用Script后面所加的參數(shù)。
例:
#!/bin/sh
WORD="a b c"
select i in $WORD ; do
case $i in
a)
echo "I am A"
;;
b)
echo "I am B"
;;
c)
echo "I am C"
;;
*)
break;
;;
esac
done
執(zhí)行結(jié)果
[foxman@foxman bash]# ./select_demo
1) a
2) b
3) c
#? 1
I am A
1) a
2) b
3) c
#? 2
I am B
1) a
2) b
3) c
#? 3
I am C
1) a
2) b
3) c
#? 4
返回狀態(tài)Exit
在繼續(xù)下去之前,我們必須要切入另一個(gè)話題,即返回狀態(tài)值 - Exit Status。因?yàn)閕f/while/until都遷涉到了使用Exit Status來控制程式流程的問題。
*************************
許多人都知道,在許多語言中(C/C++/Perl....),都有一個(gè)exit的函數(shù),甚至連Bash自己都有個(gè)exit的內(nèi)建命令。而exit后面所帶的數(shù)字,便是返回狀態(tài)值 - Exit Status。
返回狀態(tài)值可以使得程式與程式之間,利用Shell script來結(jié)合的可能性大增,利用小程式,透過Shell script,來完成很雜的工作。
在shell中,返回值為零表示成功(True),非零值為失敗(False)。
*************************
舉例來說,以下這個(gè)兩個(gè)小程式y(tǒng)es/no分別會(huì)返回0/1(成功/失敗):
/* yes.c */
void main(void) { exit(0); }
/* no.c */
void main(void) { exit(1); }
那么以下這個(gè)"YES"的shell script便會(huì)顯示"YES"。
#!/bin/sh
# YES
if yes ; then
echo "YES"
fi
而"NO"不會(huì)顯示任何東西。
#!/bin/sh
# NO
if no ; then
echo "YES"
fi
*************************
test express
[ express ]
在Shell script中,test express/[ express ]這個(gè)語法被大量地使用,它是個(gè)非常實(shí)用的指令。由于它的返回值即Exit Status,經(jīng)常被運(yùn)用在if/while/until的場合中。而在后面,我們也會(huì)大量運(yùn)用到,在進(jìn)入介紹if/while/until之前,有必要 先解一下。
其返回值為0(True)或1(False),要看表述(express)的結(jié)果為何。
express格式
-b file : 當(dāng)檔案存在并且屬性是Block special(通常是/dev/xxx)時(shí),返回True。
-c file : 當(dāng)檔案存在并且屬性是character special(通常是/dev/xxx)時(shí),返回True。
-d file : 當(dāng)檔案存在并且屬性是目錄時(shí),返回True。
-e file : 當(dāng)檔案存在時(shí),返回True。
-f file : 當(dāng)檔案存在并且是正常檔案時(shí),返回True。
-g file : 當(dāng)檔案存在并且是set-group-id時(shí),返回True。
-k file : 當(dāng)檔案存在并且有"sticky" bit被設(shè)定時(shí),返回True。
-L file : 當(dāng)檔案存在并且是symbolic link時(shí),返回True。
-p file : 當(dāng)檔案存在并且是name pipe時(shí),返回True。
-r file : 當(dāng)檔案存在并且可讀取時(shí),返回True。
-s file : 當(dāng)檔案存在并且檔案大小大于零時(shí),返回True。
-S file : 當(dāng)檔案存在并且是socket時(shí),返回True。
-t fd : 當(dāng)fd被開啟為terminal時(shí),返回True。
-u file : 當(dāng)檔案存在并且set-user-id bit被設(shè)定時(shí),返回True。
-w file : 當(dāng)檔案存在并且可寫入時(shí),返回True。
-x file : 當(dāng)檔案存在并且可執(zhí)行時(shí),返回True。
-O file : 當(dāng)檔案存在并且是被執(zhí)行的user id所擁有時(shí),返回True。
-G file : 當(dāng)檔案存在并且是被執(zhí)行的group id所擁有時(shí),返回True。
file1 -nt file2 : 當(dāng)file1比file2新時(shí)(根據(jù)修改時(shí)間),返回True。
file1 -ot file2 : 當(dāng)file1比file2舊時(shí)(根據(jù)修改時(shí)間),返回True。
file1 -ef file2 : 當(dāng)file1與file2有相同的device及inode number時(shí),返回True。
-z string : 當(dāng)string的長度為零時(shí),返回True。
-n string : 當(dāng)string的長度不為零時(shí),返回True。
string1 = string2 : string1與string2相等時(shí),返回True。
string1 != string2 : string1與string2不相等時(shí),返回True。
! express : express為False時(shí),返回True。
expr1 -a expr2 : expr1及expr2為True。
expr1 -o expr2 : expr1或expr2其中之一為True。
arg1 OP arg2 : OP是-eq[equal]、-ne[not-equal]、-lt[less-than]、-le[less-than-or-equal]、-gt [greater-than]、-ge[greater-than-or-equal]的其中之一。
*************************
在Bash中,當(dāng)錯(cuò)誤發(fā)生在致命信號(hào)時(shí),bash會(huì)返回128+signal number做為返回值。如果找不到命令,將會(huì)返回127。如果命令找到了,但該命令是不可執(zhí)行的,將返回126。除此以外,Bash本身會(huì)返回最后一個(gè) 指令的返回值。若是執(zhí)行中發(fā)生錯(cuò)誤,將會(huì)返回一個(gè)非零的值。
Fatal Signal : 128 + signo
Can't not find command : 127
Can't not execute : 126
Shell script successfully executed : return the last command exit status
Fatal during execution : return non-zero
流程控制if
if list then list [ elif list then list ] ... [ else list ] fi
幾種可能的寫法
*************************
第一種
if list then
do something here
fi
當(dāng)list表述返回值為True(0)時(shí),將會(huì)執(zhí)行"do something here"。
例一 : 當(dāng)我們要執(zhí)行一個(gè)命令或程式之前,有時(shí)候需要檢查該命令是否存在,然后才執(zhí)行。
if [ -x /sbin/quotaon ] ; then
echo "Turning on Quota for root filesystem"
/sbin/quotaon /
fi
例二 : 當(dāng)我們將某個(gè)檔案做為設(shè)定檔時(shí),可先檢查是否存在,然后將該檔案設(shè)定值載入。
# Filename : /etc/ppp/settings
PHONE=1-800-COLLECT
#!/bin/sh
# Filename : phonebill
if [ -f /etc/ppp/settings ] ; then
source /etc/ppp/settings
echo $PHONE
fi
執(zhí)行
[foxman@foxman ppp]# ./phonebill
1-800-COLLECT
*************************
第二種
if list then
do something here
else
do something else here
fi
例三 : Hostname
#!/bin/sh
if [ -f /etc/HOSTNAME ] ; then
HOSTNAME=`cat /etc/HOSTNAME`
else
HOSTNAME=localhost
fi
*************************
第三種
if list then
do something here
elif list then
do another thing here
fi
例四 : 如果某個(gè)設(shè)定檔允許有好幾個(gè)位置的話,例如crontab,可利用if then elif fi來找尋。
#!/bin/sh
if [ -f /etc/crontab ] ; then
CRONTAB="/etc/crontab"
elif [ -f /var/spool/cron/crontabs/root ] ; then
CRONTAB="/var/spool/cron/crontabs/root"
elif [ -f /var/cron/tabs/root ] ; then
CRONTAB="/var/cron/tabs/root"
fi
export CRONTAB
*************************
第四種
if list then
do something here
elif list then
do another thing here
else
do something else here
fi
例五 : 我們可利用uname來判斷目前系統(tǒng),并分別做各系統(tǒng)狀況不同的事。
#!/bin/sh
SYSTEM=`uname -s`
if [ $SYSTEM = "Linux" ] ; then
echo "Linux"
elif [ $SYSTEM = "FreeBSD" ] ; then
echo "FreeBSD"
elif [ $SYSTEM = "Solaris" ] ; then
echo "Solaris"
else
echo "What?"
fi
控制圈while/until
while list do list done
當(dāng)list為True時(shí),該圈會(huì)不停地執(zhí)行。
例一 : 無限回圈寫法
#!/bin/sh
while : ; do
echo "do something forever here"
sleep 5
done
例二 : 強(qiáng)迫把pppd殺掉。
#!/bin/sh
while [ -f /var/run/ppp0.pid ] ; do
killall pppd
done
*************************
until list do list done
當(dāng)list為False(non-zero)時(shí),該圈會(huì)不停地執(zhí)行。
例一 : 等待pppd上線。
#!/bin/sh
until [ -f /var/run/ppp0.pid ] ; do
sleep 1
done
參數(shù)與變數(shù)
在繼續(xù)下去介紹function之前,我們必須停下來介紹"參數(shù)與變數(shù)"。
*************************
參數(shù)(Parameters)是用來儲(chǔ)存"值"的資料型態(tài),有點(diǎn)像是一般語言中的變數(shù)。它可以是個(gè)名稱(name)、數(shù)字(number)、或者是以下所列出來一些特殊符號(hào)(Special Parameters)。
在shell中,變數(shù)是由name形式的參數(shù)所構(gòu)成的。
*************************
在前面的許多例中,我們事實(shí)上已經(jīng)看到許多參數(shù)的運(yùn)用。要設(shè)定一個(gè)Parameter實(shí)際很簡單:
name=value
例如說:
MYHOST="foxman"
而要使用它時(shí),則是加個(gè)"$"符號(hào)。
echo $MYHOST
*************************
位置參數(shù)(Positional Parameters)
*************************
所謂的位置參數(shù)便是0,1,2,3,4,5,6,7,8,9...。使用時(shí),用$0,$1,$2...。
位置參數(shù)是當(dāng)script被載入時(shí),后面所附加的參數(shù)。$0是本身,$1則為第一個(gè)參數(shù),$2為第二個(gè),依此類推。而當(dāng)Positional Parameters被function所使用時(shí),它們會(huì)被暫時(shí)取代(下一節(jié)會(huì)介紹function)。
例如以下這個(gè)script:
#!/bin/sh
# Filename : position
echo $0
echo $1
執(zhí)行時(shí):
[foxman@foxman bash]# ./position abc
./position
abc
當(dāng)位置參數(shù)超過兩位數(shù)時(shí),有特別的方法來展開,稱為Expansion。
*************************
特殊參數(shù)(Speical Parameters)
這些符號(hào),非常不人性,對(duì)新手來說很困擾。但上手后,會(huì)覺得方便無比,有些如果您看不懂的話,就--算了,不用浪費(fèi)太多時(shí)間在上面。
*************************
* 星號(hào)
將Positional Parameters合成一個(gè)參數(shù),其間隔為IFS內(nèi)定參數(shù)的第一個(gè)字元(見內(nèi)建變數(shù)一節(jié))。
例:
#!/bin/sh
# starsig
echo $*
執(zhí)行:
[foxman@foxman bash]# starsig a b c d e f g
a b c d e f g
*************************
@ at符號(hào)
與*星號(hào)類同。不同之處在于不參照IFS。
例:
#!/bin/sh
# atsig
echo $@
執(zhí)行:
[foxman@foxman bash]# atsig a b c d e f g
a b c d e f g
*************************
# 井字號(hào)
展開Positional parameters的數(shù)量。
例:
#!/bin/sh
# poundsig
echo $#
執(zhí)行
[foxman@foxman bash]# poundsig a b c d e f g
7
*************************
? 問號(hào)
最近執(zhí)行的foreground pipeline的狀態(tài)。
*************************
- 減號(hào)
最近執(zhí)行的foreground pipeline的選項(xiàng)參數(shù)。
*************************
$ 錢錢錢
本身的Process ID。
[foxman@foxman bash]# ps ax | grep bash
1635 p1 S 0:00 /bin/bash
[foxman@foxman bash]# echo $$
1635
*************************
! 驚號(hào)
最近執(zhí)行背景命令的Process ID。
*************************
0 零
在Positional Parameters一部份已經(jīng)說明過了,是執(zhí)行的shell script本身。但如果是用"bash -c",則$0被設(shè)為第一個(gè)參數(shù)。
[foxman@foxman bash]# echo $0
/bin/bash
*************************
_ 底線符號(hào)
顯示出最后一個(gè)執(zhí)行的命令。
[foxman@foxman bash]# echo $_
bash
*************************
內(nèi)建變數(shù)(Shell Variables)
Bash有許多內(nèi)建變數(shù),像PATH、HOME、ENV......等等。這些內(nèi)建變數(shù)將在另一節(jié)中,專門一一說明。
函數(shù)function
[ function ] name () { list; }
function的參數(shù)是Positional Paraments。
例
#!/bin/sh
function func() {
echo $1
echo $2
return 1
}
func "Hello" "function"
局部變數(shù)可用local來宣告。
函數(shù)可export,使用下一層的shell可以使用。
函數(shù)可遞,沒有遞層數(shù)的限制。
Bash內(nèi)建指令集
以下的命令,大部份都沒有使用例,您可能會(huì)看不出所以然,摸不著頭腦。在我加入例說明前,建議您"man bash",然后自己實(shí)際操作一次。
*************************
: [arguments]
不做任何事,除了[arguments]一些參數(shù)展開及一些特定重導(dǎo)向的作業(yè)外。
永遠(yuǎn)返回零。它的用法跟true一樣。
*************************
. filename [arguments]
source filename [arguments]
由filename中讀取命令,并執(zhí)行。
您會(huì)在/etc/rc.d/*中發(fā)現(xiàn)很多
. /xxxx
的指令,而xxxx的permission都不是可執(zhí)行的。事實(shí)上,在tcsh中,需要用
source /xxxx
來做同樣的指令。
注意到"."的后面是有空格的(比較一下". /"跟"./",不一樣)。filename是內(nèi)含指令的純文字檔即可,無須chmod 755 filename。
例
filename : my_source
DEV=lo
IP=127.0.0.1
NETMASK=255.0.0.0
BROADCAST=127.255.255.255
ifconfig $IP netmask $NETMASK broadcast $BROADCAST dev $DEV
接下來
. my_source
或
source my_source
便可執(zhí)行該script,而不需要"chmod 755 my_source"
*************************
alias [name[=value] ...]
昵稱命令
例如您如果來自DOS的世界,對(duì)UNIX的指令不習(xí)慣,可用alias來修改,以符合您的習(xí)慣。
例
alias ls="ls --color"
alias dir="ls"
alias cd..="cd .."
alias copy="cp -f" # dangerous, recommend, "cp -i"
alias del="rm -f" # dangerous, recommend, "rm -i"
alias move="mv -f" # dangerous, recommend, "mv -i"
alias md="mkdir"
alias rd="rmdir"
*************************
unalias [-a] [name ...]
unalias取消alias的設(shè)定。"unalias -a"將全部alias取消。
例
unalias copy
*************************
bg [jobspec]
將指定任務(wù)放到背景中,如果jobspec未指定,內(nèi)定為目前的。
*************************
fg [jobspec]
將指定任務(wù)放到前景中,如果jobsepc沒有指定,那么內(nèi)定為目前的。
*************************
jobs [-lnp] [ jobspec ... ]
第一種形式列出目前正在工作的任務(wù)。
-l : 除了列出一般資訊外,還列出Process IDs。
-p : 僅列出該工作群"首腦"(Process group leader)的Process ID.
-n : 則僅列出有改變的jobs的狀態(tài)。
如果給定jobspec,輸出資訊則只有該jobspec。
返回值為零,除非有非法的選項(xiàng)發(fā)生。
jobs -x command [ args ... ]
如果使用第二種形式(-x),jobs取代指定的command及args,并執(zhí)行返回其Exit Status。
*************************
kill [-s sigspec | -sigspec] [pid | jobspec] ...
將sigspec的信號(hào)送到pid或jobspec。
sigspec可以是SIGKILL/KILL這種形式或是信號(hào)號(hào)碼。如果sigspec是signal name,則大小寫無關(guān),而且可以沒有SIG。
kill -l [signum]
列出信號(hào)名稱。
[foxman@foxman bash]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGIOT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR
*************************
wait [n]
等待指定的行程,并返回其結(jié)束狀態(tài)。n可以是個(gè)jobspec或Process ID。如果n未指定,則等待所有的子行程,及返回值為零。若n為不存在的job或process,則返回127。否則,返回值為最后一個(gè) job/process的Exit Status。
*************************
bind [-m keymap] [-lvd] [-q name]
bind [-m keymap] -f filename
bind [-m keymap] keyseq:function-name
顯示出目前readline的按鍵及鏈結(jié)函數(shù)設(shè)定或是巨集。
-m keymap : 設(shè)定keymap binding。
-l : 顯示出所有readline function的名稱。
-v : 顯示出目前的function name及bindings。
-d : 顯示出function name及bindings。
-f filename : 從filename讀取key bindings。
-q function : 詢問那個(gè)按鍵觸發(fā)function。
*************************
break [n]
跳出控制回圈for/while/until中使用。如果有指定n,則跳出n層。n必須是大于等于1。若n大于巢狀圈數(shù),則所有的圈都會(huì)跳離。返回值回零。
*************************
continue [n]
還原控制回圈for/while/until中使用。如果有指定n,則返回n層。n必須是大于等于1。若n大于巢狀圈數(shù),則還原到最上層。返回值回零。
*************************
exit [n]
離開程式。n是Exit Status。
*************************
return [n]
在function中使用。n為返回值,其作用與Exit Status一樣。
*************************
builtin shell-builtin [arguments]
執(zhí)行內(nèi)建函數(shù)。當(dāng)您定義了與內(nèi)建函數(shù)相同的指令時(shí),可用此命令來執(zhí)行內(nèi)建函數(shù)。
*************************
cd [dir]
更換目錄到dir。如果沒有指定,內(nèi)定為HOME所指定的目錄。
*************************
command [-pVv] command [arg ...]
用command指定可取消正常的shell function尋找。只有內(nèi)建命令及在PATH中找得到的才會(huì)被執(zhí)行。"-p"選項(xiàng),搜尋命令的方式是用PATH來找。"-V"或"-v"選項(xiàng),會(huì)顯示出該命令的一些簡約描述。
*************************
declare [-frxi] [name[=value]]
typeset [-frxi] [name[=value]]
宣告參數(shù)并給它們?cè)O(shè)定屬性。如果沒有給定名稱,將會(huì)顯示各參數(shù)值。
-f : 僅使用函數(shù)名稱。
-r : 將name設(shè)為readonly。
-x : 將name輸出給后續(xù)環(huán)境使用。
-i : 該參數(shù)被設(shè)為integer來使用,可用于算術(shù)表述。
用"+"時(shí),關(guān)閉該屬性。
*************************
dirs [-l] [+/-n]
顯示目前記憶的目錄。目錄可透過pushd/popd來操作。
+n : 顯示開始的記錄n個(gè)。
-n : 顯示結(jié)尾的記錄n個(gè)。
-l : 顯示較多的資訊。
*************************
echo [-neE] [arg ...]
輸出顯示args,由空白分隔。返回值永為零。
-n : 不跳行。
-e : 啟動(dòng)"\"符號(hào)的解譯。
-E : 將ESC解譯功能取消。
"\a" : alert(bell),發(fā)出聲響。
"\b" : backspace,倒退。
"\c" : suppress trailing newline,不跳行。
"\f" : form feed,跳行跳格。
"\n" : new line,新行。
"\r" : carriage return,回到行起點(diǎn)。
"\t" : horizontal tab,水平跳位。
"\v" : vertical tab,垂直跳位。
"\\" : 輸出"\"。
"\nnn" : 輸出ASCII Code號(hào)碼nnn(八進(jìn)位)。
*************************
enable [-n] [-all] [name ...]
啟動(dòng)或關(guān)閉內(nèi)建函數(shù)命令。使用"-n"將所有指定命令皆關(guān)閉,否則都是啟動(dòng)的。如果只有"-n"參數(shù),它將會(huì)顯示所有關(guān)閉的函數(shù)。如果只有"-all",它將會(huì)顯示所有內(nèi)建命令。
*************************
eval [arg ...]
讀取args,并將args合為一個(gè)命令,然后執(zhí)行。其返回值成為eval的返回值。如果沒有參數(shù),eval返回True。
*************************
exec [[-] command [arguments]]
當(dāng)命令執(zhí)行時(shí),該命令取代shell,沒有新的process產(chǎn)生。如果第一個(gè)參數(shù)是"-",shell會(huì)將"-"放入第零個(gè)參數(shù),傳給command。
*************************
export [-nf] [name[=word]] ...
export -p
將name輸出給環(huán)境,給往后的命令使用。"-f"選項(xiàng)表示name是函數(shù)。"-p"顯示出所有export的名稱。"-n"移除name。
*************************
set [--abefhkmnptuvxldCHP] [-o option] [arg ...]
-a : 自動(dòng)將變數(shù)標(biāo)記為可讓后面環(huán)境所使用。
-b : 立即報(bào)告被終結(jié)的背景程式狀態(tài)。
-e : 當(dāng)命令(simple-command,見后面)返回非零值時(shí),立即跳出。
-f : 取消pathname expansion。
-h : 找出所記憶的函數(shù)命令位置。
-k : 所有keyword參數(shù)都放到環(huán)境中。
-m : 監(jiān)督模式。
-n : 讀取命令,但不要執(zhí)行。可用于語法檢查。
-p : 打開privileged模式。
-t : 當(dāng)讀取一個(gè)命令并執(zhí)行后,立即離開。
-u : 當(dāng)參數(shù)展開時(shí),把unset參數(shù)當(dāng)成是錯(cuò)誤。
-v : 列出shell input lines。
-x : 在展開每個(gè)simple-command后,bash顯示展開值在PS4上。
-l : 儲(chǔ)存并還原name binding在for語法中。
-d : 關(guān)閉hasing command搜尋。
-C : 跟`noclobber=`一樣。請(qǐng)見內(nèi)定參數(shù)一節(jié)。
-H : 啟動(dòng)! style history substitution。
-P : 在使用像cd這種指令時(shí),不要跟隨symbolic links。
-- : "--"之后,沒有參數(shù)跟在后面。
- : 指定將所有后面的參數(shù)當(dāng)成是位置參數(shù)。
-o option-name : option-name可以是以下之一
allexport : 與"-a"相同。
braceexpand : 啟動(dòng)Brace Expansion。這是內(nèi)定設(shè)定。
emacs : 使用emacs-style命令列編輯界面。
errexit : 與"-e"相同。
histexpand : 與"-H"相同。
ignoreeof : 效果跟`IGNOREEOF=10`一樣。
interactive-commands : 允許#做為解。
monitor : 與"-m"相同。
noclobber : 與"-C"相同。
noexec : 與"-n"相同。
noglob : 與"-f"相同。
nohash : 與"-d"相同。
notify : 與"-b"相同。
nounset : 與"-u"相同。
physical : 與"-P"相同。
posix : Bash行為修改為Posix 1003.2標(biāo)準(zhǔn)。
privileged : 與"-p"相同。
verbose : 與"-v"相同。
vi : 使用vi-style命令列編輯程式。
xtrace : 與"-x"相同。
*************************
unset [-fv] [name ...]
移除對(duì)映于name的參數(shù)。要注意PATH、IFS、PPID、PS1、PS2、UID、EUID不能unset。若RANDOM、SECONDS、 LINENO、HISTCMD被unset,它們會(huì)喪失原有意義,既始它們后來被重設(shè)也一樣。返回值為True,除非name是不能被unset的。
*************************
fc [-e ename] [-nlr] [first] [last]
fc -s [pat=rep] [cmd]
修正命令。
*************************
getopts optstring name [args]
解析位置參數(shù)。
*************************
help [pattern]
顯示協(xié)助資訊。
*************************
history [n]
history -rwan [filename]
沒有參數(shù)時(shí),會(huì)顯示所下命令的歷史記錄。帶有參數(shù)"n"則顯示最后n個(gè)。
其它參數(shù)如下:
-a : 新增"新歷史"到歷史檔中。
-n : 讀取尚未讀到歷史中的記錄。
-r : 讀取filename做為歷史檔,并用它為目前歷史記錄。
-w : 將現(xiàn)有歷史記錄寫到filename中。
*************************
let arg [arg ...]
算術(shù)表述。請(qǐng)參考算術(shù)表述一節(jié)。
*************************
local [name[=value] ...]
產(chǎn)生一個(gè)局部參數(shù)。如果用于function,則其作用圍在function內(nèi)及其子函數(shù)。
*************************
logout
離開login shell。
*************************
popd [+/-n]
移除目錄堆疊。"+n"移除上面n個(gè),"-n"移除下面n個(gè)。
*************************
pushd [dir]
pushd +/-n
將目錄新增到目錄堆疊的最上面。"+n"旋轉(zhuǎn)該堆疊,使第n個(gè)目錄變成最上面。"-n"旋轉(zhuǎn)該堆疊,使倒數(shù)第n個(gè)目錄變成最上面。
*************************
pwd
列出目前工作目錄的絕對(duì)路徑。
*************************
read [-r] [name ...]
讀進(jìn)一行,然后第一個(gè)字設(shè)到第一個(gè)name,第二個(gè)設(shè)到第二個(gè)name,依此類推。如果沒有name在參數(shù)中,則read會(huì)將值設(shè)到REPLY。返回值為零,除非遇到End-Of-File。若有"-r"選項(xiàng),則"\n"被考慮為該行的一部份。
*************************
readonly [-f] [name ...]
readonly -p
將給定的name標(biāo)記為readonly。如果是"-f"選項(xiàng),則函數(shù)也一樣被標(biāo)記為readonly。"-p"會(huì)列出所有readonly的name。"--"取消檢查剩余的參數(shù)。
*************************
shift [n]
Positional Parameters從n+1...開始,會(huì)被改為$1...。n若為零,則沒有改變。n若未給定,則內(nèi)定為1。n必須是非負(fù)數(shù),并且小于或等于$#。若n大于$#,則沒有改變。返回值為零,除非n大于$#或小于零。
*************************
suspend [-f]
暫停這個(gè)shell的執(zhí)行,直到它收到SIGCONT信號(hào)。"-f"選項(xiàng)則是叫l(wèi)ogin shell不要抱怨,不過還是一樣暫停。返回狀態(tài)零,除非該shell是個(gè)login shell,而且沒有"-f"選項(xiàng)。
*************************
test expr
[ expr ]
我們?cè)贓xit Status的部份已經(jīng)說過了,不再重。
*************************
times
列出該shell的累積的使用者及系統(tǒng)時(shí)間及從shell執(zhí)行的process時(shí)間,返回值為零。
------------------------------------------------------------------------------
trap [-l] [arg] [sigspec]
當(dāng)收到sigspec信號(hào)時(shí),執(zhí)行arg命令。"-l"顯示出信號(hào)名稱及號(hào)碼。
*************************
type [-all] [-type | -path] name [name ...]
沒有參數(shù)的狀況下,它會(huì)顯示出shell如何解譯name做為命令。如果有"-type",它將會(huì)顯示alias、keyword、 function、builtin或file。如果有"-path"的參數(shù),它將會(huì)顯示該命令的路徑,找不到的話,不顯示任何東西。如果有"-all"的 參數(shù),它將會(huì)顯示所有可執(zhí)行name的可能路徑。type接受"-a"、"-t"、"-p"做為縮寫。
*************************
ulimit [-SHacdfmstpnuv [limit]]
ulimit提供了對(duì)shell的可獲取資源控制的功能。
-a : 報(bào)告目前所有限制。
-c : 設(shè)定最大可產(chǎn)生的core檔案。
-d : 行程資料段(process's data segment)最大值。
-f : 可被這個(gè)shell產(chǎn)生的最大檔案。
-m : resident set size最大值。
-s : 堆疊最大值。
-t : CPU TIME最大值(以秒計(jì)算)。
-p : pipe size in 512-byte blocks的最大值。
-n : 可開啟的file descriptors最大值。
-u : 單一使用者可使用的最大process數(shù)。
-v : 該shell最大虛擬記憶體可用值。
所有項(xiàng)目是以1024做為單位。
*************************
umask [-S] [mode]
將使用者的file-creation mask設(shè)為mode。"-S"選項(xiàng)將mask印成符號(hào)形式。
Bash內(nèi)建參數(shù)
PPID : 該bash的呼叫者process ID.
PWD : 目前的工作目錄。
OLDPWD : 上一個(gè)工作目錄。
REPLY : 當(dāng)read命令沒有參數(shù)時(shí),直接設(shè)在REPLY上。
UID : User ID。
EUID : Effective User ID。
BASH : Bash的完整路徑。
BASH_VERSION : Bash版本。
SHLVL : 每次有Bash執(zhí)行時(shí),數(shù)字加一。
RANDOM : 每次這個(gè)參數(shù)被用到時(shí),就會(huì)產(chǎn)生一個(gè)亂數(shù)在RANDOM上。
SECONDS : 從這個(gè)Shell一開始啟動(dòng)后的時(shí)間。
LINENO : Script的行數(shù)。
HISTCMD : 歷史記錄數(shù)。
OPTARG : getopts處理的最后一個(gè)選項(xiàng)參數(shù)。
OPTIND : 下一個(gè)要由getopts所處理的參數(shù)號(hào)碼。
HOSTTYPE : 機(jī)器種類。
OSTYPE : 作業(yè)系統(tǒng)名稱。
IFS : Internal Field Separator。
PATH : 命令搜尋路徑。
PATH="/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
HOME : 目前使用者的home directory;
CDPATH : cd命令的搜尋路徑。
ENV : 如果這個(gè)參數(shù)被設(shè)定,每次有shell script被執(zhí)行時(shí),將會(huì)執(zhí)行它所設(shè)定的檔名做為環(huán)境設(shè)定。
MAIL : 如果這個(gè)參數(shù)被設(shè)定,而且MAILPATH沒有被設(shè)定,那么有信件進(jìn)來時(shí),bash會(huì)通知使用者。
MAILCHECK : 設(shè)定多久時(shí)間檢查郵件一次。
MAILPATH : 一串的郵件檢查路徑。
MAIL_WARNING : 如果有設(shè)定的話,郵件被讀取后,將會(huì)顯示訊息。
PS1 : 提示訊息設(shè)定,內(nèi)定為"bash\$ "。(請(qǐng)?jiān)斠娞崾居嵪⒁还?jié)。)
PS2 : 第二提示訊息設(shè)定,內(nèi)定為"> "。
PS3 : select命令所使用的提示訊息。
PS4 : 執(zhí)行追蹤時(shí)用的提示訊息設(shè)定,內(nèi)定為"+ "。
HISTSIZE : 命令歷史記錄量,內(nèi)定為500。
HISTFILE : 歷史記錄檔,內(nèi)定~/.bash_history。
HISTFILESIZE : 歷史記錄檔行數(shù)最大值,內(nèi)定500。
OPTERR : 如果設(shè)為1,bash會(huì)顯示getopts的錯(cuò)誤。
PROMPT_COMMAND : 如果設(shè)定的話,該值會(huì)在每次執(zhí)行命令前都顯示。
IGNOREEOF : 將EOF值當(dāng)成輸入,內(nèi)定為10。
TMOUT : 如果設(shè)為大于零,該值被解譯為輸入等待秒數(shù)。若無輸入,當(dāng)成沒有輸入。
FCEDIT : fc命令的內(nèi)定編輯器。
FIGNORE : 請(qǐng)?jiān)斠奟EADLINE。
INPUTRC : readline的startup file,內(nèi)定~/.inputrc
notify : 如果設(shè)定了,bash立即報(bào)告被終結(jié)的背景程式。
history_control, HISTCONTROL : history使用。
command_oriented_history : 存入多行指令。
glob_dot_filenames : 如果設(shè)定了,bash將會(huì)把"."包含入檔案路徑中。
allow_null_glob_expansion : 如果設(shè)定了,bash允許路徑明稱為null string。
histchars : history使用。
nolinks : 如果設(shè)定了,執(zhí)行指令時(shí),不會(huì)跟隨symbolic links。
hostname_completion_file, HOSTFILE : 包含與/etc/hosts相同格式的檔名。
noclobber : 如果設(shè)定了,Bash不會(huì)覆寫任何由">"、">&"及"<>"所操作的檔案。
auto_resume : 請(qǐng)見任務(wù)控制一節(jié)。
no_exit_on_failed_exec : 如果該值存在,非互動(dòng)的shell不會(huì)因?yàn)閑xec失敗而跳出。
cdable_vars : 如果啟動(dòng),而cd命令找不到目錄,可切換到參數(shù)形態(tài)指定的目錄下。
提示符號(hào)
Bash使用PS1~PS4來顯示提示符號(hào),其格式如下:
*************************
\t : 現(xiàn)在時(shí)間。
\d : 現(xiàn)在日期。
\n : 新行。
\s : shell的名稱。
\w : 目前工作目錄。
\W : 目前工作目錄完整路徑。
\u : 使用者名稱。
\h : Hostname。
\# : 這個(gè)命令的號(hào)碼。
\! : 歷史號(hào)碼。
\$ : 如果EUID是0,則#,否則為$。
\nnn : 八進(jìn)位的字元。
\\ : "\"符號(hào)。
\[ : 開始一序列不可列印的字元。
\] : 結(jié)束一序列不可列印的字元。
算術(shù)表述
- +
! ~
* / %
+ -
<< >>
<= >= < >
== !=
&
^
|
&&
||
= *= /= %= += -= <<= >>= &= ^= |=
重導(dǎo)Redirection
>
>>
1>
.
.
語法
Simple Command
Pipelines
Lists
(list)
{ list; }