`
renzhelife
  • 浏览: 664525 次
文章分类
社区版块
存档分类
最新评论

适合系统管理新手的 bash 脚本编程

 
阅读更多

UNIX shell 实质上是用户、内核和系统硬件之间的接口。在任何 UNIX 或 Linux 系统上,shell 都是非常重要的,是学习正确的系统管理和安全保护最关键的方面之一。shell 通常由 CLI 驱动,可以直接控制或破坏系统。本文讨论的开放源码的 bash shell 是最强大、最实用、可扩展性最好的 shell 之一。在本文中,您将学习 bash 脚本编程的基本技术、日常使用方法以及用它创建可靠的 shell 脚本的方法。

常用缩略词

  • API: 应用程序编程接口
  • CLI: 命令行接口
  • SNMP: 简单网络管理协议

bash shell 的历史

Bourne Again Shell (bash) 诞生于 1987 年,是作为 GNU 项目开发的,许多 Linux 发行版很快就采用了它。当前,有许多不同的 bash 版本可免费使用。

bash 的优点之一是它具有内置的安全特性。bash 会准确地记录用户输入的命令,并把记录写到用户主目录中的隐藏文件 .bash_history 中。因此,如果实现 bash,就很容易更紧密地跟踪系统用户。实际上,对于许多 Linux 系统,bash 常常是预安装的默认 shell 环境。

bash 的命令语法和关键词源于 Korn shell (ksh) 和 C shell (csh) 的架构和技术细节并做了改进。另外,bash 的语法具有其他 shell 所没有的许多扩展。与其他 shell 相比,bash 中的整数计算更高效,而且 bash 可以更方便地重定向标准输出(stdout)和标准错误(stderr)。

bash 还非常适合于安全性要求高的环境,它具有受限制的启动模式,可以把 shell 中的用户限制为只能执行一组确定的命令。可以通过编辑自己的 bash shell 登录控制文件(即 .bashrc、.bash_profile、.bash_logout 和 .profile 等隐藏文件)定制登录 shell。

bash shell 的用法和功能

要想编写有效的 bash shell 脚本,就必须掌握在 shell 中执行导航和日常任务的基本 bash 命令集。

bash 登录过程

在登录时,用户通常执行一个全局概要文件和两个个人文件(.bash_profile 和 .bashrc)。图 1 显示通常的过程。


图 1. bash shell 登录过程
bash shell 登录过程

现在,看看 Linux 用户典型的 .bash_profile(清单 1 )和 .bashrc(清单 2 )脚本。这些脚本是从用户的主目录装载的。


清单 1. 典型的 .bash_profile 文件
				
[fred.smythe@server01 ~]$ cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs
export JAVA_HOME=/usr/java/default
export PATH=$JAVA_HOME/bin:$PATH

PATH=$PATH:$HOME/bin

export PATH

清单 2 中的 .bashrc 文件中,配置了一些用户别名并装载了全局 bashrc 文件(如果存在的话)。


清单 2. 典型的 .bashrc 文件
				
[fred.smythe@server01 ~]$ cat .bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias tc6='cd /opt/tomcat/6.0.13'
alias conf6='cd /opt/tomcat/6.0.13/conf'
alias bin6='cd /opt/tomcat/6.0.13/bin'
alias scr='cd /opt/tomcat/scripts'
alias reports='cd /opt/tomcat/reports'
alias temp6='cd /opt/tomcat/6.0.13/template'

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

图 2 中可以看到登录过程的细节。


图 2. bash shell 登录过程细节
bash shell 登录过程细节

在此之后,用户就可以使用 bash shell 环境变量 $PATH 中指定的标准命令集。如果某个命令不在用户的 $PATH 中,但是该用户有执行此命令的权限,那么必须使用完整的路径,见 清单 3


清单 3. bash shell 中的 $PATH 问题示例
				
[fred.smythe@server01 ~]$ ifconfig -a
-bash: ifconfig: command not found
[fred.smythe@server01 ~]$ which ifconfig
/usr/bin/which: no ifconfig in (/usr/local/bin:/bin:/usr/bin:/home/fred.smythe/bin)

出现此问题的原因是二进制程序 ifconfig 不在用户定义的 PATH 变量中。但是,如果知道此命令的完整路径,就可以像 清单 4 这样执行它。


清单 4. 使用命令的完整路径解决 bash shell 中的 $PATH 问题
				
[fred.smythe@server01 ~]$ /sbin/ifconfig -a
eth0 Link encap:Ethernet HWaddr 00:50:56:96:2E:B3
inet addr:10.14.33.60 Bcast:10.14.33.255 Mask:255.255.255.0

清单 5 演示一种使用别名解决此问题的方法。在 bash 脚本中,可能希望用完整路径运行命令,这取决于谁将运行脚本。


清单 5. 通过设置别名解决 bash shell 中的 $PATH 问题
				
[fred.smythe@server01 ~]$ alias ifconfig='/sbin/ifconfig'
[fred.smythe@server01 ~]$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:50:56:96:2E:B3
inet addr:10.14.33.60 Bcast:10.14.33.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

forking

命令或 bash shell 本身可能启动(或生成)新的 shell 子进程以执行某一任务,这称为 forking 。当这个新进程(子进程)正在执行时,父进程仍然在运行。如果父进程先于子进程死亡,那么子进程就成了死进程(也称为僵尸进程 ),这常常会导致进程或应用程序挂起。因此,必须以非常规方法杀死或终止挂起的进程。尽管父进程可以访问其子进程的进程 ID 并向它传递参数,但是反过来不行。当 shell 脚本进程退出或返回到父进程时,退出码应该是 0 。如果是其他值,那么进程很可能出现了错误或问题。

执行的最后一个命令的退出码(echo $? )见 清单 6


清单 6. 退出码示例
				
# ls -ld /tmp
drwxrwxrwt 5 root root 4096 Aug 19 19:45 /tmp
[root@server01 ~]# echo $?
0 // Good command return of 0.
[root@server01 ~]# ls -l /junk
ls: /junk: No such file or directory
[root@server01 ~]# echo $?
2 // Something went wrong, there was an error, so return 2.

清单 7 演示 bash 环境中的父进程和子进程。


清单 7. bash 环境中的父进程和子进程示例
				
[root@server02 htdocs]# ps -ef | grep httpd
UID PID PPID C STIME TTY TIME CMD
root 8495 1 0 Jul26 ? 00:00:03 /usr/sbin/httpd -k start
apache 9254 8495 0 Aug15 ? 00:00:00 /usr/sbin/httpd -k start

了解自己的环境

如果输入命令 env ,就会看到 bash shell 默认环境变量当前设置的值,包括您的用户名和 tty(终端)信息、$PATH 值和当前工作目录($PWD)。请看一下 清单 8


清单 8. bash 环境的示例
				
[fred.smythe@server01 ~]$ env
HOSTNAME=server01
TERM=screen
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=10.12.132.3 56513 22
SSH_TTY=/dev/pts/0
USER=fred.smythe
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05
;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32
:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=
01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=
01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35:
MAIL=/var/spool/mail/fred.smythe
PATH=/usr/local/bin:/bin:/usr/bin:/home/fred.smythe/bin
INPUTRC=/etc/inputrc
PWD=/home/fred.smythe
LANG=en_US.UTF-8
SHLVL=1
HOME=/home/fred.smythe
LOGNAME=fred.smythe
SSH_CONNECTION=10.14.43.183 56513 10.14.43.43 22
LESSOPEN=|/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=/bin/env

文件系统导航

可以使用 清单 9 所示的 bash 命令导航 Linux 文件系统。


清单 9. 在 bash 环境中导航
				
[fred.smythe@server01 ~]$ ls -l
total 0
[fred.smythe@server01 ~]$ cd /tmp
[fred.smythe@server01 tmp]$ df -ha .
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_root-lv_tmp
2.0G 68M 1.8G 4% /tmp

在此清单中,每次只执行一个命令。但是,也可以使用分号(; )分隔符一起运行它们,见 清单 10


清单 10. 在 bash 中连续执行命令
				
[fred.smythe@server01 tmp]$ ls -l ;cd /tmp;df -ha .
total 40
-rw-r----- 1 root root 1748 May 22 2009 index.html
-rw-r----- 1 root root 786 Aug 17 04:59 index.jsp
drwx------ 2 root root 16384 Jul 15 2009 lost+found
drwx------ 2 root root 4096 Aug 9 21:04 vmware-root
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_root-lv_tmp
2.0G 68M 1.8G 4% /tmp
[fred.smythe@server01 tmp]$

在 bash 命令行上,命令补全特性可以减少日常任务所需的输入量。只需输入命令的开头,然后按 Tab 键。注意,如果由于权限限制无法访问某个命令或文件,那么命令补全也无效。

在 bash 中获得帮助

bash 提供几种形式的帮助:

  • man (见 清单 11 ):

    清单 11. bash 中的手册页示例
    						
    [fred.smythe@server01 tmp]$ man perl
    PERL(1) Perl Programmers Reference Guide PERL(1)

    NAME
    perl - Practical Extraction and Report Language

    SYNOPSIS
    perl [ -sTtuUWX ] [ -hv ] [ -V[:configvar] ] -cw ] [ -d[t][:debugger] ] [ -D
    [num- ber/list] ] [ -pna ] [ -Fpattern ] [ -l[octal] ] [ -0[octal/hexadecimal] ]
    [ -Idir ] [ -m[-]module ] [ -M[-] module... ] [ -f ] [ -C [number/list] ]
    [ -P ] [ -S ] [ -x[dir] ] [ -i[extension] ] [ -e command ] [ -- ]
    [ program- file ] [ argument ]...
  • whatis (见 清单 12 ):

    清单 12. bash 中的 whatis 命令示例
    						
    [fred.smythe@server01 tmp]$ whatis perl
    perl (1) - Practical Extraction and Report Language
    perl (rpm) - The Perl programming language
  • apropos (见 清单 13 ):

    清单 13. bash 中的 apropos 示例
    						
    [root@server01 ~]# apropos perl | more
    B (3pm) - The Perl Compiler
    B::Asmdata (3pm) - Autogenerated data about Perl ops,
    used to generate bytecode
    B::Assembler (3pm) - Assemble Perl bytecode
  • which (见 清单 14 ):

    清单 14. bash 中的 which 命令
    						
    [root@server01 ~]# which perl
    /usr/bin/perl

bash shell 包含两类命令:内部的内置命令 外部程序 (或外部筛选器和命令,它们通常是自含的二进制程序文件)。清单 15 说明如何使用 alias 命令在 bash 中寻找内置命令。


清单 15. 在 bash 中寻找内置命令
				
[root@server01 ~]# man -k builtins| more
. [builtins] (1) - bash built-in commands, see bash(1)
: [builtins] (1) - bash built-in commands, see bash(1)
[ [builtins] (1) - bash built-in commands, see bash(1)
alias [builtins] (1) - bash built-in commands, see bash(1)
bash [builtins] (1) - bash built-in commands, see bash(1)
bg [builtins] (1) - bash built-in commands, see bash(1)
bind [builtins] (1) - bash built-in commands, see bash(1)
break [builtins] (1) - bash built-in commands, see bash(1)
builtin [builtins] (1) - bash built-in commands, see bash(1)

可以使用 type 命令在 bash 中寻找特定的命令,见 清单 16


清单 16. 使用 type 命令寻找内置命令
				
[root@apache-02 htdocs]# type lsof
lsof is /usr/sbin/lsof
[root@apache-02 htdocs]# type alias
alias is a shell builtin

清单 17 给出外部命令 lsof 的示例。此命令实际上是驻留在 Linux 文件系统中的二进制文件;它是通过同名的包安装的。


清单 17. 在 bash 中寻找外部命令详细信息
				
[root@server01 ~]# which lsof
/usr/sbin/lsof
[root@server01 ~]# rpm -qa lsof-4.78-3.i386
[root@server01 ~]# rpm -qa lsof
lsof-4.78-3.i386

即时 bash 脚本编程

bash shell 最强大的特性之一是允许即时命令行脚本编程。比如 清单 18 中的示例,它设置一个 shell 变量,检查变量的值,如果值大于零,就自动地执行另一个命令。


清单 18. 用 bash 进行即时脚本编程
				
[fred.smythe@server01 ~]$ DEBUG=1
[fred.smythe@server01 ~]$ test $DEBUG -gt 0 && echo "Debug turned on"
Debug turned on

下面是即时编写的 for 循环示例(见 清单 19 )。注意,这里在 shell 提示下交互地输入;在每个 > 后面,输入交互式 shell 脚本的下一行。


清单 19. 在 bash 中即时编写的 for 循环
				
$ for SVR in 1 2 3
> do
> echo server0$SVR.example.com
> done
server01.example.com
server02.example.com
server03.example.com

注意,也可以将此代码作为分号分隔的连续命令予以运行。

使用关键词

for 命令并不是程序,而是称为关键词 的特殊内置命令。Linux 上一般 bash 版本的关键词列表见 清单 20


清单 20. bash 中的关键词
				
true, false, test, case, esac, break, continue, eval, exec, exit, export, readonly,
return, set, shift, source, time, trap, unset, time, date, do, done, if, fi, else, elif,
function, for, in, then, until, while, select

在为 shell 变量选择名称时,应该避免使用这些关键词(也称为 bash shell 保留字 )。

在 bash 中用管道输送命令

bash shell 允许重定向 Linux 或 UNIX 系统上的标准输入、标准输出和标准错误。请看 清单 21 中的示例。


清单 21. 在 bash 中用管道输送命令
				
$ USER="fred.smythe"
$ echo -n "User $USER home is: " && cat /etc/passwd | grep $USER | awk -F: '{print $6}'
User fred.smythe home is: /home/fred.smythe
$
# Re-direction of standard output (>) of the date command to a file :
[root@server01 ~]# date > /tmp/today.txt
[root@server01 ~]# cat /tmp/today.txt
Thu Aug 19 19:38:33 UTC 2010

# Re-direction of standard input (<) to standard output (>) …
[root@server01 ~]# cat < /tmp/today.txt > /tmp/today.txt.backup
[root@server01 ~]# cat /tmp/today.txt.backup
Thu Aug 19 19:38:33 UTC 2010

复合命令行

复合命令行可以使用和组合标准输入、标准输出和标准错误重定向和/或管道的多个实例,从而执行具有较高准确性的复杂操作。清单 22 提供一个示例。


清单 22. 在 bash 中执行重定向的示例
				
# command1 < input_file1.txt > output_file1.txt
# command1 | command2 | command3 > output_file.log

例如,通过使用复杂的组合命令行,可以搜索找到的所有压缩的错误日志并统计错误数量,由此查明 Apache 拒绝权限错误的数量。

$ find ./ -name 'error_log.*.gz' | xargs zcat | grep 'Permission denied'| wc -l
3

编写高质量的 bash 脚本

要想完成生产质量或企业级的脚本编程,必须记住以下几个要点:

  • 一定要用简短的标题注释脚本。
  • 要加上足够的注释,这样以后就可以轻松地想起原来编写代码的原因。请记住,脚本的第一行必须是 #!/bin/bash 行。
  • 应该把脚本的操作记录在日志文件中并加上日期和时间戳,以便日后检查。输出应该很详细,应该记录成功消息并清楚地表述错误消息或条件。记录脚本的启动和停止时间也可能有意义。可以使用 tee 命令把消息同时写到日志和标准输出:
    DATEFMT=`date "+%m/%d/%Y %H:%M:%S"`
    echo "$DATEFMT: My message" | tee -a /tmp/myscript.log
  • 如果脚本要写入日志文件,那么应该创建新的日志文件,并在日志文件名中包含日期、小时、分钟甚至秒。这样的话,在每次运行脚本时,可以使用简单的 find 命令循环和压缩脚本的日志:
    DATELOG=`date "+%m%d%y"`
    LOGFILE="/data/maillog/mail_stats.log.$DATELOG"

    # gzip the old mail_stats logs, older than 7 days
    find /logs -type f -name "mail_stats.log.????????????" -mtime +7 | xargs gzip -9

    # remove the old gzipped mail_stats logs after 30 days
    find /logs -type f -name "mail_stats.log.*.gz" -mtime +30 -exec rm {} /;

    # mail_log utility log resets
    echo "" > /var/log/mail_stats.log.$DATELOG
  • 应该在脚本中加入错误检查逻辑,不要假设任何东西是正确的。这样做会减少日后的很多麻烦和挫折。
  • 尽可能在脚本中使用函数和 shell 脚本库(通过导入另一个脚本)。这样做可以重用经过测试的可靠的代码,避免重复编写脚本代码并减少错误。
  • 要对用户提供的输入参数进行筛选:
    NUMPARAMETERS="$#"
    if [ $NUMPARAMETERS != 3 ];then
    echo "Insufficient number of parameter passed!”
    echo “Please run script in format ./myscript.sh $1 $2 $3”
    exit 2
    fi
  • 考虑在脚本中增加调试模式或功能 — 比如使用 set –x 命令。
  • 在脚本中添加对某些事件发出警报的功能。可以使用 SNMP 命令或听得到的铃声(echo x )发出警报,然后用 mail 命令发送电子邮件。
  • 如果用户将像使用交互式菜单那样使用您编写的脚本,那么要考虑用户的环境 shell 和他们有权访问的命令。如果不确定,那么脚本中的所有命令都应该使用完整路径。
  • 在 bash shell 脚本中添加独特的返回码。这样的话,在编写大脚本时,可以根据返回码轻松地找到发生错误或问题的准确位置:
    if [ “$ERRCHECK” != “” ];then
    echo “Error Detected : $ERRCHECK ! Cannot continue, exit $EXITVAL value”
    exit $EXITVAL
    fi
  • 在试验室环境中,针对可能出现的所有情况全面测试脚本。还应该让其他用户对脚本执行测试,让他们故意尝试 “破坏” 脚本。
  • 如果脚本操作来自用户或数据输入文件的输入数据,那么一定要全面筛选、检查和检验输入数据。操作数据列表的脚本应该可以处理多个不同的数据列表集。
  • 对于长时间运行的脚本,考虑在脚本中添加超时功能,以便在 n 分钟之后终止或停止脚本:
    stty –icannon min 0 time 1800
  • 在代码中适当地进行缩进,增加代码的可读性。

对于用于特殊用途的脚本,可能希望添加交互式警告提示消息,从而向用户说明脚本的用途。例如,清单 23 中的脚本获取远程日志并创建一个报告电子邮件。


清单 23. 获取并报告日志的简单 bash 脚本
				
#!/bin/bash

cd /data01/maillog

MAILSVRS=$(/bin/cat /data01/maillog/mail_servers)
DATELOG=`date "+%m%d%y"`
ALLMAILLOGS="/data01/maillog/all_svr_maillogs.$DATELOG"
MAILREPORT="/data01/maillog/all_svr_maillogs.report.$DATELOG"
MAILADDRESSES=$(/bin/cat /data01/maillog/addresses)
MAILADMINS="admin1@example.com, admin2@example.com"
MAILSTATSLOGALL="/data01/maillog/mailstats.log.all.$DATELOG"
DELDAYSLOGS=10

echo “Mail Report to $ MAILADMINS”

# 1 - Get some logs …
for svr in $MAILSVRS
do
if [ -e "/data01/maillog/$svr.maillog.$DATELOG.gz" ]; then
/bin/rm -f /data01/maillog/$svr.maillog.$DATELOG.gz
fi
done

# 2 - Combine all maillogs from all servers to onefile ($ALLMAILLOGS) ...
/bin/zcat server16.maillog.$DATELOG.gz server17.maillog.$DATELOG.gz
server18.maillog.$DATELOG.gz server19.maillog.$DATELOG.gz >>
$ALLMAILLOGS

# 3 - Run another script
/bin/cat $ALLMAILLOGS | /data01/maillog/mymailstats.pl | tee -a $MAILREPORT

# 4 - Get all of the mailstats logs to one log file to send by Email
/bin/cat /data01/maillog/mailstats.log.server*.$DATELOG > $MAILSTATSLOGALL
# Send the $MAILADMINS the mail reports
/bin/cat $MAILSTATSLOGALL | mail -s "ACME Servers Outbound Mail Servers
mailstats:$DATELOG" $MAILADMINS

下载 本文的源代码可以得到此脚本的改进版,其中包含更健全的特性。

bash 脚本编程中的变量、语法格式和结构

在 bash 中,可以通过几种方法定义和设置变量。清单 24 中的脚本给出这些 shell 变量声明方法的示例。


清单 24. 定义 bash 变量
				
$ cat a.sh
#!/bin/bash

A="String Value 1"
B='String Value 2'
C=9675
D=96.75
export E="String Value 3"
# if the variable $F is not ALREADY set to a value, assign "String Value 4" ...
F=${F:="String Value 4"}

echo "A=$A"
echo "B=$B"
echo "C=$C"
echo "D=$D"
echo "E=$E"
echo "F=$F"

exit 0

$ ./a.sh
A=String Value 1
B=String Value 2
C=9675
D=96.75
E=String Value 3
F=String Value 4

收集用户输入

要想收集用户输入,应该使用 read 语句并向用户输入分配一个变量,见 清单 25


清单 25. 在 bash 脚本中获取用户输入
				
$ cat prompt.sh
#!/bin/bash
echo "Please enter your first and last name:"
read ans
echo "Hellow $ans , welcome to bash scripting ...!"
exit 0

$ ./prompt.sh
Please enter your first and last name:
Joe Jackson
Hello Joe Jackson , welcome to bash scripting ...!

要想在 bash shell 脚本中使用函数,可以使用 清单 26 所示的方法。


清单 26. 在 bash 中实现函数
				
$ cat function.sh
#!/bin/bash

funcOne() {
echo "Running function 1, with parameter $1"
date
echo "Current listing /tmp directory, last 3 lines"
ls -lrt /tmp | tail -3
}

echo "Hello World"
funcOne "Server01"
exit 0

$ ./function.sh
Hello World
Running function 1, with parameter Server01
Sun Aug 22 22:43:04 UTC 2010
Current listing /tmp directory, last 3 lines
-rw-r- 1 dsmith progdevel 12749743 Aug 16 20:32 files.tar.gz
drwxr-xr-x 2 jjones progdevel 4096 Aug 16 20:42 ff_hosting_files
-rw-r- 1 rhill heng 1440 Aug 22 19:07 myscript.log

也可以像 清单 27 这样编写函数。


清单 27. bash 中的另一种函数定义
				
#!/bin/bash

function funcTwo () {
echo "Running function 2, with parameter $1"
date
echo "Current listing /var directory, last 3 lines"
ls -lrt /var | tail -3
}

funcTwo "Server02"

exit 0

$ ./function.sh
Running function 2, with parameter Server02
Sun Aug 22 22:53:16 UTC 2010
Current listing /var directory, last 3 lines
drwxrwxrwt 3 root root 4096 Aug 6 18:22 tmp
drwxr-xr-x 6 root root 4096 Aug 22 04:02 log
drwxrwxr-x 4 root lock 4096 Aug 22 04:22 lock

function 关键词是可选的。惟一的规则是必须先定义函数,然后才能在程序中使用它。调用函数的方法是调用它的名称并传递必需的或可选的输入参数。

循环和决策

假设您需要在几个服务器上执行某些重复的工作。在 bash 中,可以使用 for 循环轻松地实现这个目标。清单 28 给出代码。


清单 28. 简单 for 循环的 bash 脚本编程示例
				
$SERVERS=”server01 server02 server03 server04 server05”
for i in $SERVERS
do
echo "Removing file from server: $i"
ssh $i rm -f /tmp/junk1.txt
done

bash 中的 while 循环可以重复执行语句一定的次数,或者一直执行到满足某一条件为止。清单 29 给出一个示例。


清单 29. 简单的 while 循环
				
LOOPCTR=1
while [ $LOOPCTR -lt 6 ]
do
echo “Running patch script for server0$LOOPCTR”
/data/patch.sh server0$LOOPCTR
LOOPCTR=`expr $LOOPCTR + 1`
done

bash 中的 case 语句可以用来测试多个条件或值并相应地执行操作。有时候,使用这种语句比嵌套的 for 循环或 if 语句更好,可以减少重复的代码而且结构更清楚。清单 30 给出一个简短的 case 语句,它根据变量 $key 的值调用函数。


清单 30. bash 中的 case 语句示例
				
case $key in
q) logit "Quit";
exit;;
1) echo “/tChecking Mail Servers”;
check_mail_servers;;
2) echo "/tChecking Web Servers";
check_web_servers;;
3) echo “/tChecking App Servers;
check_app_servers;;
4) echo “/tChecking Database Servers”;
check_database_servers;;
b) echo "Go Back to Main menu";
MENUFLAG="main";
main_menu;;
*) echo "$key invalid choice";
invalid;;
esac

bash 脚本编程的优缺点

需要快速地完成某些任务吗?如果您掌握了 bash,就可以非常轻松地编写最新的 web 组件,可以大大减少所需的时间。bash 脚本编程不是编程语言或应用程序。不需要编译器,也不需要特殊的库或软件开发环境。但是,bash shell 脚本的行为与应用程序相似,甚至能够执行应用程序可以完成的一些任务和工作。

从好的方面来说:

  • bash 提供快速开发,代码便于修改。bash 脚本编程的基本方法几乎不随时间变动。
  • 一些编程语言的代码规则或语法的变动可能比较频繁,与它们相比,bash 的语法相当简单明了。
  • 高级 bash 特性向用户提供比以前更强的能力(例如,纪元、函数、信号控制、多个扩展、命令历史、使用一维数组的方法)。
  • 进行 bash shell 脚本编程只需要 *nix bash shell。

从坏的方面来说,bash 代码:

  • 由 shell 执行,然后传递给内核,这个过程通常比编译为纯机器码的二进制程序慢。因此,bash shell 脚本编程可能不适用于某些应用程序设计或功能。
  • 是明文的,具有读权限的任何人都可以轻松地读取它们,而编译的二进制代码是不可读的。在对敏感数据进行编码时,使用明文是很严重的安全风险。
  • 没有特定的标准函数集,而许多现代编程语言有内置的函数,可以满足各种编程需求。

结束语

既然掌握了 bash shell 脚本编程的基础,就必须善用这种能力。应该用您刚掌握的 crontab、简单命令和交互式菜单全力维护 *nix 系统。不要畏惧成为 “bash” 管理员!


下载

描述 名字 大小 下载方法
本教程的示例 bash shell 脚本 Bash_Source.zip.zip 8KB HTTP

关于下载方法的信息


参考资料

学习

  • 阅读 GNU bash reference manual — bash 语法用户指南。
  • Wikipedia 提供出色的 bash shell 定义
  • 阅读 comparison of shells ,对比 bash 与其他 shell。
  • 阅读适合初学者的 bash basics
  • AIX and UNIX 专区 :developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门 :访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总 :AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • AIX and UNIX 下载中心 :在这里你可以下载到可以运行在 AIX 或者是 UNIX 系统上的 IBM 服务器软件以及工具,让您可以提前免费试用他们的强大功能。
  • IBM Systems Magazine for AIX 中文版 :本杂志的内容更加关注于趋势和企业级架构应用方面的内容,同时对于新兴的技术、产品、应用方式等也有很深入的探讨。IBM Systems Magazine 的内容都是由十分资深的业内人士撰写的,包括 IBM 的合作伙伴、IBM 的主机工程师以及高级管理人员。所以,从这些内容中,您可以了解到更高层次的应用理念,让您在选择和应用 IBM 系统时有一个更好的认识。
  • 技术书店 :浏览关于这个主题和其他技术主题的图书。

获得产品和技术

  • 下载 bash 并获取使用 bash shell 所需的参考资料。
  • 查阅 UNIX 和 Linux 可用的 list of shells

讨论

关于作者

Roger Hill 在复杂的大型混合环境中已经担任了 23 年的 UNIX®/Linux® 系统工程师和程序员/开发人员。过去七年,他主要从事各种 UNIX、Linux 和 Windows® 平台之间的通信,以及为这些系统创建无缝且安全的自动化机制。Roger 拥有计算机信息系统第二学位证书、计算机科学学士学位和 Chancellor 的 Linux 管理证书,还通过了九个专业技术认证。

建议

分享到:
评论

相关推荐

    Linux Bash脚本编程大全

    这本书介绍了bash大量的细节和广阔的范围,使用大量的例子详细地介绍了 Bash的语法,各种技巧,调试等等的技术,以循序渐进的学习方式,让你了解Bash的所有特性,在书中还有许多练习可以引导你思考,以得到更深入的...

    Bash脚本编程基础.pdf

    Bash脚本编程基础,非常适合新手初学。内容详细,例子丰富

    高级Bash 脚本编程指南.pdf

    shell 是如此地重要,但令人惊奇的是,介绍shell 的书没有真正令人满意的。所幸的是,我看到了 这本被人称为abs 的书,这本书介绍了bash 大量的细节和广阔的范围,我...想真正学习脚本编程的唯一途径就是编写脚本...

    高级Bash脚本编程指南

    作为系统与用户之间的交互接口,shell 几乎是你在UNIX 工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX 的的开始,并且它 会始终伴随你的工作学习。 shell 是如此地重要,但令人惊奇的是,介绍shell 的...

    LinuxBash脚本编程大全

    作为系统与用户之间的交互接口,shell几乎是你在UNIX工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX的的开始,并且它会始终伴随你的工作学习。 shell是如此地重要,但令人惊奇的是,介绍shell的书没有...

    高级Bash脚本编程指南_手册CHM版

    shell几乎是你在UNIX工作平台上最亲密的朋友,...无论你是新手还是老手,或是使用其他语言的程序员,我能肯定你能在此书用受益。而本书除了介绍BASH的知识之外,也有许多有用的关于Linux/UNIX的知识和其他shell的介绍。

    高级Bash 脚本编程指南

    作为系统与用户之间的交互接口,shell 几乎是你在UNIX 工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX 的的开始,并且它 会始终伴随你的工作学习。 shell 是如此地重要,但令人惊奇的是,介绍shell 的...

    高级Bash脚本编程指南(中文版)

    shell 是如此地重要,但令人惊奇的是...无论你是新手还是老手,或是使用其他 语言的程序员,我能肯定你能在此书用受益。而本书除了介绍 BASH 的知识之外,也有许多有用的关 于 Linux/UNIX 的知识和其他 shell 的介绍。

    高级Bash Shell脚本编程指南

    作为系统与用户之间的交互接口,shell几乎是你在UNIX 工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX 的的开始,并且它会始终伴随你的工作学习。 shell 是如此地重要,但令人惊奇的是,介绍shell 的书...

    bash快速入门,适合新手

    Bash脚本编程. 适合新手快速入门. 简短实用.

    shell脚本编程基础

    shell sed awk作为shell编程的很好入门级文档,我开始学习的时候就是这个文档,现在遇到新手我就会推荐这个文档。

    Bash新手指南

    Linux/Unix shell Bash 编程入门到精通的手册,中文版,chm, 非常详细的描述了bash的语法和实例,能够让你成为Shell编程高手。

    geany-1.35_新手程序员必备开发环境 开源

    Geany是一个小巧的使用GTK+2...超越vscode,vscode调试起来速度比这个慢多了,新手编程经常需要调试,这款软件可以节省你很多很多的时间。 另附使用指南:https://blog.csdn.net/gospellkevin/article/details/82919516

    ABS-Guide-cn(shell编程经典教材)

    毫无疑问,UNIX/Linux最重要的软件之一就是shell,...无论你是新手还是老手,或是使用其他语言的程序员,我能肯定你能在此书用受益。而 本书除了介绍BASH的知识之外,也有许多有用的关于Linux/UNIX的知识和其他shell的

    Learn-Shell:“ Wicked Cool Shell脚本,第二版”的代码和注释

    Wicked Cool Shell Scripts,第二版的Shell脚本集合Wicked Cool Shell Scripts第二版的完整Shell脚本如何使用采购wcss_shell.sh脚本将设置您的bash环境,以便可以从PATH调用这些脚本,而不必相对或绝对地调用这些...

    欧拉公式求圆周率的matlab代码-vidyaratna:为新手提供精选资源,帮助他们开始编程,开源,网络安全以及更多领域

    欧拉公式求长期率的matlab代码 维迪亚拉特纳 :gem_stone: ...有关Linux命令,Bash脚本等的更多详细信息,请阅读 笔记本电脑建议 一般来说,强烈建议预装Ubuntu的笔记本电脑。 您也可以购买没有图形卡的显卡,

    Linux_BashAwk_scripting_BootCamp_RSG_iGEM_Ecuador

    Linux和Bash / Awk脚本BootCamp 与计算生物学学生小组( )合作开发了理论实践讲习班: 作者: Juan Zurita, ,Camila Armas,DanielaSampértegui新兵训练营的描述和目的本新手训练营旨在学习基于UNIX的操作系统...

Global site tag (gtag.js) - Google Analytics