开始一个小的程序——报告生成器。它将会展示若干系统运行状态指标,并且以HTML格式生成报告。
构建程序需要几个步骤,首先创建最小化的HTML文档:
First Stage: Minimal Document
HTML文件类似于下面:
<HTML>
<HEAD>
<TITLE>Page Title</TITLE>
</HEAD>
<BODY>
Page body.
</BODY>
</HTML>
创建文件 ~/bin/sys_info_page:
[me@linuxbox ~]$ vim ~/bin/sys_info_page
并写入以下命令:
#!/bin/bash
# Program to output a system information page
echo "<HTML>
<HEAD>
<TITLE>Page Title</TITLE>
</HEAD>
<BODY>
Page body.
</BODY>
</HTML>"
授权并执行输出到 sys_info_page.html 文件中,并使用浏览器查看:
[me@linuxbox ~]$ chmod 755 ~/bin/sys_info_page
[me@linuxbox ~]$ sys_info_page > sys_info_page.html
[me@linuxbox ~]$ firefox sys_info_page.html
Second Stage: Adding a Little Data
可以在报告中增加一些数据,首先先改变标题以及body中文本:
#!/bin/bash
# Program to output a system information page
echo "<HTML>
<HEAD>
<TITLE>System Information Report</TITLE>
</HEAD>
<BODY>
<H1>System Information Report</H1>
</BODY>
</HTML>"
Variables and Constants
可以通过定义变量来修改标题以及提示:
#!/bin/bash
# Program to output a system information page
title="System Information Report"
echo "<HTML>
<HEAD>
<TITLE>$title</TITLE>
</HEAD>
<BODY>
<H1>$title</H1>
</BODY>
</HTML>"
上面脚本中定义了变量 title 并赋值为 System Information Report。
Creating Variables and Constants
当 shell 遇到变量时候,他将自动创建该变量,不需要显示声明定义。但有一些问题:
[me@linuxbox ~]$ foo="yes"
[me@linuxbox ~]$ echo $foo
yes
[me@linuxbox ~]$ echo $fool
[me@linuxbox ~]$
上面命令将 foo 赋值为 yes 并使用 echo 来输出其值,但是当使用echo来输出拼写错误的 fool 时候输出空值。这是因为遇到fool时候创建该变量并赋值为默认值空值。
有一些关于变量名的规则:
- Variable names may consist of alphanumeric characters (letters and numbers) and underscore characters.
- The first character of a variable name must be either a letter or an underscore.
- Spaces and punctuation symbols are not allowed.
可以使用大写字母表示常量,小写表示变量:
#!/bin/bash
# Program to output a system information page
TITLE="System Information Report For $HOSTNAME"
echo "<HTML>
<HEAD>
<TITLE>$TITLE</TITLE>
</HEAD>
<BODY>
<H1>$TITLE</H1>
</BODY>
</HTML>"
上述命令中 加入 shell 变量 HOSTNAME,此变量为 机器的网络名称。
【注】shell提供了一种增强常量不变性的方法,可以使用 declare 内置命令 以及-r(只读)选项。
declare -r TITLE="Page Title"
此命令将会预防给 TITLE 赋值。
Assigning Values to Variables and Constants
shell 不在乎变量类型,它将他们视为字符串。
下面是赋值的一些例子:
a=z # Assign the string "z" to variable a.
b="a string" # Embedded spaces must be within quotes.
c="a string and $b" # Other expansions such as variables can be
# expanded into the assignment.
d=$(ls -l foo.txt) # Results of a command.
e=$((5 * 7)) # Arithmetic expansion.
f="\t\ta string\n" # Escape sequences such as tabs and newlines.
多个赋值可以在一行完成:
a=5 b="a string"
也可以将变量名称用大括号括起来。例如:
[me@linuxbox ~]$ filename="myfile"
[me@linuxbox ~]$ touch $filename
[me@linuxbox ~]$ mv $filename $filename1
mv: missing destination file operand after `myfile'
Try `mv --help' for more information.
由于shell将 filename1 解释为mv的第二个参数所导致。因此可以用大括号:
[me@linuxbox ~]$ mv $filename ${filename}1
可以使用上面的特性来使得报告内容更加丰富:
#!/bin/bash
# Program to output a system information page
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME, by $USER"
echo "<HTML>
<HEAD>
<TITLE>$TITLE</TITLE>
</HEAD>
<BODY>
<H1>$TITLE</H1>
<P>$TIME_STAMP</P>
</BODY>
</HTML>"
Here Documents
上面都是用echo命令输出文本。另一种 I/O 重定向 方法,在body中的文本填充为标准输入:
command << token
text
token
修改脚本为:
#!/bin/bash
# Program to output a system information page
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME, by $USER"
cat << _EOF_
<HTML>
<HEAD>
<TITLE>$TITLE</TITLE>
</HEAD>
<BODY>
<H1>$TITLE</H1>
<P>$TIME_STAMP</P>
</BODY>
</HTML>
_EOF_
字符串 EOF (end-of-file),选择它作为标记并标记嵌入文本的结尾。使用 cat 默认情况下,此处文档中的单引号和双引号对shell失去了特殊的意义:
[me@linuxbox ~]$ foo="some text"
[me@linuxbox ~]$ cat << _EOF_
> $foo
> "$foo"
> '$foo'
> \$foo
> _EOF_
some text
"some text"
'some text'
$foo
可以使用此特性来创建从ftp服务器接收文件脚本:
#!/bin/bash
# Script to retrieve a file via FTP
FTP_SERVER=ftp.nl.debian.org
FTP_PATH=/debian/dists/lenny/main/installer-i386/current/images/cdrom
REMOTE_FILE=debian-cd_info.tar.gz
ftp -n << _EOF_
open $FTP_SERVER
user anonymous me@linuxbox
cd $FTP_PATH
hash
get $REMOTE_FILE
bye
_EOF_
ls -l $REMOTE_FILE
如果将重定向符号 << 改为 <<-,shell将会忽略前面的 tab 字符:
#!/bin/bash
# Script to retrieve a file via FTP
FTP_SERVER=ftp.nl.debian.org
FTP_PATH=/debian/dists/lenny/main/installer-i386/current/images/cdrom
REMOTE_FILE=debian-cd_info.tar.gz
ftp -n <<- _EOF_
open $FTP_SERVER
user anonymous me@linuxbox
cd $FTP_PATH
hash
get $REMOTE_FILE
bye
_EOF_
ls -l $REMOTE_FILE