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

Linux Shell高级技巧(四)

 
阅读更多

十九、将文件的输出格式化为指定的宽度:

      在这个技巧中,不仅包含了如何获取和文件相关的详细信息,如行数,字符等,而且还可以让文件按照指定的宽度输出。这种应用在输出帮助信息、License相关信息时还是比较有用的。
      /> cat > test19.sh
      #!/bin/sh
      #1. 这里我们将缺省宽度设置为75,如果超过该宽度,将考虑折行显示,否则直接在一行中全部打印输出。这里只是为了演示方便,事实上,你完全可以将该值作为脚本或函数的参数传入,那样你将会得到更高的灵活性。    
      my_width=75
      #2. for循环的读取列表来自于脚本的参数。
      #3. 在获取lines和chars变量时,sed命令用于过滤掉多余的空格字符。
      #4. 在if的条件判断中${#line}用于获取line变量的字符长度,这是Shell内置的规则。
      #5. fmt -w 80命令会将echo输出的整行数据根据其命令选项指定的宽度(80个字符)进行折行显示,再将折行后的数据以多行的形式传递给sed命令。
      #6. sed在收到fmt命令的格式化输出后,将会在折行后的第一行头部添加两个空格,在其余行的头部添加一个加号和一个空格以表示差别。
      for input; do
          lines=`wc -l < $input | sed 's/ //g'`
          chars=`wc -c < $input | sed 's/ //g'`
          owner=`ls -l $input | awk '{print $3}'`
          echo "-------------------------------------------------------------------------------"
          echo "File $input ($lines lines, $chars characters, owned by $owner):"
          echo "-------------------------------------------------------------------------------"
          while read line; do
              if [ ${#line} -gt $my_width ]; then
                  echo "$line" | fmt -w 80 | sed -e '1s/^/  /' -e '2,$s/^/+ /'
              else
                  echo "  $line"
              fi
          done < $input
          echo "-------------------------------------------------------------------------------"
      done | more
      CTRL+D
      /> ./test19.sh testfile
      -------------------------------------------------------------------------------
      File testfile.dat (3 lines, 645 characters, owned by root):
      -------------------------------------------------------------------------------
         The PostgreSQL Global Development Group today released updates for all
      + active branches of the PostgreSQL object-relational database system,
      + including versions 9.1.2, 9.0.6, 8.4.10, 8.3.17 and 8.2.23. Users of any of
      + the several affected features in this release, including binary replication,
      + should update their PostgreSQL installations as soon as possible.
         This is also the last update for PostgreSQL 8.2, which is now End-Of-Life
      + (EOL). Users of version 8.2 should plan to upgrade their PostgreSQL
      + installations to 8.3 or later within the next couple of months. For more
      + information, see our Release Support Policy.
         This is just a test file.
      -------------------------------------------------------------------------------
       
二十、监控指定目录下磁盘使用空间过大的用户:

      在将Linux用作文件服务器时,所有的注册用户都可以在自己的主目录下存放各种类型和大小的文件。有的时候,有些用户的占用空间可能会明显超过其他人,这时就需要管理员可以及时发现这一异常使用状况,并根据实际情况作出应对处理。
      /> cat > test20.sh
      #!/bin/sh
      #1. 该脚本仅用于演示一种处理技巧,其中很多阈值都是可以通过脚本参来初始化的,如limited_qutoa和dirs等变量。
      limited_quota=200
      dirs="/home /usr /var"
      #2. 以冒号作为分隔符,截取passwd文件的第一和第三字段,然后将输出传递给awk命令。
      #3. awk中的$2表示的是uid,其中1-99是系统保留用户,>=100的uid才是我们自己创建的用户,awk通过print输出所有的用户名给for循环。
      #4. 注意echo命令的输出是由八个单词构成,同时由于-n选项,echo命令并不输出换行符。
      #5. 之所以使用find命令,也是为了考虑以点(DOT)开头的隐藏文件。这里的find将在指定目录列表内,搜索指定用户的,类型为普通文件的文件。并通过-ls选项输出找到文件的详细信息。其中输出的详细信息的第七列为文件大小列。
      #6. 通过awk命令累加find输出的第七列,最后再在自己的END块中将sum的值用MB计算并输出。该命令的输出将会与上面echo命令的输出合并作为 for循环的输出传递给后面的awk命令。这里需要指出的是,该awk的输出就是后面awk命令的$9,因为echo仅仅输出的8个单词。
      #7. 从for循环管道获取数据的awk命令,由于awk命令执行的动作是用双引号括起的,所以表示域字段的变量的前缀$符号,需要用\进行转义。变量$limited_quota变量将会自动完成命令替换,从而构成该awk命令的最终动作参数。
      for name in `cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99 {print $1}'`
      do
          echo -n "User $name exceeds disk quota. Disk Usage is: "
          find $dirs -user $name -type f -ls |\
                awk '{ sum += $7 } END { print sum / (1024*1024) " MB" }'
      done | awk "\$9 > $limited_quota { print \$0 }"
      CTRL+D
      /> ./test20.sh    

二十一、编写一个更具可读性的df命令输出脚本:

      这里我们将以awk脚本的方式来实现df -h的功能。
      /> cat > test21.sh
      #!/bin/sh
      #1. $$表示当前Shell进程的pid。    
      #2. trap信号捕捉是为了保证在Shell正常或异常退出时,仍然能够将该脚本创建的临时awk脚本文件删除。
      awk_script_file="/tmp/scf_tmp.$$"
      trap "rm -f $awk_script_file" EXIT
      #3. 首先需要说明的是,'EOF'中的单引号非常重要,如果忽略他将无法通过编译,这是因为awk的命令动作必须要用单引号扩住。
      #4. awk脚本的show函数中,int(mb * 100) / 100这个技巧是为了保证输出时保留小数点后两位。
      cat << 'EOF' > $awk_script_file
      function show(size) {
          mb = size / 1024;
          int_mb = (int(mb * 100)) / 100;
          gb = mb / 1024;
          int_gb = (int(gb * 100)) / 100;
          if (substr(size,1,1) !~ "[0-9]" || substr(size,2,1) !~ "[0-9]") {
              return size;
          } else if (mb < 1) {
              return size "K";
          } else if (gb < 1) {
              return int_mb "M";
          } else {
              return int_gb "G";
          }
      }
      #5. 在BEGIN块中打印重定义的输出头信息。
      BEGIN {
            printf "%-20s %7s %7s %7s %8s %s\n","FileSystem","Size","Used","Avail","Use%","Mounted"
      }
      #6. !/Filesystem/ 表示过滤掉包含Filesystem的行,即df输出的第一行。其余行中,有个域字段可以直接使用df的输出,有的需要通过show函数的计算,以得到更为可读的显示结果。
      !/Filesystem/ {
          size = show($2);
          used = show($3);
          avail = show($4);
          printf "%-20s %7s %7s %7s %8s %s\n",$1,size,used,avail,$5,$6
      }
      EOF
      df -k | awk -f $awk_script_file
      CTRL+D
      /> ./test12.sh
      FileSystem              Size       Used      Avail     Use%   Mounted
      /dev/sda2              3.84G    2.28G     1.36G      63%   /
      tmpfs                 503.57M     100K 503.47M        1%   /dev/shm
      /dev/sda1             48.41M  35.27M  10.63M      77%   /boot
      /dev/sda3              14.8G 171.47M  13.88G        2%   /home
   
二十二、编写一个用于添加新用户的脚本:

      之所以在这里选择这个脚本,没有更多的用意,只是感觉这里的有些技巧和常识还是需要了解的,如/etc/passwd、/etc/shadow、/etc/group的文件格式等。
      /> cat > test22.sh
      #!/bin/sh
      #1. 初始化和用户添加相关的变量。    
      passwd_file="/etc/passwd"
      shadow_file="/etc/shadow"
      group_file="/etc/group"
      home_root_dir="/home"
      #2. 只有root用户可以执行该脚本。    
      if [ "$(whoami)" != "root" ]; then
          echo "Error: You must be roor to run this command." >&2
          exit 1
      fi
    
      echo "Add new user account to $(hostname)"
      echo -n "login: "
      read login
      #3. 去唯一uid,即当前最大uid值加一。
      uid=`awk -F: '{ if (big < $3 && $3 < 5000) big = $3 } END {print big + 1}' $passwd_file`
      #4. 设定新用户的主目录变量
      home_dir=$home_root_dir/$login
      gid=$uid
      #5. 提示输入和创建新用户相关的信息,如用户全名和主Shell。
      echo -n "full name: "
      read fullname
      echo -n "shell: "
      read shell
      #6. 将输入的信息填充到passwd、group和shadow三个关键文件中。
      echo "Setting up account $login for $fullname..."
      echo ${login}:x:${uid}:${gid}:${fullname}:${home_dir}:$shell >> $passwd_file
      echo ${login}:*:11647:0:99999:7::: >> $shadow_file
      echo "${login}:x:${gid}:$login" >> $group_file
      #7. 创建主目录,同时将新用户的profile模板拷贝到新用户的主目录内。
      #8. 设定该主目录的权限,再将其下所有文件的owner和group设置为新用户。
      #9. 为新用户设定密码。
      mkdir $home_dir
      cp -R /etc/skel/.[a-zA-Z]* $home_dir
      chmod 755 $home_dir
      find $home_dir -print | xargs chown ${login}:${login}
      passwd $login
      exit 0
      CTRL+D
      /> ./test22.sh
      Add new user account to bogon
      login: stephen
      full name: Stephen Liu
      shell: /bin/shell
      Setting up account stephen for Stephen Liu...
      Changing password for user stephen.
      New password:
      Retype new password:
      passwd: all authentication tokens updated successfully.
   
二十三、kill指定用户或指定终端的用户进程:

      这是一台运行Oracle数据库的Linux服务器,现在我们需要对Oracle做一些特殊的优化工作,由于完成此项工作需要消耗更多的系统资源,因此我们不得不杀掉一些其他用户正在运行的进程,以便节省出更多的系统资源,让本次优化工作能够尽快完成。
      /> cat > test23.sh
      #!/bin/sh
      user=""
      tty=""
      #1. 通过读取脚本的命令行选项获取要kill的用户或终端。-t后面的参数表示终端,-u后面的参数表示用户。这两个选项不能同时使用。
      #2. case中的代码对脚本选项进行验证,一旦失败则退出脚本。
      while getopts u:t: opt; do
          case $opt in
          u) if [ "$tty" != "" ]; then
                 echo "-u and -t can not be set at one time."
                 exit 1
              fi
              user=$OPTARG
              ;;
          t)  if [ "$user" != "" ]; then
                 echo "-u and -t can not be set at one time."
                 exit 1
              fi
              tty=$OPTARG
              ;;
          ?) echo "Usage: $0 [-u user|-t tty]" >&2
              exit 1
          esac
      done
      #3. 如果当前选择的是基于终端kill,就用$tty来过滤ps命令的输出,否则就用$user来过滤ps命令的输出。
      #4. awk命令将仅仅打印出pid字段,之后传递给sed命令,sed命令删除ps命令输出的头信息,仅保留后面的进程pids作为输出,并初始化pids数组。
      if [ ! -z "$tty" ]; then
          pids=$(ps cu -t $tty | awk "{print \$2}" | sed '1d')
      else
          pids=$(ps cu -U $user | awk "{print \$2}" | sed '1d')
      fi
      #5. 判断数组是否为空,空则表示没有符合要求的进程,直接退出脚本。
      if [ -z "$pids" ]; then
          echo "No processes matches."
          exit 1
      fi
      #6. 遍历pids数组,逐个kill指定的进程。
      for pid in $pids; do
          echo "Killing process[pid = $pid]... ..."
          kill -9 $pid
      done
      exit 0
      CTRL+D
      /> ./test23.sh -t pts/1
      Killing process[pid = 11875]... ...
      Killing process[pid = 11894]... ...
      /> ./test23.sh -u stephen
      Killing process[pid = 11910]... ...
      Killing process[pid = 11923]... ...
       
二十四、判断用户输入(是/否)的便捷方法:

      对于有些交互式程序,经常需要等待用户的输入,以便确定下一步的执行流程。通常而言,当用户输入"Y/y/Yes/yes"时表示确认当前的行为,而当输 入"N/n/No/no"时则表示否定当前的行为。基于这种规则,我们可以实现一个便捷确认方式,即只判断输入的首字母,如果为Y或y,表示确认,如为N 或n,则为否定。
      /> cat > test24.sh
      #!/bin/sh
      echo -n "Please type[y/n/yes/no]: "
      read input
      #1. 先转换小写到大写,再通过cut截取第一个字符。
      ret=`echo $input | tr '[a-z]' '[A-Z]' | cut -c1`
    
      if [ $ret = "Y" ]; then
          echo "Your input is Y."
      elif [ $ret = "N" ]; then
          echo "Your input is N."
      else
          echo "Your input is error."
      fi
      CTRL+D
      /> ./test24.sh
      Please type[y/n/yes/no]: y
      Your input is Y.
      /> ./test24.sh
      Please type[y/n/yes/no]: n
      Your input is N.  

 

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

分享到:
评论

相关推荐

    Linux Shell高级技巧实战总结

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

    Linux Shell编程3/3

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

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

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

    Shell高级编程(中文版)

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

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

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

    LINUX与UNIX 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与UNIX SHELL编程指南 PDF 高清版 [16.3M]

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

    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编程指南(很全)

    第四部分 基础shell编程 第16章 shell脚本介绍 151 16.1 使用shell脚本的原因 151 16.2 脚本内容 151 16.3 运行一段脚本 152 16.4 小结 153 第17章 条件测试 154 17.1 测试文件状态 154 17.2 测试时使用逻辑操作符 ...

    Linux与unix+shell编程指南.pdf

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

    Linux shell编程指南

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

    Shell初级和高级技巧

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

    Linux命令学习 shell pdf格式

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

    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编程指南.rar

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

    Linux与unix shell编程指南

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

Global site tag (gtag.js) - Google Analytics