当前位置: 首页 > 工具软件 > bash-guide > 使用案例 >

《Advanced Bash-Scripting Guide》学习手记(一)(转载)

芮琛
2023-12-01
导读:
  Version 3.7.5
  第2章带着一个Sha-Bang出发(Sha-Bang指的是#!)
  ==============================================
  在一个最简单的例子中,一个shell脚本其实就是一堆系统命令列在一个文件中.它的最基本的
  用处就是,在你每次输入这些特定顺序的命令时可以少敲一些字.
  Example 2-1 清除:清除/var/log下的log文件
  ################################Start Script#######################################
  1 # Cleanup
  2 # 当然要使用root身份来运行这个脚本
  3
  4 cd /var/log
  5 cat /dev/null >messages
  6 cat /dev/null >wtmp
  7 echo "Logs cleaned up."
  ################################End Script#########################################
  这根本就没什么稀奇的,这只不过是命令的堆积,来让从console或者xterm中一个一个的输入命
  令更方便一些.好处就是把命令放在一个脚本中,不用每次都敲它们.这样的话,对于特定的应用
  这个脚本就很容易被修改或定制.
  ******************************传说中的分割线**************************************
  注:在linux终端下,提示符“$”表示普通用户,而符号“#”表示超级用户也就是root。
  另:shell脚本中,“#”是注释符,相当于C语言中的“//”
  参阅文档如下:
  $man cat
  CAT(1) User Commands CAT(1)
  NAME
  cat - concatenate files and print on the standard output
  SYNOPSIS
  cat [OPTION] [FILE]...
  DESCRIPTION
  Concatenate FILE(s), or standard input, to standard output.
  -A, --show-all
  equivalent to -vET
  -b, --number-nonblank
  number nonblank output lines
  -e equivalent to -vE
  -E, --show-ends
  display $ at end of each line
  -n, --number
  number all output lines
  -r, --reversible
  use / to make the output reversible, implies -v
  -s, --squeeze-blank
  never more than one single blank line
  -t equivalent to -vT
  -T, --show-tabs
  display TAB characters as ^I
  -u (ignored)
  -v, --show-nonprinting
  use ^ and M- notation, except for LFD and TAB
  --help display this help and exit
  --version
  output version information and exit
  With no FILE, or when FILE is -, read standard input.
  AUTHOR
  Written by Torbjorn Granlund and Richard M. Stallman.
  REPORTING BUGS
  Report bugs to .
  COPYRIGHT
  Copyright (C) 2004 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions. There is
  NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.
  SEE ALSO
  The full documentation for cat is maintained as a Texinfo manual. If
  the info and cat programs are properly installed at your site, the com-
  mand
  info coreutils cat
  should give you access to the complete manual.
  cat (coreutils) 5.2.1 July 2004 CAT(1)
  $man echo
  ECHO(1) User Commands ECHO(1)
  NAME
  echo - display a line of text
  SYNOPSIS
  echo [OPTION]... [STRING]...
  DESCRIPTION
  NOTE: your shell may have its own version of echo which will supercede
  the version described here. Please refer to your shell's documentation
  for details about the options it supports.
  Echo the STRING(s) to standard output.
  -n do not output the trailing newline
  -e enable interpretation of the backslash-escaped characters listed
  below
  --help display this help and exit
  --version
  output version information and exit
  With -e, the following sequences are recognized and interpolated:
  /NNN the character whose ASCII code is NNN (octal)
  / backslash
  /a alert (BEL)
  /b backspace
  /c suppress trailing newline
  /f form feed
  /n new line
  /r carriage return
  /t horizontal tab
  /v vertical tab
  AUTHOR
  Written by FIXME unknown.
  REPORTING BUGS
  Report bugs to .
  COPYRIGHT
  Copyright (C) 2004 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions. There is
  NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.
  SEE ALSO
  The full documentation for echo is maintained as a Texinfo manual. If
  the info and echo programs are properly installed at your site, the
  command
  info coreutils echo
  should give you access to the complete manual.
  echo 5.2.1 July 2004 ECHO(1)
  在linux中,执行一个Shell命令行时通常会自动打开3个标准文档,即标准输入文档(stdin,指standard input),通常对应终端的键盘;标准输出文档(stdout,指standard output)和标准错误输出文档(stderr)都对应终端的屏幕。进程将从标准输入文档中得到输入资料,将正常输出资料输出到标准输出文档,而将错误信息送到标准错误文档中。
  cat命令的功能是从命令行给出的文件中读取资料,并将这些资料直接送到标准输出
  假如文档test.txt的内容为abcdefghijklmnopqrstuvwxyz,则
  $cat test.txt
  abcdefghijklmnopqrstuvwxyz
  以上指令将文档test.txt的内容显示在终端上。但是,如果cat的命令行中没有参数,它就会从标准输入中读取资料,并将其送到标准输出。
  $cat
  hello world
  hello world
  bye
  bye
  以上指令使你输入的每一行都立刻被cat命令输出到屏幕上。
  注:当某些Linux指令的执行进入交互界面时,ctrl+c可以取消,ctrl+d表示完成
  在示例脚本中,所谓的清除动作,就是将messages和wtmp文件用一个空文件覆盖。这里又涉及到输入输出重定向操作符的运用。
  符号“<”表示输入重定向,而符号“>”表示输出重定向。
  输入重定向是指把命令或可执行程序的标准输入重定向到指定的文件中。也就是说,输入可以不来自键盘,而来自一个指定的文件。所以说,输入重定向主要用于改变一个命令的输入源,特别是改变那些需要大量输入的输入源。
  例如以上指令cat test.txt等同于cat
  作为扩展,输入重定向操作符“<<”表示当前命令的标准输入来自命令行,操作符”<<“后跟一对分隔符(分隔符是自定义的,可以是任意字符或者单词。下例以单词end来作为分割符)。
  $ sort <
  >abc
  >xyz
  >uvw
  >opq
  >end
  abc
  opq
  uvw
  xyz
  sort排序命令接受的输入到出现分割符“end”为止,所以排序的结果并不包含“end”这个单词。(因为它是操作符“<<”后定义的分割符。)
  输出重定向是指把命令(或可执行程序)的标准输出或标准错误输出重新定向到指定文档中。这样,该命令的输出就不显示在屏幕上,而是写入到指定文档中。
  例如debian下的apt-spy软件,可以用来测试筛选最快的deb源并生成sources.list文件,在它下载了镜像站点列表后,我们开始寻找亚洲地区有stable版本的最快的镜像站点。
  $apt-spy -d stable -a Asia
  .......
  这是个漫长的过程,所有的测试结果(含有镜像站点的网速)直接输出在终端上,而最终生成的sources.list文件中只有最快的一个镜像源。几十分钟的等待只获得了一个镜像源实在无法令人满意,我想保留所有站点的测试结果留待以后参考,这时就可以使用输出重定向操作符“>”
  $apt-spy -d stable -a Asia >mirrors.txt
  所有的标准输出将不再显示在终端上(标准错误输出依然显示在终端上),而是直接写入mirrors.txt文件中,方便日后参考。
  注意的是,操作符“>”的输出是覆盖性的输出,当mirrors.txt文件已经存在时,该输出必然会覆盖mirrors.txt的内容(哪怕是空的输出,也会产生一个空的mirrors.txt文件)。为了保有原先的mirrors.txt文件,我们可以使用追加性的输出,也即操作符“>>”。
  $apt-spy -d stable -a Asia >>mirrors.txt
  附:操作符"&”可以将某个指令操作放入后台,而不至于占用终端界面,但是标准输出和错误输出依然会不时显示出来。如下例:
  $apt-spy -d stable -a Asia >>mirrors.txt &
  ******************************传说中的分割线**************************************
  Example 2-2 清除:一个改良的清除脚本
  ################################Start Script#######################################
  1 #!/bin/bash
  2 # 对于一个Bash脚本的合适的头.
  3
  4 # Cleanup, 版本 2
  5
  6 # 当然要使用root身份来运行.
  7 # 在此处插入代码,来打印错误消息,并且在不是root的时候退出.
  8
  9 LOG_DIR=/var/log
  10 # 如果使用变量,当然比把代码写死的好.
  11 cd $LOG_DIR
  12
  13 cat /dev/null >messages
  14 cat /dev/null >wtmp
  15
  16
  17 echo "Logs cleaned up."
  18
  19 exit # 这个命令是一种正确并且合适的退出脚本的方法.
  ################################End Script#########################################
  ******************************传说中的分割线**************************************
  LOG_DIR因为大写了,初看像是C语言中的宏,实际上它是变量,shell脚本没有C语言那么严格的语法,变量赋值时直接就是var=,引用变量时为$var,有时侯变量名容易与其他文字混淆,比如
  num=2
  echo "this is the $numnd"
  这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:
  num=2
  echo "this is the ${num}nd"
  还有很多变量是环境变量,并不需要赋值,直接引用即可,如以下
  CDPATH 用于cd命令的查找路径
  HOME /etc/passwd文件中列出的用户目录
  MAIL /var/mail/$UERNAME mail等程序使用
  PATH
  PS1,PS2 默认提示符($)及换行提示符(>)
  shell脚本只是一系列的shell命令集合,因此,某些用户自设的环境变量也可直接在脚本中引用(当然,这违背了程序的可移置性。)BASH是shell的一种,BASH脚本也是shell脚本。
  ******************************传说中的分割线**************************************
  现在,然我们看一下一个真正意义的脚本.而且我们可以走得更远...
  Example 2-3. cleanup:一个增强的和广义的删除logfile的脚本
  ################################Start Script#######################################
  1 #!/bin/bash
  2 # 清除, 版本 3
  3
  4 # Warning:
  5 # -------
  6 # 这个脚本有好多特征,是在后边章节进行解释的,大概进行到本书的一半的时候,
  7 #
  8 # 你就会觉得它没有什么神秘的了.
  9 #
  10
  11
  12
  13 LOG_DIR=/var/log
  14 ROOT_UID=0 # $UID为0的时候,用户才具有根用户的权限
  15 LINES=50 # 默认的保存行数
  16 E_XCD=66 # 不能修改目录?
  17 E_NOTROOT=67 # 非根用户将以error退出
  18
  19
  20 # 当然要使用根用户来运行
  21 if [ "$UID" -ne "$ROOT_UID" ]
  22 then
  23 echo "Must be root to run this script."
  24 exit $E_NOTROOT
  25 fi
  26
  27 if [ -n ""]
  28 # 测试是否有命令行参数(非空).
  29 then
  30 lines=
  31 else
  32 lines=$LINES # 默认,如果不在命令行中指定
  33 fi
  34
  35
  36 # Stephane Chazelas 建议使用下边
  37 #+ 的更好方法来检测命令行参数.
  38 #+ 但对于这章来说还是有点超前
  39 #
  40 # E_WRONGARGS=65 # 非数值参数(错误的参数格式)
  41 #
  42 # case ""in
  43 # "") lines=50;;
  44 # *[!0-9]*) echo "Usage: `basename {fckeditor}` file-to-cleanup"; exit $E_WRONGARGS;;
  45 # * ) lines=;;
  46 # esac
  47 #
  48 #* 直到"Loops"的章节才会对上边的内容进行详细的描述.
  49
  50
  51 cd $LOG_DIR
  52
  53 if [ `pwd` != "$LOG_DIR" ] # 或者if[ "$PWD" != "$LOG_DIR" ]
  54 # 不在 /var/log中?
  55 then
  56 echo "Can't change to $LOG_DIR."
  57 exit $E_XCD
  58 fi # 在处理log file之前,再确认一遍是否在正确的目录.
  59
  60 # 更有效率的做法是
  61 #
  62 # cd /var/log || {
  63 # echo "Cannot change to necessary directory." >&2
  64 # exit $E_XCD;
  65 # }
  66
  67
  68
  69
  70 tail -$lines messages >mesg.temp # 保存log file消息的最后部分
  71 mv mesg.temp messages # 变为新的log目录
  72
  73
  74 # cat /dev/null >messages
  75 #* 不再需要了,使用上边的方法更安全.
  76
  77 cat /dev/null >wtmp # ': >wtmp' 和 '> wtmp'具有相同的作用
  78 echo "Logs cleaned up."
  79
  80 exit 0
  81 # 退出之前返回0,返回0为成功.
  82 #
  ################################End Script#########################################
  ******************************传说中的分割线*************************************
  表达式相应说明
  整数测试
  int1 -eq int2 相等?
  int1 -ne int2 不等?
  int1 -gt int2 int1 >int2 ?
  int1 -ge int2 int1 >= int2 ?
  int1 -lt int2 int1
  int1 -le int2 int1 <= int2 ?
  字符测试
  str1 = str2 二者相长,相同
  str1 != str2 不同
  -n string string不为空(长度不为零)
  -z string string为空
  string string不为空
  文件测试
  -r filename 用户对文件filename有读权限?
  -w filename 用户对文件filename有写权限?
  -x filename 用户对文件filename有可执行权限?
  -f filename 文件filename为普通文件?
  -d filename 文件filename为目录?
  -c filename 文件filename为字符设备文件?
  -b filename 文件filename为块设备文件?
  -s filename 文件filename大小不为零?
  -t fnumb 与文件描述符fnumb(默认值为1)相关的设备是一个终端设备?
  逻辑运算
  -a AND
  -o OR
  if-then语句,格式如下:
  if
  command_1
  then
  command_2
  command_3
  fi
  command_4
  command_1执行成功才能执行command_2,command_3,而command_4总是执行。
  if-then-else语句
  if
  command_1
  then
  command_2
  else
  command_3
  fi
  command_4
  command_1执行成功才能执行command_2,否则执行command_3,而command_4总是执行。
  ******************************传说中的分割线**************************************
  因为你可能希望将系统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
  

本文转自
http://lylone.yculblog.com/post.1096222.html
 类似资料: