`
天梯梦
  • 浏览: 13635166 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

Linux Shell高级技巧(五)

 
阅读更多

二十五、通过FTP下载指定的文件:

      相比于手工调用FTP命令下载文件,该脚本提供了更为方便的操作方式。
      /> cat > test25.sh
      #!/bin/sh
      #1. 测试脚本参数数量的有效性。    
      if [ $# -ne 2 ]; then
          echo "Usage: $0 ftp://... username" >&2
          exit 1
      fi
      #2. 获取第一个参数的前六个字符,如果不是"ftp://",则视为非法FTP URL格式。这里cut的-c选项表示按照字符的方式截取第一到第六个字符。
      header=`echo $1 | cut -c1-6`
      if [ "$header" != "ftp://" ]; then
          echo "$0: Invalid ftp URL." >&2
          exit 1
      fi
      #3. 合法ftp URL的例子:ftp://ftp.myserver.com/download/test.tar
      #4. 针对上面的URL示例,cut命令通过/字符作为分隔符,这样第三个域字段表示server(ftp.myserver.com)。
      #5. 在截取filename时,cut命令也是通过/字符作为分隔符,但是"-f4-"将获取从第四个字段开始的后面所有字段(download/test.tar)。
      #6. 通过basename命令获取filename的文件名部分。
      server=`echo $1 | cut -d/ -f3`
      filename=`echo $1 | cut -d/ -f4-`
      basefile=`basename $filename`
      ftpuser=$2
      #7. 这里需要调用stty -echo,以便后面的密码输入不会显示,在输入密码之后,需要再重新打开该选项,以保证后面的输入可以恢复显示。
      #8. echo "",是模拟一次换换。
      echo -n "Password for $ftpuser: "
      stty -echo
      read password
      stty echo
      echo ""
      #9. 通过HERE文档,批量执行ftp命令。
      echo ${0}: Downloading $baseile from server $server.
      ftp -n << EOF
      open $server
      user $ftpuser $password
      get $filename $basefile
      quit
      EOF
      #10.Shell内置变量$?表示上一个Shell进程的退出值,0表示成功执行,其余值均表示不同原因的失败。
      if [ $? -eq 0 ]; then
          ls -l $basefile
      fi
      exit 0
      CTRL+D
      /> ./test25.sh  ftp://ftp.myserver.com/download/test.tar stephen
      Password for stephen:
      ./test25.sh: Downloading from server ftp.myserver.com.
      -rwxr-xr-x. 1 root root 678 Dec  9 11:46 test.tar

二十六、文件锁定:

      在工业应用中,有些来自于工业设备的文件将会被放到指定的目录下,由于这些文件需要再被重新格式化后才能被更高层的软件进行处理。而此时负责处理的脚本程 序极有可能是多个实例同时运行,因此这些实例之间就需要一定的同步,以避免多个实例同时操作一个文件而造成的数据不匹配等问题的发生。文件锁定命令可以帮 助我们实现这一同步逻辑。
      /> cat > test26.sh
      #!/bin/sh
      #1. 这里需要先确认flock命令是否存在。
      if [ -z $(which flock) ]; then
          echo "flock doesn't exist."
          exit 1
      fi
      #2. flock中的-e选项表示对该文件加排它锁,-w选项表示如果此时文件正在被加锁,当前的flock命令将等待20秒,如果能锁住该文件,就继续执行,否则退出该命令。
      #3. 这里锁定的文件是/var/lock/lockfile1,-c选项表示,如果成功锁定,则指定其后用双引号括起的命令,如果是多个命令,可以用分号分隔。
      #4. 可以在两个终端同时启动该脚本,然后观察脚本的输出,以及lockfile1文件的内容。
      flock -e -w 20 /var/lock/lockfile1 -c "sleep 10;echo `date` | cat >> /var/lock/lockfile1"
      if [ $? -ne 0 ]; then
          echo "Fail."
          exit 1
      else
          echo "Success."
          exit 0
      fi
      CTRL+D
   
二十七、用小文件覆盖整个磁盘:

      假设我们现在遇到这样一个问题,公司的关键资料copy到测试服务器上了,在直接将其删除后,仍然担心服务器供应商可以将其恢复,即便是通过fdisk进 行重新格式化,也仍然存在被恢复的风险,鉴于此,我们需要编写一个脚本,创建很多小文件(5MB左右),之后不停在关键资料所在的磁盘中复制该文件,以使 Linux的inode无法再被重新恢复,为了达到这里效果,我们需要先构造该文件,如:
      /> find . -name "*" > testfile
      /> ls -l testfile
      -rwxr-xr-x. 1 root root 5123678 Dec  9 11:46 testfile
      /> cat > test27.sh
      #!/bin/sh
      #1. 初始化计数器变量,其中max的值是根据当前需要填充的磁盘空间和testfile的大小计算出来的。
      counter=0
      max=2000000
      remainder=0
      #2. 每次迭代counter变量都自增一,以保证每次生成不同的文件。当该值大于最大值时退出。
      #3. 对计数器变量counter按1000取模,这样可以在每生成1000个文件时打印一次输出,以便看到覆盖的进度,输出时间则便于预估还需要多少时间可以完成。
      #4. 创建单独的、用于存放这些覆盖文件的目录。
      #5. 生成临时文件,如果写入失败打印出提示信息。
      while true
      do
          ((counter=counter+1))
          if [ #counter -ge $max ]; then
              break
          fi
          ((remainder=counter%1000))
          if [ $remainder -eq 0 ]; then
              echo -e "counter = $counter\t date = " $(date)
          fi
          mkdir -p /home/temp2
          cat < testfile > "/home/temp/myfiles.$counter"
          if [[ $? -ne 0 ]]; then
              echo "Failed to wrtie file."
              exit 1
          fi
      done
      echo "Done"
      CTRL+D
      /> ./test27.sh
      counter = 1000        Fri Dec  9 17:25:04 CST 2011
      counter = 2000        Fri Dec  9 17:25:24 CST 2011
      counter = 3000        Fri Dec  9 17:25:54 CST 2011
      ... ...
      与此同时,可以通过执行下面的命令监控磁盘空间的使用率。
      /> watch -n 2 'df -h'
      Every 2.0s: df -h                                       Fri Dec  9 17:31:56 2011
    
      Filesystem            Size   Used Avail Use% Mounted on
      /dev/sda2             3.9G  2.3G  1.4G  63% /
      tmpfs                  504M  100K  504M   1% /dev/shm
      /dev/sda1              49M   36M   11M  77% /boot
      /dev/sda3              15G  172M   14G   2% /home
      我们也可以在执行的过程中通过pidstat命令监控脚本进程的每秒读写块数。    
 
二十八、统计当前系统中不同运行状态的进程数量:

      在Linux系统中,进程的运行状态主要分为四种:运行时、睡眠、停止和僵尸。下面的脚本将统计当前系统中,各种运行状态的进程数量。
      /> cat > test28.sh
      #!/bin/sh
      #1. 初始化计数器变量,分别对应于运行时、睡眠、停止和僵尸。
      running=0
      sleeping=0
      stopped=0
      zombie=0
      #2. 在/proc目录下,包含很多以数字作为目录名的子目录,其含义为,每个数字对应于一个当前正在运行进程的pid,该子目录下包含一些文件用于描述与该 pid进程相关的信息。如1表示init进程的pid。那么其子目录下的stat文件将包含和该进程运行状态相关的信息。
      #3. cat /proc/1/stat,通过该方式可以查看init进程的运行状态,同时也可以了解该文件的格式,其中第三个字段为进程的运行状态字段。
      #4. 通过let表达式累加各个计数器。
      for pid in /proc/[1-9]*
      do
          ((procs=procs+1))
          stat=`awk '{print $3}' $pid/stat`
          case $stat in
              R) ((running=runing+1));;
              S) ((sleeping=sleeping+1));;
              T) ((stopped=stopped+1));;
              Z) ((zombie=zombie+1));
          esac
      done
      echo -n "Process Count: "
      echo -e "Running = $running\tSleeping = $sleeping\tStopped = $stopped\tZombie = $zombie."
      CTRL+D
      /> ./test28.sh
      Process Count: Running = 0      Sleeping = 136  Stopped = 0     Zombie = 0.
   
二十九、浮点数验证:

     浮点数数的重要特征就是只是包含数字0到9、负号(-)和点(.),其中负号只能出现在最前面,点(.)只能出现一次。
      /> cat > test29.sh
      #!/bin/sh
      #1. 之前的一个条目已经介绍了awk中match函数的功能,如果匹配返回匹配的位置值,否则返回0。
      #2. 对于Shell中的函数而言,返回0表示成功,其他值表示失败,该语义等同于Linux中的进程退出值。调用者可以通过内置变量$?获取返回值,或者作为条件表达式的一部分直接判断。
      validint() {
          ret=`echo $1 | awk '{start = match($1,/^-?[0-9]+$/); if (start == 0) print "1"; else print "0"}'`
          return $ret
      }
    
      validfloat() {
          fvalue="$1"
          #3. 判断当前参数中是否包含小数点儿。如果包含则需要将其拆分为整数部分和小数部分,分别进行判断。
          if [ ! -z  $(echo $fvalue | sed 's/[^.]//g') ]; then
              decimalpart=`echo $fvalue | cut -d. -f1`
              fractionalpart=`echo $fvalue | cut -d. -f2`
              #4. 如果整数部分不为空,但是不是合法的整型,则视为非法格式。
              if [ ! -z $decimalpart ]; then
                  if ! validint "$decimalpart" ; then
                      echo "decimalpart is not valid integer."
                      return 1
                  fi
              fi
              #5. 判断小数部分的第一个字符是否为-,如果是则非法。
              if [ "${fractionalpart:0:1}" = "-" ]; then
                  echo "Invalid floating-point number: '-' not allowed after decimal point." >&2
                  return 1
              fi
              #6. 如果小数部分不为空,同时也不是合法的整型,则视为非法格式。
              if [ "$fractionalpart" != "" ]; then
                  if ! validint "$fractionalpart" ; then
                      echo "fractionalpart is not valid integer."
                      return 1
                  fi
              fi
              #7. 如果整数部分仅为-,或者为空,如果此时小数部分也是空,则为非法格式。
              if [ "$decimalpart" = "-" -o -z "$decimalpart" ]; then
                  if [ -z $fractionalpart ]; then
                      echo "Invalid floating-point format." >&2
                      return 1
                  fi
              fi
          else
              #8. 如果当前参数仅为-,则视为非法格式。
              if [ "$fvalue" = "-" ]; then
                  echo "Invalid floating-point format." >&2
                  return 1
              fi
              #9. 由于参数中没有小数点,如果该值不是合法的整数,则为非法格式。
              if ! validint "$fvalue" ; then
                  echo "Invalid floating-point format." >&2
                  return 1
              fi
          fi
          return 0
      }   
      if validfloat $1 ; then
          echo "$1 is a valid floating-point value."
      fi
      exit 0
      CTRL+D
      /> ./test29.sh 47895      
      47895 is a valid floating-point value.
      /> ./test29.sh 47895.33
      47895.33 is a valid floating-point value.
      /> ./test29.sh 47895.3e
      fractionalpart is not valid integer.
      /> ./test29.sh 4789t.34
      decimalpart is not valid integer.   


三十、统计英文文章中每个单词出现的频率:
    
      这个技巧的主要目的是显示如何更好的使用awk命令的脚本。
      /> cat > test30.sh
      #!/bin/sh
      #1. 通过当前脚本的pid,生成awk脚本的临时文件名。
      #2. 捕捉信号,在脚本退出时删除该临时文件,以免造成大量的垃圾临时文件。
      awk_script_file="/tmp/scf_tmp.$$"
      trap "rm -f $awk_script_file" EXIT
      #3. while循环将以当前目录下的testfile作为输入并逐行读取,在读取到末尾时退出循环。
      #4. getline读取到每一行将作为awk的正常输入。在内层的for循环中,i要从1开始,因为$0表示整行。NF表示域字段的数量。
      #5. 使$i作为数组的键,如果$i的值匹配正则表达式"^[a-zA-Z]+$",我们将其视为单词而不是标点。每次遇到单词时,其键值都会递增。
      #6. 最后通过awk脚本提供的特殊for循环,遍历数组的键值数据。
      cat << 'EOF' > $awk_script_file
      BEGIN {
          while (getline < "./testfile" > 0) {
              for (i = 1; i <= NF; ++i) {
                  if (match($i,"^[a-zA-Z]+$") != 0)
                      arr[$i]++
              }
          }
          for (word in arr) {
              printf "word = %s\t count = %s\n",word,arr[word]
          }
      }
      EOF
      awk -f $awk_script_file
      CTRL+D
      /> cat testfile
      hello world liu liu , ,
      stephen liu , ?
      /> ./test30.sh
      word = hello      count = 1
      word = world     count = 1
      word = stephen count = 1
      word = liu         count = 3

 

原文:Linux Shell高级技巧(五)

分享到:
评论

相关推荐

    Linux Shell高级技巧实战总结

    Linux Shell高级技巧实战总结 一、将输入信息转换为大写字符后再进行条件判断 二、为调试信息设置输出级别 三、判断参数是否为数字 四、判断整数变量的奇偶性 五、将Shell命令赋值给指定变量,以保证脚本的移植性 六...

    高级shell编程 第五部分 高级shell编程技巧(共5部分)

    第五部分 高级shell编程技巧 第25章 深入讨论 第26章 shell 工 具 第27章 几个脚本例子 第28章 运行级别脚本 第29章 cgi 脚 本 附录 常用shell命令

    Linux Shell编程3/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    LINUX与UNIX SHELL编程指南

    网上此书的目录很乱,而且一本书分割为好多文件。我详细整理了目录,并且合并为...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

    Shell高级编程(中文版)

    Shell高级编程(中文版) 毫无疑问,UNIX/Linux 最重要的软件之一就是 shell,目前最流行的 shell 被称为 Bash(Bourne Again Shell), 几乎所有的 Linux 和绝大部分的 UNIX 都可以使用 Bash。作为系统与用户之间的交互...

    实战Linux Shell编程与服务器管理-作者:卧龙小三(1)

    要达到这个境界,管理者必须具备相当程度的Shell操控能力与Shell程序设计能力,卧龙小三拥有丰富的主机管理实务经验,以及多年的教学经验,相信这本《实战Linux Shell编程与服务器管理》必能引领读者轻松跨越Bash ...

    绝版经典 LINUX与UNIX SHELL编程指南 PDF 高清版 [16.3M]

    shell是一种完整的编程语言,易学易用;shell脚本可以使烦人的手工作业自动...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

    Linux Shell编程1/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    Linux Shell编程2/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    Linux shell编程指南.rar

    本文档是Linux shell编程指南教程,适于Linux编程新手,高清pdf。共分为5部分,第一部分:shell,第二部分:分文本过滤,第三部分:登陆环境,第四部分:shell编程,第五部分:高级shell编程技巧。

    Linux Shell 编程 入门、提高、精通

    第一部分 shell 第1章文件安全与权限 第2章使用find和xargs ...第五部分高级shell编程技巧 第25章深入讨论 第26章shell 工具 第27章几个脚本例子 第28章运行级别脚本 第29章cgi 脚本 附录常用shell命令

    Linux与unix+shell编程指南.pdf

    非常基础的shell编程文档主要分了五个部分 1.shell 2.文本过滤 3.登录环境 4.基础shell编程 5.高级shell编程技巧

    LINUX与UNIX SHELL编程指南(很全)

    第一部分 shell 第1章 文件安全与权限 1 1.1 文件 1 1.2 文件类型 2 1.3 权限 2 1.4 改变权限位 4 1.4.1 符号模式 4 1.4.2 chmod命令举例 5 1.4.3 绝对模式 5 1.4.4 chmod命令的其他例子 6 1.4.5 可以选择使用符号...

    Linux shell编程指南

    本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。 目 录 译者序 前言 第一部分 ...

    Linux与UNIX Shell编程指南.rar

    内容简介 本书共分五部分 ,详细介绍了SHELL编程技巧,各种UNIX命令及语法,还...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

    Linux命令学习 shell pdf格式

    第一部分 shell ...第五部分 高级shell编程技巧 第二十五章 深入讨论 第二十六章 shell工具 第二十七章 几个脚本例子 第二十八章 运行级别脚本 附录 常用shell命令 另外附有Linux命令说明(doc版,32页)

    Shell初级和高级技巧

    Shell初级和高级技巧,在某大牛的的博客看到,然后自己整理归档,有需要的可以下载来看看(内附有博客地址)

    linux shell 编程教程

    linux shell编程 教程大全 目 录 译者序 前言 第一部分 shell 第1章 文件安全与权限 1 1.1 文件 1 1.2 文件类型 2 1.3 权限 2 1.4 改变权限位 4 1.4.1 符号模式 4 1.4.2 chmod命令举例 5 1.4.3 绝对模式 5 1.4.4 ...

    Linux与unix shell编程指南

    本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。 目 录 译者序 前言 第一部分 shell ...

Global site tag (gtag.js) - Google Analytics