Chinaunix首页 | 论坛 | 博客
  • 博客访问: 518367
  • 博文数量: 174
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 1827
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-15 14:12
文章分类

全部博文(174)

文章存档

2018年(1)

2017年(1)

2013年(3)

2012年(9)

2010年(12)

2009年(5)

2008年(106)

2007年(37)

我的朋友

分类:

2008-08-26 23:33:47

使用环境变量的shell脚本(如MAILER和PAGER)存在一些隐藏的危险,可能有部份设置是指向不存在的程序。举个例子说下,在显示脚本的 输出时,如果我们选择灵活性强的PAGER设置来取代一个制式的特定工具,那么要如何确保PAGER值是指向一个存在的程序呢?而如果它是指向一个不存在 的程序,那么脚本将会中断。下面这个脚本会帮我们判断程序是否存在于PATH中,同时它也可以作为一个在不同工作环境中使用脚本技术(包含方程式与变数) 的良好范例。

脚本源代码

#!/bin/sh
# inpath - 证实我们所提供的程序是否能够执行
#   或存在于系统的设定的PATH中

in_path()
{
  # 给出一个路径及命令,脚本尝试去查询这个命令
  # 如果在PATH中找到并且可以执行,则返回0,否则返回1
  # 它将暂时修改IFS的值,执行后即恢复IFS的值.

  cmd=$1

  path=$2

  retval=1
  oldIFS=$IFS

  IFS=":"

  for directory in $path
  do
    if [ -x $directory/$cmd ] ; then
      retval=0      # 在指定的目录($directory)中找到指令($cmd),返回0
    fi
  done
  IFS=$oldIFS
  return $retval
}

checkForCmdInPath()
{
  var=$1

  # 下面的变量运作需要作下说明:${var#expr}会留下变量中expr后的一个字元,
  # 而${var%expr}则留下var变量中与expr不同的字串,下面的例子中,恰巧会留下第一个字元
  # 在Bash的环境下我们也可以使用${var:0:1}或cut -c1

  if [ "$var" != "" ] ; then
    if [ "${var%${var#?}}" = "/" ] ; then
      if [ ! -x $var ] ; then
        return 1
      fi
    elif ! in_path $var $PATH ; then
      return 2
    fi
  fi
}


*************************************************************
注意:我编写的脚本要存放到哪里去?
我 建议你在主目录(home目录)下新增一个名为"scripts"的新目录,并将其完整的路径加在PATH的变量中。我们可以通过echo $PATH指令来查看正确的PATH。要修改来修改PATH变量的话,使用vi工具去编辑你的主目录下的".login"或".profile"文档,, 以符合我们的需求。
**************************************************************


运行脚本
在执行这个脚本程序之前,我们必须在这段代码后再附加上一段,让它能够对前面执行的传回值进行判断,代码如下:

if [ $# -ne 1 ] ; then
 echo "Usage: $0 command" >&2 ; exit 1
fi

checkForCmdInPath "$1"
case $? in
  0 ) echo "$1 found in PATH"                  ;;
  1 ) echo "$1 not found or not executable"    ;;
  2 ) echo "$1 not found in PATH"              ;;
esac

exit 0

把上面的代码添加到原先的脚本代码后,我们就完成该脚本,可以运行并显示结果啦。如果你觉得这段新加上去的代码会很难理解,可以考虑将它去掉或者将其注释掉。

结果

我们分別准备三个档案来测试inpath程序:第一个是存在的档案、第二个也是存在的档案,但它的路径并不在PATH的设定中,第三个档案我们会输入完整的路径与档案名,但它并不存在。

$ inpath echo
echo found in PATH
$ inpath MrEcho
MrEcho not found in PATH
$ inpath /usr/bin/MrEcho
/usr/bin/MrEcho not found or not executable

改进与加强
${str#substr} 从str左边截掉第一个匹配到的substr,并返回剩下的字符串
${str##substr} 从str左边截掉最后一个匹配到的substr,并返回剩下的字符串
${str%substr} 从str右边截掉第一个匹配到的substr,并返回剩下的字符串
${str%%substr} 从str右边截掉最后一个匹配到的substr,并返回剩下的字符串
或 许这个程序较特別的部份是利用POSIX的变量分配方式:${var%${var#?}}。我们来探讨这个表达式,其实它是个表面复杂,但实际上却是两个 巢状的字串。在巢状字串里层的是${var#?},用来分离var变量第一个字元后的字串(? 是一个万用字元,代表着任何一个字元)。接着外层的 ${vat%pattern} 将移除与pattern(即里层运算后的结果)相符的字串,再产生一个字串。从我们这个脚本来看,产生出来的字串将是第一个字元。

这是相 当复杂的解释。但关键就在 check- ForCmdInPath 的运作。由于变量可能是单独的档案名(echo)或是完整的路径与档案名(如 "/bin/echo"),check- ForCmdInPath必须分辨出两者之间的不同,它会去检查这个变数的第一个字元是否"/",因此我们必须先将变数的第一个字元分离出来。

如 果POSIX的变数让你觉得恐慌,bash与ksh支支持另一种变量方法:${varname:start:size},这个方式可以直接从变量 varname中的第"start"个字元取得"size"个字元。举例来说${varname : 0 : 1},将会从varname变量中的第1个字元开始,共取得1个字元。当然,如果还是不喜欢这种取字元的方法,也可以考虑另一种方法:$(echo $var | cut -c1)。
阅读(1029) | 评论(0) | 转发(0) |
0

上一篇:udev详解

下一篇:嵌入式Linux文件系统简介

给主人留下些什么吧!~~