Shell Programming

转自:http://blog.csdn.net/lovechen508/archive/2006/04/08/655305.aspx

 

shell programming   
 
Shell

当我们登入 Linux 之後, 第一个接触到的, 便是 Shell. 我们必须对它有点初步的认识才行.

一. Shell 简介.

Linux 系统分成三个重要的部份

核心
Shell
工具程式
核心的部份相当低阶, 操作者不易和它直接沟通, 因此, 必须要有一个友善的介面(interface), 使得操作时能更为方便, 这个介面便是 Shell.

换言之, Shell 就是一个居於核心和操作者之间的一层使用者介面.

那麽, 为何称它为 Shell 呢? Shell 的本意是 "壳" 的意思呢!

没错, 在核心的外面, 包覆着一层外壳, 用来负责接收使用者输入的指令, 然後将指令解译成核心能够了解的方式, 传给核心去执行, 再将结果传回至预设的输出周边.

如图所示:

例如: 键入

ls -l

shell 给你以下回应:


档 有
案 档
种 案 档案大小 最近修改的
类 档案权限 数 拥有人 组别 (byte单位)日期及时间 档案名称
drwxr-xr-x 14 root root 1024 Jul 21 21:31 .
drwxr-xr-x 17 root root 1024 Apr 11 12:01 ..
drwxr-xr-x 8 82 82 1024 Feb 25 19:23 apache
-rw-r--r-- 1 root root 1335460 Feb 25 17:45 apache_1_3_4.tar.gz
drwxr-xr-x 6 root root 1024 Aug 31 1998 ftp
drwxr-xr-x 5 root root 1024 Aug 31 1998 httpd
drwx------ 2 james james 1024 Apr 23 06:47 james
drwxr-xr-x 2 root root 12288 Aug 31 1998 lost+found
drwxr-xr-x 2 msql nobody 1024 Dec 28 1998 msql
drwxr-xr-x 28 ols3 ols3 2048 Jul 19 21:38 ols3
drwxr-xr-x 3 1022 nobody 1024 Jan 25 23:40 ols3cgi
drwxrwxr-x 3 perl ols3 1024 Feb 2 07:11 perl
-rw------- 1 root root 2097152 Jul 21 18:39 quota.group
-rw------- 1 root root 1278656 Jul 21 18:39 quota.user
drwxrwxr-x 2 root nobody 1024 May 11 1998 samba
drwxr-xr-x 3 apache nobody 1024 Feb 25 16:58 temp
drwxrwxr-x 2 webadm nobody 1024 Mar 14 16:34 webadm

其实不只是 Linux 有这一层 Shell, 其它作业系统也有.
比如 DOS 的 command.com, Windows 的 GUI(Graphical User Interface), Mac 的 GUI.

Shell 按着表现的方式与读取使用者输入种类的不同, 可分为二大类:

Text base : 文字导向
Graph base: 图型导向
所谓 "读取使用者输入种类不同" 是指: 读取自键盘, 或读取自滑鼠, 其它 serial input, 萤幕触控等.

这样说来, Shell 好像只是命令直译器罢了?!
嗯, 这倒要按不同的 OS 所附给的 Shell 其功能和选择性的自由度而定.

以 DOS 的 COMMAND.COM 而言, 它就是一个十足的命令直译器, 除了一点点 batch 档的能力之外, 它的功能并不多. Win 平台的 GUI, 则是一个图型式的命令直译器, 介面十分友善. 不过, 这二种 OS, 不能让你自由而简单地选择 Shell.(以前 DOS 有 4dos 可选用)

Linux 的 shell, 除了做为命令直译器之外, 它也是一个不错的程式语言, 是系统管理维护时的重要工具.

由於 Unix 家族, 对 Shell 的处理, 采独立自由开放的方式, 因此, Shell 的种类相当地多, 更可以让人自由地更换(chsh).

目前流行的 shell 有:

Bourne shell : sh
C shell : csh
Korn shell: ksh (商业软体)
tcsh (free)
Bourne Again shell: bash (GNU)
Linux 的标准 shell 是采用 bash. 它也是我们要学习的主要对象.

二. Shell 的简史

第一个重要的 shell 是 Bourne shell (如此命名是为了纪念此 shell 的发明者 Steven Bourne), 1979 年第一个流行的 Unix 版本 7 发行时, 开始使用 Bourne shell.

Bourne shell 的主档名为 sh, 因此, 日後人们便以 sh 为 Bourne shell 的主要识别名称.

虽然 Unix 上的 shell 有许多种, 但 Bourne shell 的地位至今仍然没有改变. 许多 Unix 系统中仍然使用 sh 做为重要的管理工具. (它的工作从开机到关机, 几乎无所不包)

第一个广为流行使用的 shell 变种是 C shell. C shell 主要附在 BSD 版的 Unix 系统中. 它的作者是柏克莱大学的 Bill Joy. C shell 主要是因为其语法和 C 语言相类似, 因而得名. 这使得 Unix 系统的程式师, 在学习 C shell 时, 感到相当地方便容易.

以上这二种形成 shell 的二大主流, 後来的变种 shell 大都攫取这二种 shell 的优点.

比如 Korn, tcsh 及 bash.

Bash shell 是 GNU 计划的重要工具软体之一, 也是 GNU 作业系统中标准的 shell.

Bash 相容於 sh, 因此, 许多早期开发出来的 Bourne shell 都可以继续在 bash 中运作. 现在我们安装好的 RedHat Linux 便是完全使用 Bash. (/bin/sh -> /bin/bash)

Bash 在 1988 年诞生, 最初的作者是 Brian Fox, Chet Ramey 於 *** 加入, 现在官方正式的维护者是 Chet Ramey, 他的工作便是持续不断地增强 bash 的功能.

1995~1996 期间推出 bash 2.0 , 在这之前, 广为使用的版本是 1.14.x, 它增加了许多新的功能, 以及更好的相容性.

当然, Bash 是完全免费的, 它是 Open Source 的一员, 原始码全部开放.

二. Bash 的功能.

Bash 具有以下功能:

相容於 Bourne shell (sh)
包含有 C shell 以及 Korn shell 中最好的功能.
具命令列编修的能力(您记得以前 DOS 中的 doskey 吗?)
工作控制(job control)的能力, 可控制前景及背景程式
具 shell 程式设计的能力, 可让您自订shell及设计程式, 管理系统.
三. 新版的 Bash 哪里抓取?

若欲抓取新版的 bash, 可至 http://www.gnu.org 或其 mirror 站台.

中研院 FTP 也是不错的选择. [url=ftp://ftp.sinica.edu.tw[/url] 或 [url]ftp://linux.sinica.edu.tw]ftp://ftp.sinica.edu.tw[/......ftp://linux.sinica.edu.tw[/url]

三. 开始使用 Bash

当你 login 进 Linux 主机时, 便开始和 bash 互动, 一直到你 logout 主机(下exit,logout,或按^D) 为止.

Bash 的提示符号为 $ (代表一般身份使用者), 当您具有 root 权限时, 提示符号则变为 #.

一旦出现提示符号时, 您便可以开始键入操作命令列(command line)了.

命令可分为二大类:

bash 内建的指令
程式
如果是 bash 内建的指令, 则由 bash shell 负责回应; 若是程式, 则 shell 会找出该程式, 然後将控制权交给核心, 由核心执行该程式, 执行完之後, 再将控制权交回给 shell.

怎麽知道那些指令是 bash 内建的, 那些是程式呢? 通常用 "which 指令", 若没有任何回应, 表示是内建的指令(除非该指令错误、不存在, 或该程式不在预设的搜寻路径之内), 例如下:

[ols3@ols3 /ols3]$ which echo    [没有回应, 表示是内建的指令]

[ols3@ols3 /ols3]$ which ls

/bin/ls

四. 命令列的格式.

命令列通常由好几个字串组成, 中间用空白或 tab 键分开. 如下所示:

command options arguments(或称为 parameters)
命令 选项 参数
rm -rf /home/ols3

除了空白和 tab 键之外, 每一部份, 我们称之为 token, 比如上面的例子中, 便有三个 token: rm, -rf, /home/ols3.

当键入此一命令列时, shell 首先将它分解成个别的 token, 然後判断是内建的指令, 或是程式, 再按之前提过的方式去执行.

怎麽知道一个命令或程式, 它有那些选项和参数呢? 通常 man 一下该指令, 就可以得到了. 例如:

man rm

另外, 多行指令也可以一下全部写在同一命令列中, 只要中间用 ; 分开, 如:

ls ; mkdir test ; clear

五. 现行目录和自家目录.

所谓现行目录(current directory)是指: 你现在所处的位置, 又称为工作目录(working directory).

欲知现行目录为何? 可下 pwd 指令便知.

所谓自家目录(home directory)是指: 当初 root 为你建立帐号时, 所指定给你的一个私人专用的目录, 也是你登入系统之後, 第一个进入的地方.

欲知自家目录, 可用下列方式:

cd    (然後直接按 Enter)
cd ~    (~ 代表自家目录)
cat /etc/passwd | grep 您的帐号
相关的技巧

cd ./myway (进入目前目录下的 myway 目录中) 
cd .. (回到上一层目录)
cd - (回到先前的目录)
六. 万用字元.

如果命令列的参数中, 含有档名, 那麽万用字元(wildcards)可以带来十分便利的操作. (不过若使用不当, 也是恶梦的开始)

如果各位以前有过 DOS 的操作经验, 应该还记得 * 及 ? 所代表的意义吧?!

以下是 bash 中使用的万用字元:

? 代表任何单一字元(character)
* 代表任何字串 (注意: 0 个以上的字元, 例: *yes 将包含 yes 或 yes-or-not)
[字元组合] 在中括号中的字元皆符合, 如: [a-z]代表所有的小写字母
[!字元组合] 不在中括号中的字元皆符合, 如: [!0-9]代表非数字的字元皆符合

七. 输入和输出与重新导向.

当 Linux 系统完成开机之後, 预设上, 便开有三个档案, 这三个档案是做为输入、输出以及显示错误之用的.

我们称之为:

标准输入: 通常是键盘, 档案代码为 0
标准输出: 通常是萤幕, 档案代码为 1
标准错误: 通常标准输出相同(也就是萤幕), 档案代码为 2
虽然系统已帮你设好了这三个档案, 但我们仍然可以视需要, 适时地改变输入,输出,及错误这三者至不同的地方. 这种改变标准输出入的动作, 我们称之为 "I/O 重新导向" (I/O Redirection).

例如:

ls -la > myfile 就是将查询的结果重新导向至 myfile 中(本来是应该出现在萤幕上的)

cat myfile 便可以看见 ls -la 的结果.

cat < myfile > youfile 就是将 myfile 的内容拷贝给 youfile.

> 代表将输出转向

< 代表将输入转向

另一个会将输出入转向的机制是 "管线" (Pipelines).

所谓的管线就是将一个程式的输出当成另一个程式的输入.

例如: cat /etc/passwd | grep ols3

上面这段指令的意思是说: 把 /etc/passwd 档的内容显示结果(即输出) 丢给 grep 这个指令当作输入值, 然後由 grep 从中找出包含关键字 ols3 的资料列.

八. 前景与背景工作.

Linux 是多人多工的作业系统, 这意谓 Linux 可以让多人同时使用, 更可以同时执行许多程式.

一般而言, 你所执行的指令会一直握着控制权, 一直到程式结束为止, 我们称为这样的执行工作是在前景工作(foreground jobs), 如果, 执行指令时, 你仍然可以再做其它的事情, 那我们就称它是在背景工作.

通常比较耗时间的工作, 我们会把它丢到背景去执行, 而这期间, 我们仍然可以和 shell 继续沟通, 下达其它命令给 shell 去执行.

例如: 我们想从中研院的 FTP 伺服器下载某一个目录中所有的档案, 但又不想等它执行完毕(因为这样耗时间,也很无聊), 可以用以下的方式来达成:

ncftp -R ftp://linux.sinica.edu.tw/pub1/redhat/powertools &

其中 & 这个符号便是将命令列丢到背景去执行的指令.

如果您想离线之後, 仍然令系统继续传档, 可以在前面再加一个 nohup 的指令, 如下:

nohup ncftp -R ftp://linux.sinica.edu.tw/pub1/redhat/powertools &

nohup 是 no hangup 即不挂断之意.

八. 特殊字元及引号.

有许多字元, 对 shell 来说, 是具有特殊意义的. 详列於下:

符号 意义
~ 自家目录
` 命令取代
# 解
$ 变数取值
& 背景工作
* 万用字元
( 子shell开始
) 子shell结束
/ 使特殊字元恢复本意
| 管线
[ 字元组合开始
] 字元组合结束
{ 命令区块开始
} 命令区块结束
; 命令分隔号
' 单引号(不具变数置换的功能)
" 双引号(具置换的功能)
< 输入转向
> 输出转向
/ 路径分隔号
? 万用字元
! 管线逻辑意义上的 NOT

九. 常用控制组合键.

我们在操作 Linux 时, 常会使用一些组合键来控制 shell 的活动.

详列如下:

组合键 意义
Ctrl - C 中止目前的命令
Ctrl - / 同上
Ctrl - D 输入结束, 即 EOF 之意 (如使用 mail 信件结束时); 或 logout 登出 Linux
Ctrl - Z 暂停目前的命令
Ctrl - M 相当按 Enter
Ctrl - S 暂停萤幕输出
Ctrl - Q 恢复萤幕输出
Ctrl - U 将命令列整列删除
Ctrl - ? 删除最後一个字元, 相当於按 Del

十. 指令练习.

指令 选项或参数 意义
ls
pwd
which
more
less
passwd
man
cat
touch
cd
mkdir
rmdir
cp
rm
head
tail
wc
grep
ps


----------------------------------------------------------------------------------------- 
 
Linux程式设计-11.Shell Script(bash)--(2)教学例
http://www.openchess.org/noitatsko/programming/ (2001-05-25 09:04:01)
"Hello world" Shell Script
照传统程式教学例,这一节介绍Shell Script的"Hello World"如何撰写。

--------------------------------------------------------------------------------

#!/bin/sh
# Filename : hello
echo "Hello world!"

--------------------------------------------------------------------------------

大家应该会注意到第一行的"#!/bin/sh"。在UNIX下,所有的可执行Script,不管是那一种语言,其开头都是"#!",例如Perl 是"#!/usr/bin/perl",tcl/tk是"#!/usr/bin/wish",看您要执行的Script程式位置在那里。您也可以用"#! /bin/bash"、"#!/bin/tcsh"等等,来指定使用特定的Shell。
echo是个bash的内建指令。

--------------------------------------------------------------------------------

接下来,执行hello这个script:
要执行一个Script的方式有很多种。

--------------------------------------------------------------------------------

第一种 : 将hello这个档案的权限设定为可执行。
[foxman@foxman bash]# chmod 755 hello
执行
[foxman@foxman bash]# ./hello
hello world

--------------------------------------------------------------------------------

第二种 : 使用bash内建指令"source"或"."。
[foxman@foxman bash]# source hello
hello world

[foxman@foxman bash]# . hello
hello world

--------------------------------------------------------------------------------

第三种 : 直接使用sh/bash/tcsh指令来执行。
[foxman@foxman bash]# sh hello
hello world

[foxman@foxman bash]# bash hello
hello world

--------------------------------------------------------------------------------

Bash执行选项

--------------------------------------------------------------------------------

-c string : 读取string来当命令。
-i : 互动介面。
-s : 由stdin读取命令。
- : 取消往後选项的读取。
-norc : 不要读~/.bashrc来执行。
-noprofile : 不要读/etc/profile、~/.bash_profile、~/.bash_login、~/.profile等等来执行。
-rcfile filename : 执行filename,而非~/.bashrc
-version : 显示版本。
-quiet : 启动时不要哩唆。
-login : 确保bash是个login shell。
-nobraceexpansion : 不要用curly brace expansion({}符号展开)。
-nolineediting : 不用readline来读取命令列。
-posix : 改采Posix 1003.2标准。


----------------------------------------------------------------------------------------- 
 
众所皆知地,UNIX上以小工具着名,利用许多简单的小工具,来完成原本需要大量软体开发的工作,这一点特色,使得UNIX成为许多人心目中理想的系统平台。
在众多的小工具中,Shell Script算得上是最基本、最强大、运用最广泛的一个。它运用围之广,不但从系统启动、程式编译、定期作业、上网连线,甚至安装整个Linux系统,都可以用它来完成。

因为Shell Script是利用您平日在使用的一些指令,将之组合起来,成为一个"程式"。如果您平日某些序列的指令下得特别频繁,便可以将这些指令组合起来,成为另 一个新的指令。这样,不但可以简化并加速操作速度,甚至还可以乾脆自动定期执行,大大简化系统管理工作。

--------------------------------------------------------------------------------

Bash(GNU Bourne-Again SHell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等 等,Shell Script大致都类同,当您学会一种Shell以後,其它的Shell会很快就上手,大多数的时候,一个Shell Script通常可以在很多种Shell上使用。
这里我介绍您bash的使用方法。事实上,当您"man bash"时,就可以看到bash的说明书,不过对许多人来说,这份说明书犹如"无字天书"一样难懂。这份文件,主要资料来源为"man bash",我加上一些实际日常的应用例来说明。希望这样能让那些始终不得其门而入的人们,多多少少能有点概念。


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(4)档案系统检查
http://www.openchess.org/noitatsko/programming/ (2001-05-25 11:00:00)
系 统安全一向是大多数电脑用户关心的事,在UNIX系统中,最重视的事,即系统中有没有"木马"(Trojan horse)。不管Trojan horse如何放进来的,有一点始终会不变,即被放置木马的档案,其档案日期一定会被改变,甚至会有其它的状态改变。此外,许多状况下,系统会多出一些不 知名的档案。因此,平日检查整个档案系统的状态是否有被改变,将所有状态有改变的档案,以及目前有那些程式正在执行,自动报告给系统管理员,是个避免坐 上"木马"的良方。

--------------------------------------------------------------------------------

#!/bin/sh
# Filename : whatever_you_name_it
DIRS="/etc /home /bin /sbin /usr/bin /usr/sbin /usr/local /var /your_directory"
ADMIN="[email protected] "
FROM="[email protected] "
# 写入Sendmail的标头
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
# 报告目前正在执行的程式
ps axf >> /tmp/today.mail
# 档案系统检查
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

然後把它放到一个不显眼的地方去,让别人找不到。

把它加入crontab中。

30 7 * * * /full_check_script_path/whatever_you_name_it 1> /dev/null 2> /dev/null #上班前检查

有些档案是固定会更动的,像/var/log/messages、/var/log/syslog、/dev/ttyX等等,不要太大惊小怪。


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(5)控制圈for
http://www.openchess.org/noitatsko/programming/ (2001-05-25 12:10:00)

示了几个简单的Shell Script,相信您应该对Shell Script有点概念了。现在我们开始来仔细研究一些较高等的Shell Script写作。一些进一步的说明,例如"$"、">"、"<"、">>"、"1>"、"2>"符号的使用,会在 稍後解释。

--------------------------------------------------------------------------------

for name [ in word; ] do list ; done
控制圈。
word是一序列的字,for会将word中的个别字展开,然後设定到name上面。list是一序列的工作。如果[in word;]省略掉,那麽name将会被设定为Script後面所加的参数。

--------------------------------------------------------------------------------

例一:
#!/bin/sh

for i in a b c d e f ; do
echo $i
done

它将会显示出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

这个Script将会显示a到z。

--------------------------------------------------------------------------------

例三 : 修改副档名
如果您有许多的.txt档想要改名成.doc档,您不需要一个一个来。
#!/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

当您输入"meow file1 file2 ..."时,其作用就跟"cat file1 file2 ..."一样。

--------------------------------------------------------------------------------

例五 : listbin
#!/bin/sh
# Filename : listbin

for i in /bin/* ; do
echo $i
done

当您输入"listbin"时,其作用就跟"ls /bin/*"一样。

--------------------------------------------------------------------------------

例六 : /etc/rc.d/rc
拿一个实际的例来说,Red Hat的/etc/rc.d/rc的启动程式中的一个片断。

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


-----------------------------------------------------------------------------------------
 
Linux程式设计-11.Shell Script(bash)--(6)流程控制case
http://www.openchess.org/noitatsko/programming/ (2001-05-25 13:04:01)
case word in [ pattern [ | pattern ] ... ) list ;; ] ... esac
case/esac的标准用法大致如下:
case $arg in
pattern | sample) # arg in pattern or sample
;;
pattern1) # arg in pattern1
;;
*) #default
;;
esac
arg是您所引入的参数,如果arg内容符合pattern项目的话,那麽便会执行pattern以下的程式码,而该段程式码则以两个分号";;"做结尾。

可以注意到"case"及"esac"是对称的,如果记不起来的话,把"case"颠倒过来即可。

--------------------------------------------------------------------------------

例一 : paranoia
#!/bin/sh
case $1 in
start | begin)
echo "start something"
;;
stop | end)
echo "stop something"
;;
*)
echo "Ignorant"
;;
esac

执行
[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都会附上一个管理用的Shell Script,像BIND就附上ndc,Apache就附上apachectl。这些管理程式都是用shell script来写的,以下示一个管理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

--------------------------------------------------------------------------------

例三 : 判断系统
有时候,您所写的Script可能会跨越好几种平台,如Linux、FreeBSD、Solaris等等,而各平台之间,多多少少都有不同之处,有时候需要判断目前正在那一种平台上执行。此时,我们可以利用uname来找出系统资讯。
#!/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


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(7)流程控制select
http://www.openchess.org/noitatsko/programming/ (2001-05-25 14:08:00)
select name [ in word; ] do list ; done
select顾名思义就是在word中选择一项。与for相同,如果[in word;]省略,将会使用Script後面所加的参数。

#!/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

执行结果
[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


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(8)返回状态Exit
http://www.openchess.org/noitatsko/programming/ (2001-05-25 15:00:00)
在继续下去之前,我们必须要切入另一个话题,即返回状态值 - Exit Status。因为if/while/until都迁涉到了使用Exit Status来控制程式流程的问题。

--------------------------------------------------------------------------------

许多人都知道,在许多语言中(C/C++/Perl....),都有一个exit的函数,甚至连Bash自己都有个exit的内建命令。而exit後面所带的数字,便是返回状态值 - Exit Status。
返回状态值可以使得程式与程式之间,利用Shell script来结合的可能性大增,利用小程式,透过Shell script,来完成很杂的工作。

在shell中,返回值为零表示成功(True),非零值为失败(False)。

--------------------------------------------------------------------------------

举例来说,以下这个两个小程式yes/no分别会返回0/1(成功/失败):
/* yes.c */
void main(void) { exit(0); }
/* no.c */
void main(void) { exit(1); }
那麽以下这个"YES"的shell script便会显示"YES"。
#!/bin/sh
# YES
if yes ; then
echo "YES"
fi
而"NO"不会显示任何东西。
#!/bin/sh
# NO
if no ; then
echo "YES"
fi

--------------------------------------------------------------------------------

test express
[ express ]
在Shell script中,test express/[ express ]这个语法被大量地使用,它是个非常实用的指令。由於它的返回值即Exit Status,经常被运用在if/while/until的场合中。而在後面,我们也会大量运用到,在进入介绍if/while/until之前,有必要 先解一下。

其返回值为0(True)或1(False),要看表述(express)的结果为何。

express格式

-b file : 当档案存在并且属性是Block special(通常是/dev/xxx)时,返回True。
-c file : 当档案存在并且属性是character special(通常是/dev/xxx)时,返回True。
-d file : 当档案存在并且属性是目录时,返回True。
-e file : 当档案存在时,返回True。
-f file : 当档案存在并且是正常档案时,返回True。
-g file : 当档案存在并且是set-group-id时,返回True。
-k file : 当档案存在并且有"sticky" bit被设定时,返回True。
-L file : 当档案存在并且是symbolic link时,返回True。
-p file : 当档案存在并且是name pipe时,返回True。
-r file : 当档案存在并且可读取时,返回True。
-s file : 当档案存在并且档案大小大於零时,返回True。
-S file : 当档案存在并且是socket时,返回True。
-t fd : 当fd被开启为terminal时,返回True。
-u file : 当档案存在并且set-user-id bit被设定时,返回True。
-w file : 当档案存在并且可写入时,返回True。
-x file : 当档案存在并且可执行时,返回True。
-O file : 当档案存在并且是被执行的user id所拥有时,返回True。
-G file : 当档案存在并且是被执行的group id所拥有时,返回True。
file1 -nt file2 : 当file1比file2新时(根据修改时间),返回True。
file1 -ot file2 : 当file1比file2旧时(根据修改时间),返回True。
file1 -ef file2 : 当file1与file2有相同的device及inode number时,返回True。
-z string : 当string的长度为零时,返回True。
-n string : 当string的长度不为零时,返回True。
string1 = string2 : string1与string2相等时,返回True。
string1 != string2 : string1与string2不相等时,返回True。
! express : express为False时,返回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中,当错误发生在致命信号时,bash会返回128+signal number做为返回值。如果找不到命令,将会返回127。如果命令找到了,但该命令是不可执行的,将返回126。除此以外,Bash本身会返回最後一个 指令的返回值。若是执行中发生错误,将会返回一个非零的值。
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


--------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(9)流程控制if
http://www.openchess.org/noitatsko/programming/ (2001-05-25 16:10:00)

if list then list [ elif list then list ] ... [ else list ] fi
几种可能的写法

--------------------------------------------------------------------------------

第一种
if list then
do something here
fi
当list表述返回值为True(0)时,将会执行"do something here"。

例一 : 当我们要执行一个命令或程式之前,有时候需要检查该命令是否存在,然後才执行。
if [ -x /sbin/quotaon ] ; then
echo "Turning on Quota for root filesystem"
/sbin/quotaon /
fi

例二 : 当我们将某个档案做为设定档时,可先检查是否存在,然後将该档案设定值载入。
# 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
执行
[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
例四 : 如果某个设定档允许有好几个位置的话,例如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来判断目前系统,并分别做各系统状况不同的事。
#!/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


----------------------------------------------------------------------------------------- 
 
Linux程式设计-11.Shell Script(bash)--(10)控制圈while/until
http://www.openchess.org/noitatsko/programming/ (2001-05-25 17:04:01)
while list do list done
当list为True时,该圈会不停地执行。
例一 : 无限回圈写法
#!/bin/sh

while : ; do
echo "do something forever here"
sleep 5
done

例二 : 强迫把pppd杀掉。
#!/bin/sh

while [ -f /var/run/ppp0.pid ] ; do
killall pppd
done

--------------------------------------------------------------------------------

until list do list done
当list为False(non-zero)时,该圈会不停地执行。
例一 : 等待pppd上线。
#!/bin/sh
until [ -f /var/run/ppp0.pid ] ; do
sleep 1
done


-----------------------------------------------------------------------------------------

Linux程式设计-11.Shell Script(bash)--(11)参数与变数
http://www.openchess.org/noitatsko/programming/ (2001-05-25 18:08:00)
在继续下去介绍function之前,我们必须停下来介绍"参数与变数"。

--------------------------------------------------------------------------------

参数(Parameters)是用来储存"值"的资料型态,有点像是一般语言中的变数。它可以是个名称(name)、数字(number)、或者是以下所列出来一些特殊符号(Special Parameters)。
在shell中,变数是由name形式的参数所构成的。

--------------------------------------------------------------------------------

在前面的许多例中,我们事实上已经看到许多参数的运用。要设定一个Parameter实际很简单:
name=value

例如说:

MYHOST="foxman"

而要使用它时,则是加个"$"符号。

echo $MYHOST

--------------------------------------------------------------------------------

位置参数(Positional Parameters)

--------------------------------------------------------------------------------

所谓的位置参数便是0,1,2,3,4,5,6,7,8,9...。使用时,用$0,$1,$2...。
位置参数是当script被载入时,後面所附加的参数。$0是本身,$1则为第一个参数,$2为第二个,依此类推。而当Positional Parameters被function所使用时,它们会被暂时取代(下一节会介绍function)。

例如以下这个script:
#!/bin/sh
# Filename : position
echo $0
echo $1

执行时:
[foxman@foxman bash]# ./position abc
./position
abc

当位置参数超过两位数时,有特别的方法来展开,称为Expansion。

--------------------------------------------------------------------------------

特殊参数(Speical Parameters)
这些符号,非常不人性,对新手来说很困扰。但上手後,会觉得方便无比,有些如果您看不懂的话,就--算了,不用浪费太多时间在上面。

--------------------------------------------------------------------------------

* 星号
将Positional Parameters合成一个参数,其间隔为IFS内定参数的第一个字元(见内建变数一节)。
例:
#!/bin/sh
# starsig
echo $*

执行:
[foxman@foxman bash]# starsig a b c d e f g
a b c d e f g

--------------------------------------------------------------------------------

@ at符号
与*星号类同。不同之处在於不参照IFS。

例:
#!/bin/sh
# atsig
echo $@

执行:
[foxman@foxman bash]# atsig a b c d e f g
a b c d e f g

--------------------------------------------------------------------------------

# 井字号
展开Positional parameters的数量。

例:
#!/bin/sh
# poundsig
echo $#

执行
[foxman@foxman bash]# poundsig a b c d e f g
7

--------------------------------------------------------------------------------

? 问号
最近执行的foreground pipeline的状态。

--------------------------------------------------------------------------------

- 减号
最近执行的foreground pipeline的选项参数。

--------------------------------------------------------------------------------

$ 钱钱钱
本身的Process ID。

[foxman@foxman bash]# ps ax | grep bash
1635 p1 S 0:00 /bin/bash

[foxman@foxman bash]# echo $$
1635

--------------------------------------------------------------------------------

! 惊号
最近执行背景命令的Process ID。

--------------------------------------------------------------------------------

0 零
在Positional Parameters一部份已经说明过了,是执行的shell script本身。但如果是用"bash -c",则$0被设为第一个参数。

[foxman@foxman bash]# echo $0
/bin/bash

--------------------------------------------------------------------------------

_ 底线符号
显示出最後一个执行的命令。

[foxman@foxman bash]# echo $_
bash

--------------------------------------------------------------------------------

内建变数(Shell Variables)
Bash有许多内建变数,像PATH、HOME、ENV......等等。这些内建变数将在另一节中,专门一一说明。


----------------------------------------------------------------------------------------- 
 
Linux程式设计-11.Shell Script(bash)--(12)函数function
http://www.openchess.org/noitatsko/programming/ (2001-05-25 19:00:00)
[ function ] name () { list; }
function的参数是Positional Paraments。


#!/bin/sh

function func() {
echo $1
echo $2
return 1
}

func "Hello" "function"

局部变数可用local来宣告。

函数可export,使用下一层的shell可以使用。

函数可递,没有递层数的限制。


-----------------------------------------------------------------------------------------
 
Linux程式设计-11.Shell Script(bash)--(13)Bash内建指令集
http://www.openchess.org/noitatsko/programming/ (2001-05-25 20:10:00)
Bash内建指令集
以下的命令,大部份都没有使用例,您可能会看不出所以然,摸不着头脑。在我加入例说明前,建议您"man bash",然後自己实际操作一次。

--------------------------------------------------------------------------------

: [arguments]
不做任何事,除了[arguments]一些参数展开及一些特定重导向的作业外。

永远返回零。它的用法跟true一样。

--------------------------------------------------------------------------------

. filename [arguments]
source filename [arguments]
由filename中读取命令,并执行。
您会在/etc/rc.d/*中发现很多
. /xxxx
的指令,而xxxx的permission都不是可执行的。事实上,在tcsh中,需要用
source /xxxx
来做同样的指令。
注意到"."的後面是有空格的(比较一下". /"跟"./",不一样)。filename是内含指令的纯文字档即可,无须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

便可执行该script,而不需要"chmod 755 my_source"

--------------------------------------------------------------------------------

alias [name[=value] ...]
昵称命令
例如您如果来自DOS的世界,对UNIX的指令不习惯,可用alias来修改,以符合您的习惯。


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的设定。"unalias -a"将全部alias取消。


unalias copy

--------------------------------------------------------------------------------

bg [jobspec]
将指定任务放到背景中,如果jobspec未指定,内定为目前的。

--------------------------------------------------------------------------------

fg [jobspec]
将指定任务放到前景中,如果jobsepc没有指定,那麽内定为目前的。

--------------------------------------------------------------------------------

jobs [-lnp] [ jobspec ... ]
第一种形式列出目前正在工作的任务。
-l : 除了列出一般资讯外,还列出Process IDs。
-p : 仅列出该工作群"首脑"(Process group leader)的Process ID.
-n : 则仅列出有改变的jobs的状态。
如果给定jobspec,输出资讯则只有该jobspec。

返回值为零,除非有非法的选项发生。

jobs -x command [ args ... ]

如果使用第二种形式(-x),jobs取代指定的command及args,并执行返回其Exit Status。

--------------------------------------------------------------------------------

kill [-s sigspec | -sigspec] [pid | jobspec] ...
将sigspec的信号送到pid或jobspec。
sigspec可以是SIGKILL/KILL这种形式或是信号号码。如果sigspec是signal name,则大小写无关,而且可以没有SIG。
kill -l [signum]
列出信号名称。

[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]
等待指定的行程,并返回其结束状态。n可以是个jobspec或Process ID。如果n未指定,则等待所有的子行程,及返回值为零。若n为不存在的job或process,则返回127。否则,返回值为最後一个job/process的Exit Status。

--------------------------------------------------------------------------------

bind [-m keymap] [-lvd] [-q name]
bind [-m keymap] -f filename
bind [-m keymap] keyseq:function-name
显示出目前readline的按键及链结函数设定或是巨集。

-m keymap : 设定keymap binding。
-l : 显示出所有readline function的名称。
-v : 显示出目前的function name及bindings。
-d : 显示出function name及bindings。
-f filename : 从filename读取key bindings。
-q function : 询问那个按键触发function。

--------------------------------------------------------------------------------

break [n]
跳出控制回圈for/while/until中使用。如果有指定n,则跳出n层。n必须是大於等於1。若n大於巢状圈数,则所有的圈都会跳离。返回值回零。

--------------------------------------------------------------------------------

continue [n]
还原控制回圈for/while/until中使用。如果有指定n,则返回n层。n必须是大於等於1。若n大於巢状圈数,则还原到最上层。返回值回零。

--------------------------------------------------------------------------------

exit [n]
离开程式。n是Exit Status。

--------------------------------------------------------------------------------

return [n]
在function中使用。n为返回值,其作用与Exit Status一样。

--------------------------------------------------------------------------------

builtin shell-builtin [arguments]
执行内建函数。当您定义了与内建函数相同的指令时,可用此命令来执行内建函数。

--------------------------------------------------------------------------------

cd [dir]
更换目录到dir。如果没有指定,内定为HOME所指定的目录。

--------------------------------------------------------------------------------

command [-pVv] command [arg ...]
用command指定可取消正常的shell function寻找。只有内建命令及在PATH中找得到的才会被执行。"-p"选项,搜寻命令的方式是用PATH来找。"-V"或"-v"选项,会显示出该命令的一些简约描述。

--------------------------------------------------------------------------------

declare [-frxi] [name[=value]]
typeset [-frxi] [name[=value]]
宣告参数并给它们设定属性。如果没有给定名称,将会显示各参数值。

-f : 仅使用函数名称。
-r : 将name设为readonly。
-x : 将name输出给後续环境使用。
-i : 该参数被设为integer来使用,可用於算术表述。

用"+"时,关闭该属性。

--------------------------------------------------------------------------------

dirs [-l] [+/-n]
显示目前记忆的目录。目录可透过pushd/popd来操作。

+n : 显示开始的记录n个。
-n : 显示结尾的记录n个。
-l : 显示较多的资讯。

--------------------------------------------------------------------------------

echo [-neE] [arg ...]
输出显示args,由空白分隔。返回值永为零。

-n : 不跳行。
-e : 启动"/"符号的解译。
-E : 将ESC解译功能取消。

"/a" : alert(bell),发出声响。
"/b" : backspace,倒退。
"/c" : suppress trailing newline,不跳行。
"/f" : form feed,跳行跳格。
"/n" : new line,新行。
"/r" : carriage return,回到行起点。
"/t" : horizontal tab,水平跳位。
"/v" : vertical tab,垂直跳位。
"//" : 输出"/"。
"/nnn" : 输出ASCII Code号码nnn(八进位)。

--------------------------------------------------------------------------------

enable [-n] [-all] [name ...]
启动或关闭内建函数命令。使用"-n"将所有指定命令皆关闭,否则都是启动的。如果只有"-n"参数,它将会显示所有关闭的函数。如果只有"-all",它将会显示所有内建命令。

--------------------------------------------------------------------------------

eval [arg ...]
读取args,并将args合为一个命令,然後执行。其返回值成为eval的返回值。如果没有参数,eval返回True。

--------------------------------------------------------------------------------

exec [[-] command [arguments]]
当命令执行时,该命令取代shell,没有新的process产生。如果第一个参数是"-",shell会将"-"放入第零个参数,传给command。

--------------------------------------------------------------------------------

export [-nf] [name[=word]] ...
export -p
将name输出给环境,给往後的命令使用。"-f"选项表示name是函数。"-p"显示出所有export的名称。"-n"移除name。

--------------------------------------------------------------------------------

set [--abefhkmnptuvxldCHP] [-o option] [arg ...]
-a : 自动将变数标记为可让後面环境所使用。
-b : 立即报告被终结的背景程式状态。
-e : 当命令(simple-command,见後面)返回非零值时,立即跳出。
-f : 取消pathname expansion。
-h : 找出所记忆的函数命令位置。
-k : 所有keyword参数都放到环境中。
-m : 监督模式。
-n : 读取命令,但不要执行。可用於语法检查。
-p : 打开privileged模式。
-t : 当读取一个命令并执行後,立即离开。
-u : 当参数展开时,把unset参数当成是错误。
-v : 列出shell input lines。
-x : 在展开每个simple-command後,bash显示展开值在PS4上。
-l : 储存并还原name binding在for语法中。
-d : 关闭hasing command搜寻。
-C : 跟`noclobber=`一样。请见内定参数一节。
-H : 启动! style history substitution。
-P : 在使用像cd这种指令时,不要跟随symbolic links。
-- : "--"之後,没有参数跟在後面。
- : 指定将所有後面的参数当成是位置参数。
-o option-name : option-name可以是以下之一
allexport : 与"-a"相同。
braceexpand : 启动Brace Expansion。这是内定设定。
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标准。
privileged : 与"-p"相同。
verbose : 与"-v"相同。
vi : 使用vi-style命令列编辑程式。
xtrace : 与"-x"相同。

--------------------------------------------------------------------------------

unset [-fv] [name ...]
移除对映於name的参数。要注意PATH、IFS、PPID、PS1、PS2、UID、 EUID不能unset。若RANDOM、SECONDS、LINENO、HISTCMD被unset,它们会丧失原有意义,既始它们後来被重设也一样。 返回值为True,除非name是不能被unset的。

--------------------------------------------------------------------------------

fc [-e ename] [-nlr] [first] [last]
fc -s [pat=rep] [cmd]
修正命令。

--------------------------------------------------------------------------------

getopts optstring name [args]
解析位置参数。

--------------------------------------------------------------------------------

hash [-r] [name]
对每个name命令的完整路径记录下来。"-r"选项强迫忘记所有命令位置。如果没有给参数,则将会印出所有的资讯。返回值为True。

--------------------------------------------------------------------------------

help [pattern]
显示协助资讯。

--------------------------------------------------------------------------------

history [n]
history -rwan [filename]
没有参数时,会显示所下命令的历史记录。带有参数"n"则显示最後n个。

其它参数如下:
-a : 新增"新历史"到历史档中。
-n : 读取尚未读到历史中的记录。
-r : 读取filename做为历史档,并用它为目前历史记录。
-w : 将现有历史记录写到filename中。

--------------------------------------------------------------------------------

let arg [arg ...]
算术表述。请参考算术表述一节。

--------------------------------------------------------------------------------

local [name[=value] ...]
产生一个局部参数。如果用於function,则其作用围在function内及其子函数。

--------------------------------------------------------------------------------

logout
离开login shell。

--------------------------------------------------------------------------------

popd [+/-n]
移除目录堆叠。"+n"移除上面n个,"-n"移除下面n个。

--------------------------------------------------------------------------------

pushd [dir]
pushd +/-n
将目录新增到目录堆叠的最上面。"+n"旋转该堆叠,使第n个目录变成最上面。"-n"旋转该堆叠,使倒数第n个目录变成最上面。

--------------------------------------------------------------------------------

pwd
列出目前工作目录的绝对路径。

--------------------------------------------------------------------------------

read [-r] [name ...]
读进一行,然後第一个字设到第一个name,第二个设到第二个name,依此类推。如果没有name在参数中,则read会将值设到REPLY。返回值为零,除非遇到End-Of-File。若有"-r"选项,则"/n"被考虑为该行的一部份。

--------------------------------------------------------------------------------

readonly [-f] [name ...]
readonly -p
将给定的name标记为readonly。如果是"-f"选项,则函数也一样被标记为readonly。"-p"会列出所有readonly的name。"--"取消检查剩馀的参数。

--------------------------------------------------------------------------------

shift [n]
Positional Parameters从n+1...开始,会被改为$1...。n若为零,则没有改变。n若未给定,则内定为1。n必须是非负数,并且小於或等於$#。若n大於$#,则没有改变。返回值为零,除非n大於$#或小於零。

--------------------------------------------------------------------------------

suspend [-f]
暂停这个shell的执行,直到它收到SIGCONT信号。"-f"选项则是叫login shell不要抱怨,不过还是一样暂停。返回状态零,除非该shell是个login shell,而且没有"-f"选项。

--------------------------------------------------------------------------------

test expr
[ expr ]
我们在Exit Status的部份已经说过了,不再重。

--------------------------------------------------------------------------------

times
列出该shell的累积的使用者及系统时间及从shell执行的process时间,返回值为零。

--------------------------------------------------------------------------------

trap [-l] [arg] [sigspec]
当收到sigspec信号时,执行arg命令。"-l"显示出信号名称及号码。

--------------------------------------------------------------------------------

type [-all] [-type | -path] name [name ...]
没有参数的状况下,它会显示出shell如何 解译name做为命令。如果有"-type",它将会显示alias、keyword、function、builtin或file。如果 有"-path"的参数,它将会显示该命令的路径,找不到的话,不显示任何东西。如果有"-all"的参数,它将会显示所有可执行name的可能路径。 type接受"-a"、"-t"、"-p"做为缩写。

--------------------------------------------------------------------------------

ulimit [-SHacdfmstpnuv [limit]]
ulimit提供了对shell的可获取资源控制的功能。

-a : 报告目前所有限制。
-c : 设定最大可产生的core档案。
-d : 行程资料段(process's data segment)最大值。
-f : 可被这个shell产生的最大档案。
-m : resident set size最大值。
-s : 堆叠最大值。
-t : CPU TIME最大值(以秒计算)。
-p : pipe size in 512-byte blocks的最大值。
-n : 可开启的file descriptors最大值。
-u : 单一使用者可使用的最大process数。
-v : 该shell最大虚拟记忆体可用值。

所有项目是以1024做为单位。


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(14)Bash内建参数
http://www.openchess.org/noitatsko/programming/ (2001-05-25 21:04:01)

PPID : 该bash的呼叫者process ID.
PWD : 目前的工作目录。

OLDPWD : 上一个工作目录。

REPLY : 当read命令没有参数时,直接设在REPLY上。

UID : User ID。

EUID : Effective User ID。

BASH : Bash的完整路径。

BASH_VERSION : Bash版本。

SHLVL : 每次有Bash执行时,数字加一。

RANDOM : 每次这个参数被用到时,就会产生一个乱数在RANDOM上。

SECONDS : 从这个Shell一开始启动後的时间。

LINENO : Script的行数。

HISTCMD : 历史记录数。

OPTARG : getopts处理的最後一个选项参数。

OPTIND : 下一个要由getopts所处理的参数号码。

HOSTTYPE : 机器种类。

OSTYPE : 作业系统名称。

IFS : Internal Field Separator。

PATH : 命令搜寻路径。
PATH="/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."

HOME : 目前使用者的home directory;

CDPATH : cd命令的搜寻路径。

ENV : 如果这个参数被设定,每次有shell script被执行时,将会执行它所设定的档名做为环境设定。

MAIL : 如果这个参数被设定,而且MAILPATH没有被设定,那麽有信件进来时,bash会通知使用者。

MAILCHECK : 设定多久时间检查邮件一次。

MAILPATH : 一串的邮件检查路径。

MAIL_WARNING : 如果有设定的话,邮件被读取後,将会显示讯息。

PS1 : 提示讯息设定,内定为"bash/$ "。(请详见提示讯息一节。)

PS2 : 第二提示讯息设定,内定为"> "。

PS3 : select命令所使用的提示讯息。

PS4 : 执行追踪时用的提示讯息设定,内定为"+ "。

HISTSIZE : 命令历史记录量,内定为500。

HISTFILE : 历史记录档,内定~/.bash_history。

HISTFILESIZE : 历史记录档行数最大值,内定500。

OPTERR : 如果设为1,bash会显示getopts的错误。

PROMPT_COMMAND : 如果设定的话,该值会在每次执行命令前都显示。

IGNOREEOF : 将EOF值当成输入,内定为10。

TMOUT : 如果设为大於零,该值被解译为输入等待秒数。若无输入,当成没有输入。

FCEDIT : fc命令的内定编辑器。

FIGNORE : 请详见READLINE。

INPUTRC : readline的startup file,内定~/.inputrc

notify : 如果设定了,bash立即报告被终结的背景程式。

history_control, HISTCONTROL : history使用。

command_oriented_history : 存入多行指令。

glob_dot_filenames : 如果设定了,bash将会把"."包含入档案路径中。

allow_null_glob_expansion : 如果设定了,bash允许路径明称为null string。

histchars : history使用。

nolinks : 如果设定了,执行指令时,不会跟随symbolic links。

hostname_completion_file, HOSTFILE : 包含与/etc/hosts相同格式的档名。

noclobber : 如果设定了,Bash不会覆写任何由">"、">&"及"<>"所操作的档案。

auto_resume : 请见任务控制一节。

no_exit_on_failed_exec : 如果该值存在,非互动的shell不会因为exec失败而跳出。

cdable_vars : 如果启动,而cd命令找不到目录,可切换到参数形态指定的目录下。


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(15)提示符号
http://www.openchess.org/noitatsko/programming/ (2001-05-25 22:08:01)

Bash使用PS1~PS4来显示提示符号,其格式如下:

--------------------------------------------------------------------------------

/t : 现在时间。
/d : 现在日期。
/n : 新行。
/s : shell的名称。
/w : 目前工作目录。
/W : 目前工作目录完整路径。
/u : 使用者名称。
/h : Hostname。
/# : 这个命令的号码。
/! : 历史号码。
/$ : 如果EUID是0,则#,否则为$。
/nnn : 八进位的字元。
// : "/"符号。
/[ : 开始一序列不可列印的字元。
/] : 结束一序列不可列印的字元。


-----------------------------------------------------------------------------------------  
 
Linux程式设计-11.Shell Script(bash)--(16)算术表述
http://www.openchess.org/noitatsko/programming/ (2001-05-26 07:00:00)


- +
! ~
* / %
+ -
<< >>
<= >= < >
== !=
&
^
|
&&
||
= *= /= %= += -= <<= >>= &= ^= |=


----------------------------------------------------------------------------------------- 
 
Linux程式设计-11.Shell Script(bash)--(17)重导Redirection
http://www.openchess.org/noitatsko/programming/ (2001-05-26 08:10:00)

>
>>
1>
.
.


----------------------------------------------------------------------------------------- 
 
Linux程式设计-11.Shell Script(bash)--(18)语法
http://www.openchess.org/noitatsko/programming/ (2001-05-26 09:04:00)


Simple Command


Pipelines

Lists

(list)
{ list; }

-----------------------------------------------------------------------------------------  
 
设置Unix启动密码
本文出自: http://go3.163.com/~axiom999 (2001-06-18 22:08:01)
在 DOS和WINDOWS98系统中设置启动密码已经有很多方法和现成的软件可用了,但是,在UNIX系统中,有没有一种方法可以设置启动密码呢?下面我自 编了一个SHELL小程序,可以实现在系统启动过程中加以密码限制,即使启动了机器,在输入密码之前,也不能使系统出现LOGIN的提示符。
这个小程序是加载在/etc/rc2文件中的,rc2文件是unix系统在启动过程中调用的一个shell文件,我们在最后加入如下内容,就可实现启动密码的限制了。程序如下:


在/etc/rc2文件中寻找下面这句话

if [ "${BOOT}" = "yes" -a "$7" = "2" ]
then
# dspmsg $MF_RC -s $MS_RC2 $RC2_READY 'The System is Ready ! /n'
找到后
屏蔽上面这句话,之后加入下面这个程序:
# 循环开始
while true
do
clear
setcolor -b black -k lt_red
echo '/033[09;18H 系'
setcolor -b black -k lt_cyan
echo '/033[09;25H 统'
setcolor -b black -k lt_magenta
echo '/033[09;32H 启'
setcolor -b black -k hi_white
echo '/033[09;39H 动'
setcolor -b black -k yellow
echo '/033[09;46H 完'
setcolor -b black -k lt_green
echo '/033[09;53H 毕'
setcolor -b black -k white
echo '/n/n/n/n/n/n/n/n/n/n/n/n/n'
echo ' ┏━━━━━━━━━━━━━━━━━┓'
echo ' ┃ 欢 迎 您 使 用 UNIX ┃'
echo ' ┗━━━━━━━━━━━━━━━━━┛'
echo "/033[17;15H 请输入密码:[****] "
setcolor -b black -k black
echo "/033[17;42H/c"
read ch
setcolor -b black -k white
# 在上面的两个setcolor语句中,可以使键入的密码不回显
case $ch in

# 以下括号内为启动密码
2015)
setcolor -b black -k lt_green
echo " "
echo " "
echo "密码正确,请使用本系统."
setcolor -b black -k white
break
;;
*)
echo "/007"
echo "/033[20;1H"
setcolor -b black -k lt_red
echo "/007/t/t/t 密码错误!!!,请重新输入/c"
setcolor -b black -k white
read s
;;

esac
done
# 循环结束

elif [ "$7" = "2" ]
then
dspmsg $MF_RC -s $MS_RC2 $RC2_COMPLETE 'Change to state 2 has been completed./n'
fi
如果在while循环中,每一条setcolor语句下面加如sleep 1(延迟1秒),更能获得动态
的效果!


-----------------------------------------------------------------------------------------

Shell 递归程序设计-批量转换大写文件名为小写
本文出自: http://ehnt.net/clansoft/gb/ (2001-06-19 14:08:00)

-----------------------------------------------------------------------------------------  
 
shell实现Unix进程间信息交换的几种方法

本文出自:计算机世界2000年第32期 作者: 北京中软同和公司 何绍德 (2001-06-26 22:08:00)
本文将介绍在SCO OpenServer5.0.5系统中使用shell语言来实现进程间信息交换的几种方法:

使用命名管道实现进程间信息交换

使用kill命令和trap语句实现进程间信息交换

使用点命令“.”实现进程间信息交换

使用export语句实现父进程对子进程的信息传递

一、使用命名管道
  命名管道是一种先进先出(FIFO)的数据结构,它允许两个进程通过管道联接实现信息交换。
在Unix系统中,命名管道是一种特殊类型的文件,因此可以对命名管道进行读写操作;当然,同样
也会有读写和执行等权限的限制。

  通过下面的命令可以创建一个命名管道:
  /etc/mknod pipe_name p

  其中“pipe_name”是要创建的命名管道的名字,参数p 必须出现在命名管道名字之后。

  命名管道文件被创建后,一些进程就可以不断地将信息写入命名管道文件里,而另一些进程也
可以不断地从命名管道文件中读取信息。对命名管道文件的读写操作是可以同时进行的。下面的例子
显示命名管道的工作过程。

  进程A、B、C中运行的程序只是一条简单的echo命令,它们不断地把信息写入到命名管道文件
/tmp/pipe1中。与此同时,程序中的“read msg” 命令不断地从命名管道文件/tmp/pipe1中读取这些
信息,从而实现这些进程间的信息交换。

  程序执行时,首先创建命名管道文件,此时程序处于等待状态,直到A、B、C进程中某一个进程往
命名管道中写入信息时,程序才继续往下执行。使用rm命令可以删除命名管道文件从而清除已设置的
命名管道。

  下面是一个用于记录考勤的例子:

  在主机上运行的程序/tmp/text产生命名管道/tmp/pipe1,并不断地从命名管道中读取信息送屏幕
上显示。

/tmp/text程序:
if [ ! -p /tmp/pipe1 ]
then
/etc/mknode /tmp/pipe1 p
fi
while :
do
read msg
if [ “$msg" = “" ]
then
continue
else
echo “$msg"
fi
done < /tmp/pipe1

  在终端上运行的是雇员签到程序/tmp/text1。每个雇员在任何一台终端上键入自己的名字或代码,
程序/tmp/text1将把这个名字连同当时的签到时间送入命名管道。

/tmp/text1程序:
tty=‘who am I | awk ‘{print $2}’’
while :
do
echo “Enter your name: /c" > /dev/$tty
read name
today=‘date’
echo “$name/t$today"
done > /tmp/pipe1

  当雇员从终端上输入自己的姓名后,运行/tmp/text程序的主机将显示类似下面的结果:

wang Thu Jan 28 09:29:26 BTJ 1999
he Thu Jan 28 09:29:26 BTJ 1999
cheng Thu Jan 28 09:30:26 BTJ 1999
zhang Thu Jan 28 09:31:26 BTJ 1999

二、使用kill命令和trap语句
  在Unix系统中,当检测到一个异常的内部状态,或者硬件及外部设备发出请求,或者执行某些指令时,
将会向系统中的进程发出信号报告事件产生。当进程捕获到这些信号后,系统便转去执行预先设定的默认
程序,完成指定的动作;这些预先设定的默认程序称之为信号的系统陷阱。

  在shell中,使用trap语句为信号设置新的陷阱。当shell 捕获到一个信号时(信号11除外,因为
shell本身要利用这个信号进行内存分配),它将这个信号传递给所有当前正在执行的程序
(父程序和子程序),并分别执行父程序和子程序中已设置的信号陷阱。一旦陷阱程序执行结束,便返
回中断点,继续执行原来的程序流程。

trap语句的基本格式:
trap command_list signal_list

  command_list: 由一个或多个命令(或命令组)构成的命令列表。当命令列表中含有多个命令时要
用单引号或双引号括起来,并且各命令间要用分号隔开。

  signal_list:由一个或多个信号值构成的信号列表,各信号值间要用空格分开。

  在一个shell程序(父程序)中重新设置信号的陷阱并不改变被这个程序所调用的子程序中同名信号
的陷阱。同样,在子程序中设置的信号陷阱也不影响父程序中同名信号的陷阱。

  shell在读取trap语句时,要扫描一次命令列表,以便设置陷阱。在捕获信号后,shell再次扫描命令
列表,执行已设置好的陷阱程序(命令或命令组)。因此,如果命令列表中含有变量置换或命令置换表达
式,shell在第一次扫描命令列表时就会用当前的变量值或命令结果置换这些表达式,使得在捕获到信号而
去执行陷阱程序时,陷阱程序已经不是原来设置的陷阱程序了。为了避免这种情况发生,使用单引号而不是
使用双引号把trap语句中含有变量置换或命令置换表达式的命令列表括起来;因为单引号可以消除所有字符
的特殊含义,这样避免了shell在第一次扫描时执行任何置换或替代操作,直到命令列表被执行时才进行置
换或替代。

  向一个程序或进程传递信号方法很多,比如在程序执行时按下Ctrl+c键或Del键,将向程序传递一个
SIGINT信号,执行该信号的系统陷阱将终止程序执行。使用kill命令传递信号是shell语言编程中最为常用
的方法。

  kill命令的基本格式是:
  kill [ - signal ] PID

  通常kill命令用来终止一个进程。但如果使用了带有短划线“-”的信号作为参数时,kill命令就发送
该信号给PID指示的一个或多个进程,而不是终止进程。当trap语句捕获到这个信号后便执行设定的信号陷阱
程序,实现进程间的相互通讯。

  下面的例子显示了程序master和slave1、slave2间如何利用信号机制实现相互通讯的。首先在后台运行
程序slave1和slave2,然后运行程序master。在文件/tmp/pro_list中记录了这三个程序的进程号。

  程序slave1首先设置信号15的陷阱,然后把自己的当前进程写入文件/tmp/pro_list;在获得master进程
号后,进入循环状态。当接收到master发出的信号15时,执行陷阱程序,显示相关信息后,向master发出信
号15。

  程序slave2执行情况与slave1相似。

  程序master也是首先设置信号15的陷阱,然后把自己的当前进程写入文件/tmp/pro_list。在取得所有
slave程序进程号后,向这些slave程序发出信号15,然后进入循环等待。当接收到slave1或slave2发出的信
号15时,执行陷阱程序,显示相关信息,杀死所有slave进程,清空文件/tmp/pro_list,然后退出。

程序/tmp/slave1:
slave() {
echo “slave1 has received sighal from master"
echo “Request master to kill slave1 process"
kill -15 $master_pid
}
trap slave 15
echo “slave1_pid $$" >> /tmp/pro_list
sleep 1
while :
do
master_pid=‘awk ’$1 ~/master/
{print $2}‘/tmp/pro_list’
if [ “$master_pid" != “" ]
then break
fi
done
while :
do
sleep 1
done

程序/tmp/slave2:
slave() {
echo “slave2 has received sighal from master"
echo “Request master to kill slave2 process"
kill -15 $master_pid
}
trap slave 15
echo “slave2_pid $$" >> /tmp/pro_list
sleep 1
while :
do
master_pid=‘awk ’$1 ~/master/
{print $2}‘/tmp/pro_list’
if [ “$master_pid" != “" ]
then break
fi
done
while :
do
sleep 1
done

程序/tmp/master:
kill_slave() {
echo “Master has received signals
from slave processes"
echo “End all slave processes"
kill -9 $slave_list
>/tmp/pro_list
exit 0
}
trap kill_slave 15
echo “master_pid $$" >> /tmp/pro_list
sleep 1
slave_list=‘awk ’$1 ~/slave/
{print $2}‘/tmp/pro_list’
echo “Current slave processes are:"
echo “$slave_list"
kill -15 $slave_list
while :
do
sleep 1
done

执行程序:
$ cd /tmp
$ ./slave1&
15638
$ ./slave2&
16831
$ ./master
Current slave processes are:
15638
16831
slave1 has received signal 15 from master
Request master to kill slave1 process
slave2 has received signal 15 from master
Request master to kill slave2 process
Master has received signals from slave processes
End all slave processes
15638 Killed
16831 Killed

三、使用点命令“.”
  “.”点命令是shell的一个内部命令,它从指定的shell 文件中读入所有命令语句并在当前进程
中执行。 因此当多个shell进程(父子进程或无关进程均可)共享一组变量值时,就可以将这些变量
赋值语句定义到一个shell文件里,并在需要这些变量值的程序中使用点语句来引用这个shell文件,
从而实现变量值共享(对这些变量值的修改仅涉及到这个shell文件)。但要注意的是,这个shell文
件不能包括含有位置参数的语句,即不能接受$1、$2等命令行参数。

  下面是一个在超市中发布每日商品价格的示范程序片段。发布每日商品价格统一由程序/tmp/jiage
来执行,它为每种商品价格赋值,并把相应的赋值语句写入文件/tmp/jiagebiao中。在各终端上运行的
收款程序/tmp/shoukuan将读入文件 /tmp/jiagebiao中所有赋值语句并在当前进程中执行,从而获取在
程序/tmp/jiage中设定的价格。

  价格设定程序/tmp/jiage:

echo “Enter the price of chicken,
duck and fish: /c"
read chicken duck fish
exec 3>/tmp/jiagebiao
echo “chicken_price=$chicken" >&3
echo “duck_price=$duck" >&3
echo “fish_price=$fish" >&3

  执行/tmp/jiage程序后,文件/tmp/jiagebiao中将有如下内容:

chicken_price=5.4
duck_price=2.5
fish_price=4.2

  收款程序/tmp/shoukuan:

. /tmp/jiagebiao
count=0
while :
do
echo “Enter the trade name and
quantities or input q to sum: /c"
read trade$count quantity$count
eval a=/$trade$count
if [ “$a" = “q" ]
then if [ $count -gt 0 ]
then
count=‘expr $count - 1’
fi
break
fi
count=‘expr $count + 1 ’
done
echo “/n‘date’"
echo “trade name/tquantity/tsum"
while [ “$count" -ge 0 ]
do
eval trade=“/${trade$count}"
eval trade_price=“${trade}_price"
eval danjia=/${$trade_price}
eval quantity=“/${quantity$count}"
sum=‘echo “scale=2; $danjia
*$quantity"|bc’
echo “$trade/t/t$quantity/t/t$sum"
count=‘expr $count - 1 ’
done

  在终端上执行程序/tmp/shoukuan将有如下显示:

Enter the trade name and quantities
or input q to sum: chicken 2
Enter the trade name and quantities
or input q to sum: fish 3
Enter the trade name and quantities
or input q to sum: duck 4
Enter the trade name and quantities
or input q to sum: q

Thu Jan 28 09:29:29 BJT 1999:
duck 4 10
fish 3 12.6
chicken 2 10.8

四、使用export语句
  通常shell变量是局部变量,无论是通过赋值操作还是通过命令赋值,其变量值只在当前进程中
有效。但是经过export语句说明的shell变量就成为一个全局性变量,其变量名和变量值可以传递给
子进程及其后代进程。在子进程中可以修改这个变量的值,但并不影响这个变量在父进程中的取值。

  下面的例子中,父进程(/tmp/text)将赋值后的变量 pro_name传递给子进程(/tmp/text_child),
在子进程中对变量pro_name所赋的新值并不影响父进程中该变量的值。

/tmp/text程序:
pro_name=“PARENT"
echo “The variable pro_name is
$pro_name in parent process"
export pro_name
/tmp/text_child
echo “The variable pro_name is
$pro_name after retund to parent process"

/tmp/text_child程序:
echo“The variable pro_name ($pro_name) is
transmited to child process"
pro_name=“CHILD"
echo “To change the variable pro_name to
$pro_name in child process"
执行程序/tmp/text:
$ /tmp/text
The variable pro_name is PARENT
in parent process
The variable pro_name (PARENT)
is transmited to child process
To change the variable pro_name to CHILD
in child process
The variable pro_name is PARENT
after retund to parent process


-----------------------------------------------------------------------------------------  
 
介绍B-SHELL的一些运用方法


这里只介绍B-SHELL的一些运用方法,不对B-SHELL的基本知识进行说明(与其他的语言有很多的共性,果你懂一种语言的话,很快就 能上手),如你是对B-SHELL不是很了解的话,而且又想学的话,建议你去查阅相关的资料(网上有很多关于这方面的东东;当然也可买些书;如果你是一个 借别人的书才能阅读的人,那就去借吧!我就是这样的人之一。)。我的能力有限,若有不足或错误,请多多指教,小弟将感激不尽!所有的介绍适合于内核 2.2.13的及以上的liunx环境。

B-SHELL是一个便捷的开发工具,在紧急情况下要实现产品的某一功能,而用C语言不能很快完成,则可选择B-SHLL实现,日后再用C语言完 成;在产品里对于那些不常运行的程序可用B-SHELL替代,这样可以避免因对C语言使用不当而带来的不良后果;对于一些处理量不大的程序可用B- SHELL实现。


讨论:


#!/bin/sh à B-SHELL的解释器标志


ALL=$@

#{

B-SHELL中带”$”的变量的说明:$0à SHELL命令本身

$nà 位置参数n(n != 0)

$@à 所有的输入变量

$$à 当前进程号

$!à 最近后台进程的PID值

$?à 最近命令执行状态的返回值

$#à 参数的个数

}#

declare -x TIME=0

#{

变量声明的说明:


declare 声明全局变量;如果在函数内声明,则只在函数内有效(局部变量);-x表明变量值可以传递给后继命令(从函数传值给后继命令);-i表明变量作为整型处 理;-r表明变量为只度;用“+”代替“-”,原有变量的声明屏蔽,恢复为无定义状态。由第一次赋值决定其参数在脚本中的性质,如果首次是字符,以后都当 字符处理,其它等同。


local声明局部变量;local 变量名 [ = “值”];一般在函数内部运用。


直接定义变量,不用declare 和local指明。由第一次赋值决定其参数在脚本中的性质,如果首次是字符,以后都当字符处理,其它等同。也可在定义确定。

}#

declare -x NUMBEROFFILE=0

#{

关于脚本函数说明:

定义方式:function 函数名() 或 函数名()

{

函数体(作你想要作的事)

}

调用方式:函数名 参数列

在脚本里函数的调用就象调用命令一样使用。à 后面将会提到

}#


function hel_ver() à 显示帮助信息或版本号

{


if [ "$1" = "-h" ] ;then

echo "fstrf -v :show version of shell script."

echo "Usages : fstrf -h||-v "

echo " fstrf ARGUMENTS DIRECTORY STRING || fstrf ARGUMENTS STRING "

echo " For more informations run man fstrf."

exit

fi


if [ "$1" = "-v" ] || [ "$1" = "version" ];then

echo "fstrf version 1.0.1 2001/07/05."

exit

fi

}


function find_offer() à 在给定的目录下查找是否有包含指定字串的文件,并显示其路径

{

for file in `ls "$1"` à for var in command do ………done 的一个典型运用;对$1目录下的目录或文件进行处理

do

if [ -d "$1"/$file ];then à 判断$file是否为目录

continue

else

string=`grep "$2" "$1"/$file ` à 查找字串

if [ -n "$string" ];then à 判断字串为非空

echo $string > /str

str=`awk '{print $1 }' /str` à 取得str 的第一域值

rm /str

if [ "$str" != "Binary" ];then à 剔除二进制文件

NUMBEROFFILE=`expr $NUMBEROFFILE + 1 ` à 相当于C语言的NUMBEROFFILE +=1;可用

let ‘ NUMBEROFFILE=NUMBEROFFILE + 1‘替换

TIME=`expr $TIME + 1`

echo "$1/$file" à 显示匹配文件

fi

fi

fi

done


}


#else

function find_curr() à 在当前目录下查找是否有包含指定字串的文件,并显示其路径(相对路径)实现机制与find_offer相同

{

# if [ "$#" -eq "1" ];then à

for file in `ls ./` 如果只输入一个参数,则查找当前工作目录下的文件

do

if [ -d "$file" ];then

continue

else

string=`grep "$1" $file`

if [ -n "$string" ];then

echo $string > /str

str=`awk '{print $1 }' /str`

rm /str

if [ "$str" != "Binary" ];then

NUMBEROFFILE=`expr $NUMBEROFFILE + 1 `

TIME=`expr $TIME + 1`

echo "./$file"

fi

fi

fi

done

}

function print_num() à 显示查找的文件数 (在查多级目录时未能实现,如果你知道,告诉我,我会很高兴的!)

{

if [ "$NUMBEROFFILE" -gt "0" ] ;then

# echo ""

if [ "$#" -eq "1" ];then

#{

关于彩色显示的说明:

不同的linux系统,运行的命令的方式都不一样。在LINUX/BSD系统中:echo -e “/033[40;32m”;在V系统中:echo “/033[40;32m”。本例中采用前一种方式。40位为背景色,取值40��47之间;32位为前景色,取值 30��37之间;/033是固定用法。彩色显示要成队匹配,如脚本所示。通常后一个色彩控制为

echo -e "/033[40;37m" (意思是恢复正常色)。彩色显示控制通常是成对出现,例如,

`echo -e "/033[40;33m"`"$2"`echo -e "/033[40;37m"`

echo -e "/033[40;37m"à 恢复正常显示(黑背景,白前景)。利用彩色显示控可以作出漂亮的liunx菜单(当然不能与Xwindows和WINDOWS相比)。

}#

echo "Finded `echo -e "/033[40;32m"`$NUMBEROFFILE`echo -e "/033[40;37m"` file(s) which have the string `echo -e "/033[40;33m"`"$1"`echo -e "/033[40;37m"` ."

else

echo "Finded `echo -e "/033[40;32m"`$NUMBEROFFILE`echo -e "/033[40;37m"` file(s) which have the string `echo -e "/033[40;33m"`"$2"`echo -e "/033[40;37m"`. "

fi

else

if [ -z "$2" ];then

echo "Finded `echo -e "/033[40;32m"`no `echo -e "/033[40;37m"`file under current directory."

else

echo "Finded `echo -e "/033[40;32m"`no `echo -e "/033[40;37m"`file under directory "$1"."

fi

fi

}

function fdir() à 从给定的目录开始查找当前目录及其子目录的包含的目录,并存入/tmp/dtmp文件。

{

>/tmp/dtmp

#cd /

echo "$1" >/tmp/dtmp

tmp=`echo $1 | grep "//proc"`à 不查找/proc目录下的目录

if [ ! -z $tmp ];then

# echo "/proc"

exit

fi

i=`expr $i + 1 ` à 记录找到的目录数目,每向/tmp/dtmp文件加一目录记录时此值加一(以下同样)

###first grade

cd $1 à 进入脚本的工作目录(不会改变控制台的工作目录)

for loop in `ls ./`

do

# echo $loop

if [ -d $loop ];then à 判断$loop是否为目录(以下同样)

tmp=`echo $loop | grep "proc"`

if [ ! -z $tmp ];then

continue

fi

i=`expr $i + 1 `

echo "`pwd`/$loop" >>/tmp/dtmp à 连同目录的绝对路径加入/tmp/dtmp文件(以下同样)

###second grade

cd $loop à 进入脚本二级工作目录

for loop1 in `ls ./`

do

# echo $loop1

if [ -d $loop1 ];then

tmp=`echo $loop1 | grep "proc"`

if [ ! -z $tmp ];then

continue

fi

i=`expr $i + 1 `

echo "`pwd`/$loop1" >>/tmp/dtmp

###third grade

cd $loop1à 进入脚本三级工作目录

for loop1 in `ls ./`

do

# echo $loop1

if [ -d $loop1 ];then

i=`expr $i + 1 `

echo "`pwd`/$loop1" >>/tmp/dtmp

…………

………

………

………

…………

else

continue

fi

done

cd .. à 退出脚本三级工作目录,进入脚本二级工作目录

else

continue

fi

done

cd ..à 退出脚本二级工作目录,进入脚本一级工作目录

else

continue

fi

done

}


#{

test的用法说明:在脚本里,用一对[ ]表示test,如[ "$#" -eq "0" ]。注意:参数与[]之间一定要有空格(最好是所有的参数之间都要有空格)。如果不了解test参数的用法,运行man test,只要你学过英语你一定能看懂;实在没有办法,那就上网去查吧!

}#

##main shell

if [ "$#" -eq "0" ];then

echo "`echo -e "/033[40;33m"`run fstrf -h or man fstrf `echo -e "/033[40;37m"`to get more help informations."

echo "`echo -e "/033[40;36m"`list current directory:`echo -e "/033[40;37m"`"

ls ./

echo "`echo -e "/033[40;36m"`no string input!!!`echo -e "/033[40;37m"`"

exit

fi

hel_ver $ALL à 调用hel_ver函数

if [ "$1" = "-up" ];then à 查找指定当前目录内及字目录内的文件

if [ "$#" -eq "3" ];then

fdir $2 $3 2>/dev/null 1>&2 à 将所有的错误输出均输向/dev/null(不在屏幕上回显,以下一样)

#{

while read var do .. done的重定向说明:

有两种方式: 1. while read var do .. done < 重定向文件的路径及文件名

while read var

do

..

done < 重定向文件的路径及文件名

2. dd if=重定向文件的路径及文件名 bs=512 2>/dev/null | while read var do .. done

dd if=重定向文件的路径及文件名 bs=512 2>/dev/null | /

while read var

do

..

done


}#

#{

关于函数调用的说明:

在脚本中函数的调用类似与LINUX命令的调用,只是变量要用“”括起来。函数内部的$n只相对与函数的参数位置,如find_offer "$DIR" "$3",find_offer内的$1对应于"$DIR",$2对应于"$3",与SHELL 主程序的$n无对应关系,既函数的$1不一定要等于SHELL主程序的$1。

}#

dd if=/tmp/dtmp bs=512 2>/dev/null | /

while read DIR

do

find_offer "$DIR" "$3"

done

# print_num "$2" "$3"

fi

if [ "$#" -eq "2" ];then à 查找指定当前工作目录内及字其目录内的文件

fdir ./ 2>/dev/null 1>&2

dd if=/tmp/dtmp bs=512 2>/dev/null | /

while read DIR

do

find_offer "$DIR" "$2"

done

# print_num "$2"

fi

fi

if [ "$1" = "-cu" ];then à 查找当前目录或指定当前目录内的文件

if [ "$#" -eq "2" ];then à 查找当前目录匹配的文件

find_curr "$2"

print_num "$2" à 显示匹配的文件数

fi

if [ "$#" -eq "3" ];then à 查找指定当前目录内的文件

find_offer "$2" "$3"

print_num "$3" à 显示匹配的文件数

fi

fi

if [ -e /tmp/dtmp ];then à 文件存在则删除

rm /tmp/dtmp

fi


-----------------------------------------------------------------------------------------  
 
shell编程例子 -- 一个简单的目录菜单

until
echo List Directory..........1
echo Change Directory........2
echo Edit File...............3
echo Remove File.............4
echo Exit Menu...............5

read choice
test $choice = 5
do
case $choice in
1) ls;;
2) echo Enter target directory
read dir
cd $dir
;;
3) echo Enter file name
read file
vi $file
;;
4) echo Enter file name
read file
rm $file
;;
q|Q|5) echo Goodbye;;
*) echo illegal Option
esac
done


-----------------------------------------------------------------------------------------  
 
shell编程例子 -- 一个.cshrc例子

*****************************************************************
# * *
# * *
# *****************************************************************
#
# HISTORY
#
# @(#)$RCSfile: .cshrc,v $ $Revision: 4.1.3.3 $ (DEC) $Date: 1992/05/11 09:13:09
$
#
setenv MAIL /usr/spool/mail/$USER
#******************************************************************************
#******************************************************************************
#
# add by zzy 2000.08.06
#
#******************************************************************************
#******************************************************************************
# set pics environment
#******************************************************************************
#source /etc/pics.d/picsenv.csh
#******************************************************************************
# set innovator environment
#******************************************************************************
#source /usr/innovator/inoenv.csh
#******************************************************************************
# set PCFC application environment
#******************************************************************************
source ${HOME}/app_login
#******************************************************************************
# change path to home path
#******************************************************************************
cd ${HOME}
#******************************************************************************
app_login:
==========
#******************************************************************************
#* module: app_login
#* description: app login
#* This script must be called in the login file
#* with the command 'source app_login'
#* author: zzy
#* version: 31.08.1998
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# this path and this script
#******************************************************************************
set this_path1 = "`dirname ${HOME}/x`"
set this_script1 = "app_login"

if ( ! -f ${this_path1}/${this_script1} ) then
$say 'this script must be in the directory $HOME'
goto exit
endif

#******************************************************************************
# start message
#******************************************************************************
$say " %$this_script1, `date '+%H:%M:%S'` start executing on $node"

#******************************************************************************
# set project and channel prefix for all user
#******************************************************************************
if ( "$user" == "root" ) then
setenv PROJ pcfc
setenv CPRE ""
endif

if ( "$user" == "pcfc" ) then
setenv PROJ pcfc
setenv CPRE ""
endif

if ( "$user" == "picsadm" ) then
setenv PROJ baoshan
setenv CPRE ""
endif

if ( "$user" == "picsvis" ) then
setenv PROJ baoshan
setenv CPRE ""
endif

if ( "$user" == "" ) then
setenv PROJ pcfc
setenv CPRE ""
endif

#******************************************************************************
# set project directory
#******************************************************************************
setenv PROJ_DIR /home/$PROJ

#******************************************************************************
# call project application login
#******************************************************************************
if ( -f "${this_path1}/${this_script1}_$PROJ" ) then
$say " %$this_script1, call project application login"
source ${this_path1}/${this_script1}_$PROJ
endif

#******************************************************************************
# end message
#******************************************************************************
#$say " %$this_script1, `date '+%H:%M:%S'` finished"

#******************************************************************************
# exit
#******************************************************************************
exit:
unset this_path1
unset this_script1
exit

#******************************************************************************

app_login_pcfc
==============
#******************************************************************************
#* module: application_login_$PROJ
#* description: application login for a project
#* This script must be called in the login file app_login
#* with the command 'source app_login_$PROJ'
#* author: Zhou zeyan
#*
#* version: 8.1.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# this path and this script
#******************************************************************************
set this_path2 = "`dirname ${HOME}/x`"
set this_script2 = "app_login_$PROJ"

#******************************************************************************
# start message
#******************************************************************************
$say " %$this_script2, `date '+%H:%M:%S'` start executing on $node"

#******************************************************************************
# history
#******************************************************************************
set history=40
alias h history

#******************************************************************************
# aliases
#******************************************************************************
alias sql sqlplus pcfcadm/pcfcadm

#******************************************************************************
# set environment for components
#******************************************************************************

set cmp = glb
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = utl
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = com
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = log
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = tel
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = mva
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = mtr
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = mm
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = de
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = se
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = comtcp
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
set cmp = sdd
if ( -r "${PROJ_DIR}/${cmp}/etc/${cmp}_init" ) then
source ${PROJ_DIR}/${cmp}/etc/${cmp}_init
endif
unset cmp

#******************************************************************************
# set environment for project
#******************************************************************************
if ( -r "${PROJ_DIR}/login/login" ) then
source ${PROJ_DIR}/login/login
endif

#******************************************************************************
# end message
#******************************************************************************
#$say " %$this_script2, `date '+%H:%M:%S'` finished"

#******************************************************************************
# unset
#******************************************************************************
exit:
unset this_path2
unset this_script2
exit
#******************************************************************************

login
========
#******************************************************************************
#* module: login
#* description: project login definitions
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = echo
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# pathes
#******************************************************************************
set path_project_login = "${PROJ_DIR}/login"
set path_project_com = "${path_project_login}/com"

#******************************************************************************
# definitions make
#******************************************************************************
if ( -r "${path_project_com}/def_make" ) then
source ${path_project_com}/def_make
endif

#******************************************************************************
# definitions path
#******************************************************************************
if ( -r "${path_project_com}/def_path" ) then
source ${path_project_com}/def_path
endif

#******************************************************************************
# definitions unix commands
#******************************************************************************
if ( -r "${path_project_com}/def_unix" ) then
source ${path_project_com}/def_unix
endif

#******************************************************************************
# definitions user commands
#******************************************************************************
if ( -r "${path_project_com}/def_user" ) then
source ${path_project_com}/def_user
endif

#******************************************************************************
# welcome
#******************************************************************************
if ( -r "${path_project_com}/welcome" ) then
source ${path_project_com}/welcome
endif

#******************************************************************************
# exit
#******************************************************************************
unset path_project_login
unset path_project_com
exit

#******************************************************************************

def_unix
========
#******************************************************************************
#* module: def_user
#* description: user command settings
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# pathes
#******************************************************************************
set path_project_com1 = "${PROJ_DIR}/login/com"
set path_project_com2 = "${path_project_com1}/com"

#******************************************************************************
# user command settings
#******************************************************************************
alias cdproj "cd ${PROJ_DIR}"
alias cdmkf "cd ${PROJ_DIR}/mkf"
alias cdglb "cd ${PROJ_DIR}/glb"
alias cdutl "cd ${PROJ_DIR}/utl"
alias cdcom "cd ${PROJ_DIR}/com"
alias cdlog "cd ${PROJ_DIR}/log"
alias cdtel "cd ${PROJ_DIR}/tel"
alias cdtools "cd ${PROJ_DIR}/tools"
alias cdcomtcp "cd ${PROJ_DIR}/comtcp"
alias cdexport "cd ${PROJ_DIR}/export"
alias cdoracle "cd ${PROJ_DIR}/oracle"
alias cdsystem "cd ${PROJ_DIR}/system"
alias cds "cd /home/zzy/system"
alias cdbuild "cd ${PROJ_DIR}/oracle/build"
alias cdzzy "cd /home/zzy"

# make environments
alias mkglb "make -f ${PROJ_DIR}/glb/work/etc/glb.mkf"
alias mkutl "make -f ${PROJ_DIR}/utl/work/etc/utl.mkf"
alias mkcomtcp "make -f ${PROJ_DIR}/comtcp/work/etc/comtcp.mkf"
alias mkuserlib "make -f ${PROJ_DIR}/userlib/userlib.mkf"

#******************************************************************************
# exit
#******************************************************************************
unset path_project_com1
unset path_project_com2
exit

#******************************************************************************
def_make
============
#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

#******************************************************************************
#* module: def_make
#* description: make settings
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# pathes
#******************************************************************************
set path_project_com1 = "${PROJ_DIR}/login/com"
set path_project_com2 = "${path_project_com1}/com"

#******************************************************************************
# make settings
#******************************************************************************
# Add setenv debug=1 by zzy 2000-08-07
setenv debug 1
setenv OS unix
setenv OSVERS
setenv GLOBAL_MKF_HOME ${PROJ_DIR}/mkf/

#******************************************************************************
# exit
#******************************************************************************
unset path_project_com1
unset path_project_com2
exit

#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

def_path
============
#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

#******************************************************************************
#* module: def_path
#* description: path settings
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# path settings
#******************************************************************************
if ($?path) then
set path=($HOME/userlib $path)
else
set path=($HOME/bin /usr/bin .)
endif

#******************************************************************************
# exit
#******************************************************************************
exit

#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

def_user
============
#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

#******************************************************************************
#* module: def_user
#* description: user command settings
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# pathes
#******************************************************************************
set path_project_com1 = "${PROJ_DIR}/login/com"
set path_project_com2 = "${path_project_com1}/com"

#******************************************************************************
# user command settings
#******************************************************************************
alias cdproj "cd ${PROJ_DIR}"
alias cdmkf "cd ${PROJ_DIR}/mkf"
alias cdglb "cd ${PROJ_DIR}/glb"
alias cdutl "cd ${PROJ_DIR}/utl"
alias cdcom "cd ${PROJ_DIR}/com"
alias cdlog "cd ${PROJ_DIR}/log"
alias cdtel "cd ${PROJ_DIR}/tel"
alias cdtools "cd ${PROJ_DIR}/tools"
alias cdcomtcp "cd ${PROJ_DIR}/comtcp"
alias cdexport "cd ${PROJ_DIR}/export"
alias cdoracle "cd ${PROJ_DIR}/oracle"
alias cdsystem "cd ${PROJ_DIR}/system"
alias cds "cd /home/zzy/system"
alias cdbuild "cd ${PROJ_DIR}/oracle/build"
alias cdzzy "cd /home/zzy"

# make environments
alias mkglb "make -f ${PROJ_DIR}/glb/work/etc/glb.mkf"
alias mkutl "make -f ${PROJ_DIR}/utl/work/etc/utl.mkf"
alias mkcomtcp "make -f ${PROJ_DIR}/comtcp/work/etc/comtcp.mkf"
alias mkuserlib "make -f ${PROJ_DIR}/userlib/userlib.mkf"

#******************************************************************************
# exit
#******************************************************************************
unset path_project_com1
unset path_project_com2
exit

#******************************************************************************
#* Copyright (C) BS P4 2000. All Rights Reserved. Confidental *
#******************************************************************************

welcome
==========
#******************************************************************************
#* Copyright (C) BS 2000. All Rights Reserved. Confidental *
#******************************************************************************

#******************************************************************************
#* module: welcome
#* description: welcome
#* author: Zhou zeyan
#* version: 31.08.2000
#******************************************************************************

#******************************************************************************
# entry
#******************************************************************************

#******************************************************************************
# environment
#******************************************************************************
set say = "echo"
set mode = ""
set node = "`uname -n`"
set user = "`logname`"

#******************************************************************************
# pathes
#******************************************************************************
set path_project_com1 = "${PROJ_DIR}/login/com"
set path_project_com2 = "${path_project_com1}/com"

#**********************************************************************
# welcome
#**********************************************************************
set text6=" user: $user "
set text7=" node: $node "

echo ""
echo "======================================================================="
echo ""
echo " +-----------------------------------------------------+"
echo " | |"
echo " | ###### ####### ####### ####### |"
echo " | # # # # # |"
echo " | # # # # # |"
echo " | ###### # ####### # |"
echo " | # # # # |"
echo " | # # # # |"
echo " | # ####### # ####### |"
echo " | |"
echo " +-----------------------------------------------------+"
echo ""
echo "======================================================================="
echo " B S"
echo "======================================================================="
echo "$text6"
echo ""
echo "$text7"
echo "======================================================================="
echo ""
unset text6
unset text7

#**********************************************************************
# exit
#**********************************************************************
unset path_project_com1
unset path_project_com2
exit


-----------------------------------------------------------------------------------------


 
 
 
PM 信息 发邮件 复制 引用 回复 编辑  删除   [文艺天地 | 万有科学 | 汗青简牍 | 朝夕问道] 积分: 150   5 10 20 30 40 50 -5 -10 -20 -30 -40 -50   
 
quickleader [同济人]

CS. Tongji Universitat

来自: Tongji UniversitY
积分: 150

注册: 2002-06-20
发贴: 5893
[ 校园布告 | 有问有答 ]
[ 论坛规则 | RSS订阅 ] 
  Re:shell programming  发表于 : 2004-07-16 17:09:32  来源:BBS.TONGJI.NET   
 
shell编程例子 -- 一个.login例子
本文出自: 作者: (2001-10-01 10:00:00)
*****************************************************************
# * *
# * or in FAR 52.227-19, as applicable. *
# * *
# *****************************************************************
#
#
# HISTORY
#
# @(#)$RCSfile: .login,v $ $Revision: 4.1.7.3 $ (DEC) $Date: 1995/10/25 20:03:52
$
#
#
if ($?path) then
set path=($HOME/bin $path)
else
set path=($HOME/bin /usr/bin .)
endif
if ( ! ${?DT} ) then
stty dec new
tset -I -Q
endif
set mail=/usr/spool/mail/$USER


-----------------------------------------------------------------------------------------


 
 
 
PM 信息 发邮件 复制 引用 回复 编辑  删除   [文艺天地 | 万有科学 | 汗青简牍 | 朝夕问道] 积分: 150   5 10 20 30 40 50 -5 -10 -20 -30 -40 -50   
 
quickleader [同济人]

CS. Tongji Universitat

来自: Tongji UniversitY
积分: 150

注册: 2002-06-20
发贴: 5893
[ 校园布告 | 有问有答 ]
[ 论坛规则 | RSS订阅 ] 
  Re:shell programming  发表于 : 2004-07-16 17:09:51  来源:BBS.TONGJI.NET   
 
shell编程例子 -- 一个makefile例子
本文出自: 作者: (2001-10-01 12:00:00)
unix.mkf
========
#=============================================================================#
# Copyright (C) BS P4 2000. All Rights Reserved. Confidential #
#=============================================================================#

#=============================================================================#
# module: unix.mkf #
# description: global include for all makefiles #
# system UNIX #
# version: 2000.08.01 #
# Author: Zhou zeyan #
#=============================================================================#

#=============================================================================#
# processline #
#=============================================================================#
PLINE = PCFC

#=============================================================================#
# useful #
#=============================================================================#
NOTHING =
BLANC = $(NOTHING) $(NOTHING)
SAY = $(BLANC)echo$(BLANC)
CONTINUE = $(BLANC)echo"">/dev/null$(BLANC)
IF = $(BLANC)if$(BLANC)
THEN = ;then$(BLANC)
FI = ;fi$(BLANC)
FSY = [ -f$(BLANC)
FSN = [ ! -f$(BLANC)
FSE = $(BLANC)]$(BLANC)
CP = cp$(BLANC)
RCP = rcp$(BLANC)
PU = echo>/dev/null<
RM = rm$(BLANC)
DTOU = dos2unix
SS =
SM1 = .*

#=============================================================================#
# home device and directory #
#=============================================================================#
DEVHOME = /
DIRHOME = home/$(PROJ)

#=============================================================================#
# global directories #
#=============================================================================#
GLOBALDOS = $(DEVHOME)$(DIRHOME)/dos/
GLOBALMKF = $(DEVHOME)$(DIRHOME)/mkf/

#=============================================================================#
# Include application mkf #
#=============================================================================#
include $(GLOBAL_MKF_HOME)$(PROJ).mkf

#=============================================================================#
# oracle directories #
#=============================================================================#
ORAINC = $(ORACLE_HOME)/precomp/public/

#=============================================================================#
# system directories #
#=============================================================================#
SYSINC = /usr/include/
SYSINC2 = /usr/include/sys/

#=============================================================================#
# file extensions #
#=============================================================================#
EXTCOM =
EXTORS = .pc
EXTSRC = .c
EXTINC = .h
EXTOBJ = .o
EXTLIB = .a
EXTSHL =
EXTBIN =
EXTLIS = .lis

#=============================================================================#
# all include pathes #
#=============================================================================#
OCALLINC = $(BLANC)include=$(GLBINC) include=$(UTLINC) include=$(COMINC)
include=$(PKSINC) include=$(ORAINC) include=$(SIIXINC) include=$(CCMINC)
include=$(SYSINC) include=$(SYSINC2)

#=============================================================================#
# depencies for objects #
#=============================================================================#
GLBINC_ELE = $(GLBINC)ch_names.h $(GLBINC)cgl_inc.h $(GLBINC)tele_l1.h /
$(GLBINC)tele_l2.h
UTLINC_ELE = $(UTLINC)utl_inc.h $(UTLINC)utl_db_i.h
COMINC_ELE = $(COMINC)comp.h $(COMINC)dbgp.h
PKSINC_ELE = $(PKSINC)pks_comm.h
MVAINC_ELE =
MTINC_ELE =
ORAINC_ELE = $(ORAINC)sqlca.h
SIIXINC_ELE = $(SIIXINC)pdv_errno.h $(SIIXINC)ppx_errno.h
CCMINC_ELE = $(CCMINC)pcm_defs_u.h
SYSINC_ELE = $(SYSINC)stdio.h

#=============================================================================#
# depencies for binaries #
#=============================================================================#
GLBLIB_ELE =
UTLLIB_ELE = $(UTLLIB)libutl.a
COMLIB_ELE = $(COMLIB)libcom.a
USERLIB_ELE = $(USERLIBHOME)userlib.a
ORALIB_ELE = $(ORACLE_HOME)/lib/libsql.a
SIIXLIB_ELE =
CCMLIB_ELE = /opt/SiiXdvl/lib/libpics.a /opt/SiiXdvl/lib/libpdi.a /
/usr/lib/libnsl.so
SYSLIB_ELE = /usr/lib/libm.a
SOCKLIB_ELE = /usr/lib/libsocket.a /usr/lib/libdl.so /usr/lib/libintl.so

#=============================================================================#
# libraries for binaries #
#=============================================================================#
LIBGLB =
LIBUTL = $(BLANC)$(UTLLIB)libutl.a
LIBCOM = $(BLANC)$(COMLIB)libcom.a
LIBUSER = $(BLANC)$(USERLIBHOME)userlib.a
LIBMVA =
LIBMT =
LIBORA = $(BLANC)-L$(PROLDLIBS)
LIBSIIX =
LIBCCM = $(BLANC)/opt/SiiXdvl/lib/libpics.a /opt/SiiXdvl/lib/libpdi.a /
/usr/lib/libnsl.so.1
LIBSYS = $(BLANC)/usr/lib/libm.so
LIBSOCK = $(BLANC)/usr/lib/libsocket.so /usr/lib/libdl.so /usr/lib/libintl.so

#=============================================================================#
# Oracle Compiler #
#=============================================================================#
# name of compiler
OC = $(ORACLE_HOME)/bin/proc
# compilerflags and -switches
OCINC = include=
OCOPT = config=$(GLOBALMKF)proc.cfg

#=============================================================================#
# Compiler #
#=============================================================================#
# name of compiler
CC = /usr/bin/cc
# compilerflags and -switches
CCINC = -I
CCDEBUG = $(debug:1=-g)
# comment by zzy CCOPT = -c -DDEBUG $(CCDEBUG)
CCOPT = -c $(CCDEBUG)
# flag for objectfile
CCOBJ = -o

#=============================================================================#
# create and make library #
#=============================================================================#
# create library
CL = /usr/bin/ar -rc
# make library
ML = /usr/bin/ar -rcv
# separator between objectfiles
MLS =

#=============================================================================#
# Oracle Linker #
#=============================================================================#
# name of oracle linker
OL = cc -o
# linkerflags and -switches
OLDEBUG = $(debug:1=-g)
OLOPT = $(OLDEBUG)
# librarymark for object library
OLOL =
# librarymark for shared-library
OLSL =
# separator between objectfiles
OLS = $(BLANC)

#=============================================================================#
# Linker #
#=============================================================================#
# name of linker
LD = /usr/bin/cc
# linkerflags und -switches
LDDEBUG = $(debug:1=-g)
LDOPT = -o $(LDDEBUG)
# librarymark for object library
LDOL =
# librarymark for shared-library
LDSL =
# separator between objectfiles
LDS =

#=============================================================================#
# Copyright (C) BS P4 2000. All Rights Reserved. Confidential #
#=============================================================================#

host.mkf
========
#=============================================================================#
# Copyright (C) BS P4 2000. All Rights Reserved. Confidential #
#=============================================================================#

#=============================================================================#
# module: pcfc.mkf #
# description: application include for all makefiles #
# system UNIX #
# version: 2000.08.01 #
# Author: Zhou zeyan #
#=============================================================================#

#=============================================================================#
# USERLIB directories #
#=============================================================================#
USERLIBHOME = $(DEVHOME)$(DIRHOME)/userlib/

#=============================================================================#
# COMTCP directories #
#=============================================================================#
COMTCPHOME = $(DEVHOME)$(DIRHOME)/comtcp/
COMTCPWORKETC = $(COMTCPHOME)work/etc/
COMTCPWORKSRC = $(COMTCPHOME)work/src/
COMTCPWORKINC = $(COMTCPHOME)work/inc/
COMTCPWORKOBJ = $(COMTCPHOME)work/obj/
COMTCPWORKLIB = $(COMTCPHOME)work/lib/
COMTCPWORKBIN = $(COMTCPHOME)work/bin/
COMTCPWORKLIS = $(COMTCPHOME)work/src/
COMTCPSRC = $(COMTCPHOME)work/src/
COMTCPLIS = $(COMTCPHOME)work/src/
COMTCPETC = $(COMTCPHOME)etc/
COMTCPINC = $(COMTCPHOME)inc/
COMTCPOBJ = $(COMTCPHOME)obj/
COMTCPLIB = $(COMTCPHOME)lib/
COMTCPBIN = $(COMTCPHOME)bin/

#=============================================================================#
# Copyright (C) BS P4 2000. All Rights Reserved. Confidential #
#=============================================================================#

application.mkf
===============
#=============================================================================#
# Copyright (C) BS AG 1998. All Rights Reserved. Confidential #
#=============================================================================#

#=============================================================================#
# #
# Project : #
# BAO CRM3 CGL - Level 2 #
# #
# module name : #
# de.mkf #
# #
# Task #
# Makefile for programe de #
# #
# Author #
# Zhou zeyan #
# #
# Begin of implementation #
# Dec.31, 1998 #
# #
# Update #
# Zhou zeyan #
# #
# Update date #
# Feb.12, 1999 #
# #
# Release #
# Version 1.00 #
# #
# Definition #
# make -f de.mkf #
# #
# Parameters #
# No parameters #
# #
# Return code #
# No return code #
# #
#=============================================================================#

#=============================================================================#
# global include #
#=============================================================================#
include $(GLOBAL_MKF_HOME)$(OS).mkf

#=============================================================================#
# directories/files #
#=============================================================================#
DOS = $(DEWORKDOS)
ETC = $(DEWORKETC)
SRC = $(DEWORKSRC)
INC = $(DEWORKINC)
OBJ = $(DEWORKOBJ)
LIB = $(DEWORKLIB)
BIN = $(DEWORKBIN)
MSC = $(DEWORKMSC)
LIS = $(DEWORKLIS)
RUNETC = $(DEETC)
RUNSRC = $(DESRC)
RUNINC = $(DEINC)
RUNOBJ = $(DEOBJ)
RUNLIB = $(DELIB)
RUNBIN = $(DEBIN)
RUNMSC = $(DEMSC)

INAM_1 = qdr_inc

SNAM_1 = qdr
SNAM_2 = qdr_list
SNAM_3 = de

ONAM_1 = $(SNAM_1)
ONAM_2 = $(SNAM_2)
ONAM_3 = $(SNAM_3)

LNAM_1 = qdr

BNAM_2 = $(SNAM_2)
BNAM_3 = $(SNAM_3)x

IMOD_1 = $(INC)$(INAM_1)$(EXTINC)

PMOD_1 = $(SRC)$(SNAM_1)$(EXTORS)
SMOD_1 = $(SRC)$(SNAM_1)$(EXTSRC)
PMOD_2 = $(SRC)$(SNAM_2)$(EXTORS)
SMOD_2 = $(SRC)$(SNAM_2)$(EXTSRC)
PMOD_3 = $(SRC)$(SNAM_3)$(EXTORS)
SMOD_3 = $(SRC)$(SNAM_3)$(EXTSRC)

OMOD_1 = $(OBJ)$(ONAM_1)$(EXTOBJ)
OMOD_2 = $(OBJ)$(ONAM_2)$(EXTOBJ)
OMOD_3 = $(OBJ)$(ONAM_3)$(EXTOBJ)

LMOD_1 = $(LIB)$(LNAM_1)$(EXTLIB)

BMOD_2 = $(BIN)$(BNAM_2)$(EXTBIN)
BMOD_3 = $(BIN)$(BNAM_3)$(EXTBIN)

LIST_1 = $(LIS)$(SNAM_1)$(EXTLIS)

RUN_IMOD_1 = $(RUNINC)$(INAM_1)$(EXTINC)
RUN_BMOD_2 = $(RUNBIN)$(BNAM_2)$(EXTBIN)
RUN_BMOD_3 = $(RUNBIN)$(BNAM_3)$(EXTBIN)
RUN_LMOD_1 = $(RUNLIB)$(LNAM_1)$(EXTLIB)

#=============================================================================#
# generate #
#=============================================================================#
all : src obj lib bin
@ $(SAY) "$(@) done !"
@ $(SAY) ""

src : $(SMOD_1) $(SMOD_2) $(SMOD_3)
@ $(SAY) "$(@) done !"
@ $(SAY) ""

obj : $(OMOD_1) $(OMOD_2) $(OMOD_3)
@ $(SAY) "$(@) done !"
@ $(SAY) ""

lib : $(LMOD_1)
@ $(SAY) "$(@) done !"
@ $(SAY) ""

bin : $(BMOD_2) $(BMOD_3)
@ $(SAY) "$(@) done !"
@ $(SAY) ""

#=============================================================================#
# sources #
#=============================================================================#
$(SMOD_1) : $(PMOD_1) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
$(SAY) "+--- make $(@) ---+"
$(OC) iname=$(PMOD_1) $(OCINC)$(INC)$(OCALLINC) oname=$(@) /
$(OCOPT)
@ $(SAY) ""

$(SMOD_2) : $(PMOD_2) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
$(SAY) "+--- make $(@) ---+"
$(OC) iname=$(PMOD_2) $(OCINC)$(INC)$(OCALLINC) oname=$(@) /
$(OCOPT)
@ $(SAY) ""

$(SMOD_3) : $(PMOD_3) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
$(SAY) "+--- make $(@) ---+"
$(OC) iname=$(PMOD_3) $(OCINC)$(INC)$(OCALLINC) oname=$(@) /
$(OCOPT)
@ $(SAY) ""

#=============================================================================#
# objects #
#=============================================================================#
$(OMOD_1) : $(SMOD_1) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
@ $(SAY) "+--- make $(@) ---+"
$(CC) $(CCOPT)$(LIS) /
$(CCINC)$(INC) $(CCALLINC) $(CCOBJ)$(@) $(SMOD_1)
@ $(SAY) ""

$(OMOD_2): $(SMOD_2) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
@ $(SAY) "+--- make $(@) ---+"
$(CC) $(CCOPT)$(LIS) /
$(CCINC)$(INC) $(CCALLINC) $(CCOBJ)$(@) $(SMOD_2)
@ $(SAY) ""

$(OMOD_3): $(SMOD_3) $(IMOD_1) /
$(GLBINC_ELE) $(UTLINC_ELE) $(COMINC_ELE) $(PKSINC_ELE) /
$(SIIXINC_ELE) $(CCMINC_ELE) /
$(ORAINC_ELE) $(SYSINC_ELE)
@ $(SAY) "+--- make $(@) ---+"
$(CC) $(CCOPT)$(LIS) /
$(CCINC)$(INC) $(CCALLINC) $(CCOBJ)$(@) $(SMOD_3)
@ $(SAY) ""

#=============================================================================#
# libraries #
#=============================================================================#
$(LMOD_1) : $(OMOD_1)
@ $(SAY) "+--- make $(@) ---+"
@ $(IF) $(FSN) $(LMOD_1) $(FSE) $(THEN) $(CL) $(LMOD_1) $(FI)
$(ML) $(LMOD_1) $(OMOD_1)
@ $(SAY) ""

#=============================================================================#
# binaries #
#=============================================================================#
$(BMOD_2) : $(OMOD_2) /
$(MTLIB_ELE) $(COMLIB_ELE) $(CCMLIB_ELE) /
$(ORALIB_ELE) $(SYSLIB_ELE)
@ $(SAY) "+--- make $(@) ---+"
$(OL) $(@) $(OMOD_2) $(LIBCOM) $(LIBUTL) $(LIBCCM) /
$(LIBORA) $(LMOD_1) $(OLOPT)
@ $(SAY) ""

$(BMOD_3) : $(OMOD_3) /
$(MTLIB_ELE) $(COMLIB_ELE) $(CCMLIB_ELE) /
$(ORALIB_ELE) $(SYSLIB_ELE)
@ $(SAY) "+--- make $(@) ---+"
$(OL) $(@) $(OMOD_3) $(LIBCOM) /
$(LIBUTL) $(LIBPKS) $(LIBCCM) $(LIBORA) $(LMOD_1) $(OLOPT)
@ $(SAY) ""

#=============================================================================#
# export #
#=============================================================================#
export : /
exportetc exportsrc exportinc exportobj exportlib exportbin exportmsc
@ $(SAY) "$(@) done !"
@ $(SAY) ""

exportetc :
@ $(IF)$(FSY)$(RUNETC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNETC)"$(FI)
@ $(IF)$(FSY)$(RUNETC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNETC) $(FI)

exportsrc :
@ $(IF)$(FSY)$(RUNSRC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNSRC)"$(FI)
@ $(IF)$(FSY)$(RUNSRC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNSRC) $(FI)

exportinc : $(RUN_IMOD_1)
@ $(IF)$(FSY)$(RUNINC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNINC)"$(FI)
@ $(IF)$(FSY)$(RUNINC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNINC) $(FI)
$(RUN_IMOD_1) : $(IMOD_1)
$(CP) $(IMOD_1) $(RUN_IMOD_1)

exportobj :
@ $(IF)$(FSY)$(RUNOBJ)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNOBJ)"$(FI)
@ $(IF)$(FSY)$(RUNOBJ)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNOBJ) $(FI)

exportlib : $(RUN_LMOD_1)
@ $(IF)$(FSY)$(RUNLIB)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNLIB)"$(FI)
@ $(IF)$(FSY)$(RUNLIB)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNLIB) $(FI)
$(RUN_LMOD_1) : $(LMOD_1)
$(CP) $(LMOD_1) $(RUN_LMOD_1)

exportbin : $(RUN_BMOD_2) $(RUN_BMOD_3)
@ $(IF)$(FSY)$(RUNBIN)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNBIN)"$(FI)
@ $(IF)$(FSY)$(RUNBIN)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNBIN) $(FI)
$(RUN_BMOD_2) : $(BMOD_2)
$(CP) $(BMOD_2) $(RUN_BMOD_2)
$(RUN_BMOD_3) : $(BMOD_3)
$(CP) $(BMOD_3) $(RUN_BMOD_3)

exportmsc :
@ $(IF)$(FSY)$(RUNMSC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(RUNMSC)"$(FI)
@ $(IF)$(FSY)$(RUNMSC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(RUNMSC) $(FI)

#=============================================================================#
# delete old #
#=============================================================================#
delold : /
deloldetc deloldsrc deloldinc deloldobj deloldlib deloldbin deloldmsc /
deloldlis
@ $(SAY) "$(@) done !"
@ $(SAY) ""
deloldetc :
@ $(IF)$(FSY)$(ETC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(ETC)"$(FI)
@ $(IF)$(FSY)$(ETC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(ETC) $(FI)
deloldsrc :
@ $(IF)$(FSY)$(SRC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(SRC)"$(FI)
@ $(IF)$(FSY)$(SRC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(SRC) $(FI)
deloldinc :
@ $(IF)$(FSY)$(INC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(INC)"$(FI)
@ $(IF)$(FSY)$(INC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(INC) $(FI)
deloldobj :
@ $(IF)$(FSY)$(OBJ)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(OBJ)"$(FI)
@ $(IF)$(FSY)$(OBJ)*.*$(SM1)$(FSE)$(THEN) $(PU)$(OBJ) $(FI)
deloldlib :
@ $(IF)$(FSY)$(LIB)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(LIB)"$(FI)
@ $(IF)$(FSY)$(LIB)*.*$(SM1)$(FSE)$(THEN) $(PU)$(LIB) $(FI)
deloldbin :
@ $(IF)$(FSY)$(BIN)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(BIN)"$(FI)
@ $(IF)$(FSY)$(BIN)*.*$(SM1)$(FSE)$(THEN) $(PU)$(BIN) $(FI)
deloldmsc :
@ $(IF)$(FSY)$(MSC)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(MSC)"$(FI)
@ $(IF)$(FSY)$(MSC)*.*$(SM1)$(FSE)$(THEN) $(PU)$(MSC) $(FI)
deloldlis :
@ $(IF)$(FSY)$(LIS)*.*$(SM1)$(FSE)$(THEN)$(SAY)"$(PU)$(LIS)"$(FI)
@ $(IF)$(FSY)$(LIS)*.*$(SM1)$(FSE)$(THEN) $(PU)$(LIS) $(FI)

#=============================================================================#
# clean #
#=============================================================================#
clean : /
cleanetc cleansrc cleaninc cleanobj cleanlib cleanbin cleanmsc /
cleanlis
@ $(SAY)"$(@) done !"
@ $(SAY)""
cleanetc :
@ $(CONTINUE)
cleansrc :
@ $(IF)$(FSY)$(SMOD_1) $(FSE)$(THEN)$(SAY)"$(RM)$(SMOD_1)$(SS)"$(FI)
@ $(IF)$(FSY)$(SMOD_1) $(FSE)$(THEN) $(RM)$(SMOD_1)$(SS) $(FI)
@ $(IF)$(FSY)$(SMOD_2) $(FSE)$(THEN)$(SAY)"$(RM)$(SMOD_2)$(SS)"$(FI)
@ $(IF)$(FSY)$(SMOD_2) $(FSE)$(THEN) $(RM)$(SMOD_2)$(SS) $(FI)
@ $(IF)$(FSY)$(SMOD_3) $(FSE)$(THEN)$(SAY)"$(RM)$(SMOD_3)$(SS)"$(FI)
@ $(IF)$(FSY)$(SMOD_3) $(FSE)$(THEN) $(RM)$(SMOD_3)$(SS) $(FI)
@ $(CONTINUE)
cleaninc :
@ $(CONTINUE)
cleanobj :
@ $(IF)$(FSY)$(OMOD_1) $(FSE)$(THEN)$(SAY)"$(RM)$(OMOD_1)$(SS)"$(FI)
@ $(IF)$(FSY)$(OMOD_1) $(FSE)$(THEN) $(RM)$(OMOD_1)$(SS) $(FI)
@ $(IF)$(FSY)$(OMOD_2) $(FSE)$(THEN)$(SAY)"$(RM)$(OMOD_2)$(SS)"$(FI)
@ $(IF)$(FSY)$(OMOD_2) $(FSE)$(THEN) $(RM)$(OMOD_2)$(SS) $(FI)
@ $(IF)$(FSY)$(OMOD_3) $(FSE)$(THEN)$(SAY)"$(RM)$(OMOD_3)$(SS)"$(FI)
@ $(IF)$(FSY)$(OMOD_3) $(FSE)$(THEN) $(RM)$(OMOD_3)$(SS) $(FI)
@ $(CONTINUE)
cleanlib :
@ $(IF)$(FSY)$(LMOD_1)$(FSE)$(THEN)$(SAY)"$(RM)$(LMOD_1)$(SS)"$(FI)
@ $(IF)$(FSY)$(LMOD_1)$(FSE)$(THEN) $(RM)$(LMOD_1)$(SS) $(FI)
@ $(CONTINUE)
cleanbin :
@ $(IF)$(FSY)$(BMOD_2)$(FSE)$(THEN)$(SAY)"$(RM)$(BMOD_2)$(SS)"$(FI)
@ $(IF)$(FSY)$(BMOD_2)$(FSE)$(THEN) $(RM)$(BMOD_2)$(SS) $(FI)
@ $(IF)$(FSY)$(BMOD_3)$(FSE)$(THEN)$(SAY)"$(RM)$(BMOD_3)$(SS)"$(FI)
@ $(IF)$(FSY)$(BMOD_3)$(FSE)$(THEN) $(RM)$(BMOD_3)$(SS) $(FI)
@ $(CONTINUE)
cleanmsc :
@ $(CONTINUE)
cleanlis :
@ $(CONTINUE)


-----------------------------------------------------------------------------------------
 
Bash最常见的激活模式

Bash最常见的激活模式是交互式和非交互式:
1.交互式激活
指其标准输入和输出都连接在终端上.又分为三种类型:login,非login,posix
以及受限的shell.
确定一个shell是否是交互式的可以通过检测$PS1环境变量.
(1) 当Bash作为login shell被激活时,它将依次读取并执行以下文件:
/etc/profile,~/.bash_profile,~/.bash_login,~/.profile
使用--noprofile选项激活Bash可以禁止其读任何初始化文件
在退出时执行 ~/.bash_logout 文件
(2) 当Bash作为非login shell被激活时,它将读取并执行~/.bashrc
使用--norc选项激活Bash可以禁止执行任何初始化文件,使用
--rcfile file可以指定执行的初始化文件.
(3) 当Bash作为posix模式被激活时,它将先检查$ENV变量是否定义.
若定义,Bash读取并执行有$ENV变量扩展而得到的文件,否则不再
执行任何初始化文件。
(4) 当Bash作为受限模式被激活时,它除了禁止某些操作以外,其他行为
于其他模式相同.受限操作有:改变目录,修改$SHELL和$PATH变量,
运行exec,以绝对路径运行程序以及使用重定向.Bash 1.x中不包含
受限模式.
2.非交互式激活
主要用来运行Shell脚本.启动后,Bash检查$BASH_ENV变量,若定义,
这执行该变量指定文件中包含的命令.

Bash 的激活选项
-c string 该选项表明string中包含了一条命令.如 bash -c ls ~
-i 使Bash以交互式方式运行
-r 使Bash以受限方式运行
--login 使Bash以登录Shell方式运行
--posix 使Bash遵循POSIX标准
--verbose 使Bash显示所有其读入的输入行
--help 打印Bash的使用信息
--version 打印版本信息
--noprofile
--norc
--rcfile file


-----------------------------------------------------------------------------------------
 
Bash中的变量

1.用户定义的变量
用户定义的变量有字母数字及下划线组成,并且变量名的第一个字符不能为数字.
与其它UNIX名字一样,变量名是大小写敏感的.
对于变量,用户可按如下方式赋值:
name = value
在引用变量时,需在前面加$符号,用户也可以在变量间进行相互赋值,如:
(前面的$是命令提示符)

$ JOHN = john
$ NAME = $JOHN
$ echo Hello $NAME
Hello john

也可以用变量和其他字符组成新的字,这时可能需要把变量用{}括起,如:

$ SAT = Satur
$ echo Today is ${SAT}day
Today is Saturday

对于未赋值的变量,Bash以空值对待,用户也可以用unset命令清除给变量
赋的值.

Bash中还可以使用数组变量,其赋值有两种:

(1) name[index] = value
(2) name = (value1 ... valuen) 此时下标从0开始

数组下标的范围没有任何限制,同时也不必使用连续的分量.

Bash中关于变量的内建命令有:

(1) declare和typeset.两者具有一样的功能.其选项有:
[-/+]a 设置/撤消变量的数组属性
[-/+]i 设置/撤消变量的整数属性
[-/+]r 设置/撤消变量的只读属性
[-/+]x 设置/撤消变量的输出属性
-p var 显示变量属性
(2) export和local.
export把变量输出到环境中,用法为:
export name
export name = value

这里需要简单介绍一下export的作用:当Bash shell执行一个
程序时,将首先为该程序建立一个新的执行环境,称为子shell,
在Bash Shell中变量都是局部的,即它们只是在创建它们的子
Shell中是有意义的,使用export后,变量被设置为全局变量,这
时可以被其它子Shell所识别

local标记变量为局部的(如只能被函数内部使用),用法为:
local name
local name = value
(3) readonly.
指定变量为只读,执行后,改变量不能被再次赋值,用法为:
readonly name

2.位置变量或Shell参数
Bash Shell在解释用户命令时,将把命令行的第一个子作为命令,而其它字作为
参数通过位置变量传递给程序.$1,...,$9分别代表第一,...,九个参数.其中1-9
是真正的参数名,"$"符只是用来标识变量的替换.
位置变量$0指命令对应的可执行名.
其它的还有:
$# 送给命令的参数个数
$@ 所有的参数,每个用双括号括起
$* 所有的参数,用双括号括起
3.与Shell有关的变量
(1) Shell自身设置的一些常用变量:
LINENO 正在执行的命令在脚本中的行号
PWD 用户当前目录的全名
OLDPWD 最近一次执行cd之前,用户当前目录的全名
PPID 父进程ID
$ 当前进程ID
RANDOM 随机数(范围0-32767)
SECONDS Bash Shell的运行时间,单位是秒
REPLY select和read命令使用,以后会讲到
OPTARG
ORTIND 这两个变量由getopt命令设置
UID 当前用户的User ID
_ 上一条命令使用的最后一个参数
(2) 影响Shell行为的一些常用环境变量:
PATH 命令搜索路径,以冒号为分隔符.注意与DOS下不同的是,
当前目录不在系统路径里
HOME 用户home目录的路径名,是cd命令的默认参数
COLUMNS 定义了命令编辑模式下可使用命令行的长度
EDITOR 默认的行编辑器
VISUAL 默认的可视编辑器
FCEDIT 命令fc使用的编辑器
HISTFILE 命令历史文件
HISTSIZE 命令历史文件中最多可包含的命令条数
HISTFILESIZE 命令历史文件中包含的最大行数
IFS 定义SHELL使用的分隔符
LOGNAME 用户登录名
MAIL 指向一个需要SHELL监视其修改时间的文件.当该文件修改后,
SHELL将发消息You hava mail给用户
MAILCHECK SHELL检查MAIL文件的周期,单位是秒
MAILPATH 功能与MAIL类似.但可以用一组文件,以冒号分隔,每个文件后
可跟一个问号和一条发向用户的消息
SHELL SHELL的路径名
TERM 终端类型
TMOUT SHELL自动退出的时间,单位为秒,若设为0则禁止SHELL自动退出
PROMPT_COMMAND 指定在主命令提示符前应执行的命令
PS1 主命令提示符
PS2 二级命令提示符,命令执行过程中要求输入数据时用
PS3 select的命令提示符
PS4 调试命令提示符
MANPATH 寻找手册页的路径,以冒号分隔
LD_LIBRARY_PATH 寻找库的路径,以冒号分隔


-----------------------------------------------------------------------------------------
 
 
Bash中的特殊字符

1.通配符
* 匹配任何长度的任何串
? 匹配单个字符
[...] 匹配单个括号内的字符,[]中的-,!具有特殊含义,如:
$ echo [a-z]*
显示首字母在a-z范围内的文件或目录名
$ echo [a,b]*
显示首字母为a或b的文件或目录名
$ echo [!a]*
显示首字母不为a的文件或目录名(使用!时,!必须是[后的第一个字符)
!还可与-和,一起使用

在Bash 2.0以后的版本中,若用shopt打开了extglob选项(shopt -s extglob),
那么还可以扩展的模式表达式(模式表达式是指那些包含了一个或多个shell通配
符的字):
*(pattern [|pattern] ...) 匹配模式的零次或多次出现
+(pattern [|pattern] ...) 匹配模式的一次或多次出现
@(pattern [|pattern] ...) 匹配模式的一次出现
?(pattern [|pattern] ...) 匹配任何一个模式.与*不同的是它不匹配
多个模式或模式的重复出现
!(pattern [|pattern] ...) 与?类似,不过是不包括指定模式的串
应该注意到,模式表达式的定义是递归的,每个表达式都可以包含一个或多个
模式,而且模式表达式也是可以嵌套的.

2.数据或程序控制使用的特殊字符:
主要有:
> (file) 输出重定向到文件
>> (file) 输出重定向到文件,内容加到已存在的文件尾部
< (file) 输入重定向到文件
; 命令分隔符
| 管道符,把一条命令的输出重定向为另一命令的输入
& 放在命令之后强迫命令在后台执行
`` 命令替换,重定向一条命令的输出为另一命令的参数

3.用于引用和逃逸的特殊字符:
逃逸符/ 表示以后的字符不具有特殊的含义或不是Shell的函数,
除此之外,Bash还可以识别一些C语言中的转义序列,如:
/a 响伶
/b 回退
/e Escape
/n 换行
/r 回车
/t 制表
/v 制表
// 反斜线
/nnn 八进制的ASCII编码
/xnnn 十六进制的ASCII编码
但必须以如下方式进行引用:
$'string'
引用符'和" 将特殊字符或由空白分隔的字引用起来组成一个简单字符串
两者区别在与,双引号内的内容可以进行参数和变量替换

你可能感兴趣的:(linux技术)