文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>BASH学习笔记(一)

BASH学习笔记(一)

时间:2009-07-14  来源:potatofamily


BASH简介

bash 是一个为GNU项目编写的Unix shell。它的名字是一系列缩写:Bourne-AgainSHell — 这是关于Bourne bash(sh)的一个双关语(Bourne again / born again)。Bourne shell是一个早期的重要shell,由Stephen Bourne在1978年前后编写,并同Version 7 Unix一起发布。bash则在1987年由Brian Fox创造。在1990年,Chet Ramey成为了主要的维护者。

bash是大多数Linux系统以及Mac OS X默认的shell,它能运行于大多数Unix like操作系统之上,甚至被移植到了Microsoft Windows上的Cygwin和MSYS系统中,以实现Windows的POSIX虚拟接口。此外,它也被DJGPP项目移植到了MS-DOS上。

------以上来自维基百科

Linux之父Linus对BASH的描述: 我下载了一个叫Borne Shell的外壳程序。它是UNIX的初始外壳程序之一,可以从互联网上免费下载,名字来源于一个难听的双关语。编写该外壳程序的家伙名叫波恩(“出生”之意),所以这个程序就叫做“Borne Again Shell”(“再次降生外壳程序”),或一般被称为BASH(bash的英文意为“重击”)。   BASH的正确缩写: BASH = GNU Bourne-Again SHell,BASH 是 GNU 组织开发和推广的一个项目。   BASH的作者和产生: Bourne shell 的作者是 Steven Bourne,它是 UNIX 最初使用的 Shell 并且在每种 UNIX 上都可以使用。 而BASH 与 Bourne shell 完全向后兼容,是Bourne shell的扩展。   双关语的经典之处: [1]作者名叫Steven Bourne,“bourne”与“borne”的发音相近,而born有“出生”和“忍受”的含义。 [2]Bourne-Again字面意思代表了它是“Bourne shell”l的一种扩展,而暗示“borne-again”、“born-again”则有“重生”和“再次忍受”的意思。(我想作者应该更喜欢“重生”) [3]它的简写“bash”的意思是“重击”,暗示它的出现是一次强有力的重击。
bash脚本就是许多现成命令的罗列, Shell脚本遵循典型的UNIX哲学,就是把大的复杂的工程分成小规模的子任务,并且把这些部件和工具组合起来。许多人认为这种办法更好一些,至少这种办法比使用那种高\大\全的语言更美,更愉悦,更适合解决问题。比如Perl就是这种能干任何事能适合任何人的语言,但是代价就是你需要强迫自己使用这种语言来思考解决问题的办法。
什么时候不使用Shell脚本? 资源密集型的任务,尤其在需要考虑效率时(比如,排序,hash等等)
需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN来处理)
有跨平台移植需求(一般使用C或Java)
复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)
对于影响系统全局性的关键任务应用。
对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵,破解,恶意破坏等等。
项目由连串的依赖的各个部分组成。
需要大规模的文件操作
需要多维数组的支持
需要数据结构的支持,比如链表或数等数据结构
需要产生或操作图形化界面GUI
需要直接操作系统硬件
需要I/O或socket接口
需要使用库或者遗留下来的老代码的接口
私人的,闭源的应用(shell脚本把代码就放在文本文件中,全世界都能看到)
二、 编写一个shell脚本
============================================== 一个简单的shell脚本其实就是将一堆系统命令罗列在一个文件中。它的最基本的 用处就是, 如果你需要按照固定顺序重复执行这些命令时可以少敲一些字(懒人专用)。
Example 2-1 清除:清除/var/log下的log文件 ########################## 脚本开始 ########################### #!/bin/bash # 清除 # 必须使用root身份来运行这个脚本 cd /var/log cat /dev/null > messages cat /dev/null > wtmp echo "Logs cleaned up." ########################## 脚本结束 ########################### 这根本就没什么稀奇的, 只不过是命令的堆积, 仅仅比从console或者xterm中一个一个的输入命令更方便一些。好处就是把所有命令都放在一个脚本中,不用每次都敲它们。这样的话,对于同一类型的应用来说,这个脚本就很容易被修改或定制以适应新的需要。
Example 2-2 清除:一个改良的清除脚本 ########################## 脚本开始 ########################### #!/bin/bash # 一个Bash脚本的正确的开头部分. # Cleanup, 版本 2 # 当然要使用root身份来运行. # 在此处插入代码,来打印错误消息,并且在不是root身份的时候退出.
LOG_DIR=/var/log # 如果使用变量,当然比把代码写死的好. cd $LOG_DIR
cat /dev/null > messages cat /dev/null > wtmp
echo "Logs cleaned up."
exit # 这个命令是一种正确并且合适的退出脚本的方法. ########################## 脚本结束 ###########################
现在,让我们看一下一个真正意义的脚本。其实我们还可以做到更好... Example 2-3. cleanup:一个增强的广义的删除日志文件的脚本 ########################## 脚本开始 ########################### #!/bin/bash # 清除, 版本 3   #  Warning: #  ------- #  这个脚本有好多特征,这些特征是在后边章节进行解释的,大概是进行到本书的一半的 #  时候, #  你就会觉得它没有什么神秘的了. #
LOG_DIR=/var/log ROOT_UID=0     # $UID为0的时候,用户才具有根用户的权限 LINES=50       # 默认的保存行数 E_XCD=66       # 不能修改目录? E_NOTROOT=67   # 非根用户将以error退出
# 当然要使用根用户来运行 if [ "$UID" -ne "$ROOT_UID" ] then     echo "Must be root to run this script."     exit $E_NOTROOT fi  
if [ -n "$1" ] # 测试是否有命令行参数(非空). then     lines=$1 else       lines=$LINES # 默认,如果不在命令行中指定 fi  
# #    E_WRONGARGS=65  # 非数值参数(错误的参数格式) # #    case "$1" in #    ""      ) lines=50;; #    *[!0-9]*) echo "Usage: `basename $0` file-to-cleanup"; exit $E_WRONGARGS;; #    *       ) lines=$1;; #    esac # #* 直到"Loops"的部分才会对上边的内容进行详细的描述.
cd $LOG_DIR
if [ `pwd` != "$LOG_DIR" ]  # 或者 if[ "$PWD" != "$LOG_DIR" ]                             # 不在 /var/log中? then     echo "Can't change to $LOG_DIR."     exit $E_XCD fi  # 在处理log file之前,再确认一遍当前目录是否正确.
# 更有效率的做法是 # # cd /var/log || { #   echo "Cannot change to necessary directory." >&2 #   exit $E_XCD; # }
tail -$lines messages > mesg.temp # 保存log file消息的最后部分. mv mesg.temp messages             # 变为新的log目录.
# cat /dev/null > messages #* 不再需要了,使用上边的方法更安全.
cat /dev/null > wtmp  #  ': > wtmp' 和 '> wtmp'具有相同的作用 echo "Logs cleaned up."
exit 0 #  退出之前返回0,返回0表示成功. # ########################## 脚本结束 ###########################
因为你可能希望将系统log全部消灭,这个版本留下了log消息最后的部分.你将不断地找到新 的方法来完善这个脚本,并提高效率。
要注意,在每个脚本的开头都使用"#!",这意味着告诉你的系统这个文件的执行需要指定一个解 释器.#!实际上是一个2字节[1]的魔法字符,这是指定一个文件类型的特殊标记, 换句话说, 在 这种情况下,指的就是一个可执行的脚本(键入man magic来获得关于这个迷人话题的更多详细 信息).在#!之后接着是一个路径名.这个路径名指定了一个解释脚本中命令的程序,这个程序可 以是shell,程序语言或者是任意一个通用程序.这个指定的程序从头开始解释并且执行脚本中 的命令(从#!行下边的一行开始),忽略注释.[2] 如: 1 #!/bin/sh 2 #!/bin/bash 3 #!/usr/bin/perl 4 #!/usr/bin/tcl 5 #!/bin/sed -f 6 #!/usr/awk -f
上边每一个脚本头的行都指定了一个不同的命令解释器,如果是/bin/sh,那么就是默认shell (在Linux系统中默认是Bash).[3]使用#!/bin/sh,在大多数商业发行的UNIX上,默认是Bourne shell,这将让你的脚本可以正常的运行在非Linux机器上,虽然这将会牺牲Bash一些独特的特征. 脚本将与POSIX[4] 的sh标准相一致.
注意: #! 后边给出的路径名必须是正确的,否则将会出现一个错误消息,通常是 "Command not found",这将是你运行这个脚本时所得到的唯一结果.
当然"#!"也可以被忽略,不过这样你的脚本文件就只能是一些命令的集合,不能够使用shell内建 的指令了,如果不能使用变量的话,当然这也就失去了脚本编程的意义了.
注意:这个例子鼓励你使用模块化的方式来编写脚本,平时也要注意收集一些零碎的代码, 这些零碎的代码可能用在你将来编写的脚本中.这样你就可以通过这些代码片段来构 造一个较大的工程用例. 以下边脚本作为序,来测试脚本被调用的参数是否正确. ########################## 脚本开始 ########################### E_WRONG_ARGS=65 script_parameters="-a -h -m -z" #                  -a = all, -h = help, 等等.
if [ $# -ne $Number_of_expected_args ] then   echo "Usage: `basename $0` $script_parameters"   # `basename $0`是这个脚本的文件名   exit $E_WRONG_ARGS fi ########################## 脚本结束 ########################### 大多数情况下,你需要编写一个脚本来执行一个特定的任务,在本章中第一个脚本就是一个这样 的例子, 然后你会修改它来完成一个不同的,但比较相似的任务。用变量来代替写死的常量,就是 一个好方法,将重复的代码放到一个函数中,也是一种好习惯。

2.1 调用一个脚本 ---------------- 编写完脚本之后,你可以使用sh scriptname,[5]或者bash scriptname来调用它. (不推荐使用sh <scriptname,因为这禁用了脚本从stdin中读数据的功能.) 更方便的方法是让脚本本身就具有可执行权限,通过chmod命令可以修改.
比如:     chmod 555 scriptname (允许任何人都具有 可读和执行权限) [6]   或: chmod +rx scriptname (允许任何人都具有 可读和执行权限) chmod u+rx scriptname (只给脚本的所有者 可读和执行权限)
既然脚本已经具有了可执行权限,现在你可以使用./scriptname.[7]来测试它了.如果这个脚本 以一个"#!"行开头,那么脚本将会调用合适的命令解释器来运行.
最后一步,在脚本被测试和debug之后,你可能想把它移动到/usr/local/bin或者/usr/bin(当然是以root身份),来让你的脚本对所有用户都有用.这样用户就可以直接敲脚本名字来运行了。
注意事项: [1] 那些具有UNIX味道的脚本(基于4.2BSD)需要一个4字节的魔法字符,在#!后边需要一个空格                 #! /bin/sh. [2] 脚本中的#!行的最重要的任务就是命令解释器(sh或者bash).因为这行是以#开始的, 当命令解释器执行这个脚本的时候,会把它作为一个注释行.当然,在这之前,这行语句 已经完成了它的任务,就是调用命令解释器.
如果在脚本的里边还有一个#!行,那么bash将把它认为是一个一般的注释行. #!/bin/bash echo "Part 1 of script." a=1 #!/bin/bash # 这将不会开始一个新脚本. echo "Part 2 of script." echo $a  # Value of $a stays at 1. [3] 这里可以玩一些小技巧. #!/bin/rm # 自删除脚本. # 当你运行这个脚本时,基本上什么都不会发生...除非这个文件消失不见. WHATEVER=65 echo "This line will never print (betcha!)." exit $WHATEVER  # 没关系,脚本是不会在这退出的. 当然,你还可以试试在一个README文件的开头加上#!/bin/more,并让它具有执行权限. 结果将是文档自动列出自己的内容.(一个使用cat命令的here document也可能是一个 更好的选则。). [4] 可移植的操作系统接口,标准化类UNIX操作系统的一种尝试.POSIX规范可以在 http://www.opengroup.org/onlinepubs/007904975/toc.htm中查阅。 [5] 小心:使用sh scriptname来调用脚本的时候将会关闭一些Bash特定的扩展,脚本可能 因此而调用失败. [6] 脚本需要读和执行权限,因为shell需要读这个脚本. [7] 为什么不直接使用scriptname来调用脚本?如果你当前的目录下($PWD)正好有你想要 执行的脚本,为什么它运行不了呢?失败的原因是,出于安全考虑,当前目录并没有被 加在用户的$PATH变量中.因此,在当前目录下调用脚本必须使用./scriptname这种 形式。
第一篇笔记,记录shell脚本的基础知识。
相关阅读 更多 +
排行榜 更多 +
盒子小镇2游戏手机版下载

盒子小镇2游戏手机版下载

冒险解谜 下载
世界盒子模组版下载最新版本

世界盒子模组版下载最新版本

模拟经营 下载
音乐搜索app最新版本下载

音乐搜索app最新版本下载

趣味娱乐 下载