Chinaunix首页 | 论坛 | 博客
  • 博客访问: 216808
  • 博文数量: 60
  • 博客积分: 2440
  • 博客等级: 大尉
  • 技术积分: 530
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-12 16:38
文章分类

全部博文(60)

文章存档

2011年(2)

2010年(16)

2009年(42)

我的朋友

分类: LINUX

2010-05-31 17:14:35


13.2.3 Shell 参数

几个需要记住的特殊参数

     $0      = shell 名称或 shel 脚本名称
     $1      = 第一个(1)shell 参数
      ...
     $9      = 第九个(9)shell 参数
     $#      = 位置参数的个数
     "$*"    = "$1 $2 $3 $4 ... $n"
     "$@"    = "$1" "$2" "$3" "$4" ... "$n"
     $?      = 最近执行的命令的退出状态
     $$      = 当前 shell 脚本的 PID
     $!      = 最近启动的后台作业的 PID

需要记住的基本扩展参数

         形式        如果设置了 var      如果没有设置 var
     ${var:-string}  $var                string
     ${var:+string}  string              null
     ${var:=string}  $var                string 
                                         (并且执行 var=string)
     ${var:?string}  $var                (返回 string 然后退出)

在此,冒号“:”在所有运算表达式中事实上均是可选的。

  • 有“:” = 运算表达式测试“存在”和“非空”。

  • 没有“:” = 运算表达式仅测试“存在”。

需要记住的替换参数

         形式        	结果
     ${var%suffix}   删除位于 var 结尾的 suffix 最小匹配模式
     ${var%%suffix}  删除位于 var 结尾的 suffix 最大匹配模式
     ${var#prefix}   删除位于 var 开头的 prefix 最小匹配模式
     ${var##prefix}  删除位于 var 开头的 prefix 最大匹配模式

13.2.4 Shell 重定向

需要记住的基本重定向(redirection)运算符(在此[n]表示定义文件描述符的可选参数):

     [n]> file     重定向标准输出(或 n)到 file。
     [n]>> file    重定向标准输出(或 n)到 file。
     [n]< filefile重定向到标准输入(或 n)。
     [n1]>&n2      重定向标准输出(或 n1) 到n2。
     2> file >&2    重定向标准输出和错误输出到 file。
     | command     将标准输出通过管道传递给 command。
     2>&1 | command 将标准输出或错误输出通过管道传递给 command

在这里:

  • stdin: 标准输入 (文件描述符 = 0)

  • stdout: 标准输出 (文件描述符 = 1)

  • stderr: 标准错误 (文件描述符 = 2)

shell 允许你通过使用 exec 内嵌一个任意的文件描述符来打开文件。

     $ echo Hello >foo
     $ exec 3bar  # 打开文件
     $ cat <&3 >&4       # 重定向标准输入到 3,标准输出到 4
     $ exec 3<&- 4>&-    # 关闭文件
     $ cat bar
     Hello

在这里, n<&- 和 n>&- 表示关闭文件描述符 n


13.2.5 Shell 条件表达式

每条命令均可返回一个退出状态,这个状态值可用于条件表达式:

  • 成功:0 (True)

  • 错误:1–255 (False)

注意该用法,返回值0用来表示“true”与计算机其它领域中常见的转换是不同的。另外`['等阶于使用test命令进行参数赋值`]'相当于一个条件表达式。

需要记住的常用基本条件表达式

     command && if_success_run_this_command_too || true
     command || if_not_success_run_this_command_instead
     
     if [ conditional_expression ]; then  
      if_success_run_this_command
     else
      if_not_success_run_this_command
     fi

当 shell 使用 -e 调用的时候, 需要使用 || true 来确保这个 shell 不会在本行意外退出。

在条件表达式中使用的文件比较运算符有:

     -e file         file 存在则返回True。
     -d file         file 存在且是一个目录则返回 True。
     -f file         如果 file 存在且是一个普通文件则返回 True。
     -w file         如果 file 存在且可写则返回 True。
     -x file         如果 file 存在且可执行则返回 True。
     file1 -nt file2 如果 file1file2 新则返回 True。(指修改日期)
     file1 -ot file2 如果 file1file2 旧则返回 True。(指修改日期)
     file1 -ef file2 如果两者是相同的设备和具有相同的结点(inode)数则返回 True。

条件表达式中使用的字符串比较运算符有:

          -z str    如果 str 长度为零则返回 True。
          -n str    如果 str 长度为非零则返回 True。
     str1 == str2   如果字符串相等则返回 True。
     str1 =  str2   如果字符串相等则返回 True。
         (使用"=="代替"="符合严格意义上的 POSIX 兼容) 
     str1 != str2   如果字符串不相等则返回 True。
     str1 <  str2   如果 str1 排在 str2 之前则返回 True(与当前位置有关)。
     str1 >  str2   如果 str1 排在 str2 之后则返回 True(与当前位置有关)。

条件表达式中的算术整数比较运算符有-eq-ne-lt-le-gt-ge


13.2.6 命令行处理

shell按如下的方式处理脚本:

  • 用这些元字符将其分割成 tokens:SPACE, TAB, NEWLINE, ;, (, ), <, >, |, &

  • 如果不在"..."或'...'内就检查 keyword(循环检查)

  • 如果不在"..."或'...'内就扩展 alias(循环检查)

  • 如果不在"..."或'...'内就扩展 bracea{1,2} -> a1 a2

  • 如果不在"..."或'...'内就扩展 tilde, ~user -> user's home directory

  • 如果不在'...'内就扩展 parameter, $PARAMETER

  • 如果不在'...'内就扩展 command substitution, $(command)

  • 如果不在"..."或'...'内就用 $IFS 分割成 words

  • 如果不在"..."或'...'内就扩展 pathname *?[]

  • 查找 command

    • function

    • built-in

    • file in $PATH

  • 循环

在双单号内单引号将失效。

在 shell 里执行 set -x 或者使用 -x 选项调用 shell, 该 shell 将会显示出所有执行的命令。 这对调试非常有用。


13.6 Make

Make 参考资源:

  • info make

  • make(1)

  • Managing Projects with make, 2nd edition (O'Reilly)

简单自动变量:

语法规则:

     target: [ prerequisites ... ]
      [TAB]  command1
      [TAB]  -command2 # ignore errors
      [TAB]  @command3 # suppress echoing

在此[TAB]代表一个 TAB 符。 在完成 make 变量代换后,shell 将逐行进行解释。在行尾使用 \ 可以续行。使用 $$ 可将 $ 加入到 shell 脚本的环境变量中。

适用于 target 和 prerequisites 的隐含的等价规则:

     %: %.c header.h

or,

     %.o: %.c header.h

在此,target 包含了 % 字符(确切地说是其中之一),% 可匹配实际的 target 文件名中任何非空子串。prerequisites 同样也使用 % 来显示它们的名字是如何关联到实际的 target 文件名的。

用 Suffix rules 方法来定义 make 的隐含规则(implicit rules)已经过时。GNU make 因为兼容性的考虑仍支持它,但只要有可能就应该使用与之等价的模版规则(pattern rules):

     old suffix rule --> new pattern rule
     .c:             --> %  : %.c
     .c.o:           --> %.o: %.c

上述规则所使用的自动变量:

     foo.o: new1.c new2.c old1.c new3.c
     $@ == foo.o                         (target)
     $< == new1.c                        (first one)
     $? == new1.c new2.c new3.c          (newer ones)
     $^ == new1.c new2.c old1.c new3.c   (all)
     $* == `%' matched stem in the target pattern.

变量参考:

     foo1 := bar    # One-time expansion
     foo2  = bar    # Recursive expansion
     foo3 += bar    # Append
     SRCS := $(wildcard *.c)
     OBJS := $(foo:c=o)
     OBJS := $(foo:%.c=%.o) 
     OBJS := $(patsubst %.c,%.o,$(foo)) 
     DIRS  = $(dir directory/filename.ext) # Extracts "directory"
      $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...

执行make -p -f/dev/null可查看内部自动规则。


13.7.2 调试


13.7.2.1 使用 gdb 进行调试

准备工作:

     # apt-get install gdb

gdb参考资源:

  • info gdb (tutorial)

  • gdb(1)

使用 -g 选项编译程序就可使用 gdb 进行调试。许多命令都可以缩写。Tab 扩展功能和在 shell 中的一样。

     $ gdb program
     (gdb) b 1                # 在line 1 设置断点
     (gdb) run arg1 arg2 arg3 # 运行程序
     (gdb) next               # 下一行
     ...
     (gdb) step               # 前进一步
     ...
     (gdb) p parm             # 打印 parm  
     ...
     (gdb) p parm=12          # 设置其值为 12

在 Emacs 环境下调试程序,参阅。

Debian 系统上所有默认安装的二进制文件都已经进行了 strip 操作, 调试符号已经被移除。 为了能够让 gdb 对 Debian 软件包进行调试, 相关的软件包需要使用下面的方法重新打包:

  • 编辑 debian/control 来改变软件包的 

  • 检查打包脚本,确保使用 CFLAGS=-g-Wall 来编译二进制文件。

  • 设置 DEB_BUILD_OPTIONS=nostrip,noopt 来建立 Debian 包。

更多信息请参阅: 


13.7.2.2 检查库函数关联关系

使用ldd可查看程序与库函数的关联关系:

     $ ldd /bin/ls
             librt.so.1 => /lib/librt.so.1 (0x4001e000)
             libc.so.6 => /lib/libc.so.6 (0x40030000)
             libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
             /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

可在 chrooted 环境下使用 ls 检查上述库函数在你的 chroot 环境中是否可见。

下面的命令也很有用:

  • strace: 跟踪系统调用和消息

  • ltrace: 跟踪库函数调用

阅读(762) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~