管理员使用的shell
时间:2008-09-26 来源:suli2921
第27章 管理员使用的shell
本章内容:
n 管理统计信息
n 执行备份
n 管理用户
对于Linux系统管理员来说,没有比shell脚本编程更有用处的了。通常,Linux系统管理员每天需要完成无数项任务,从监视系统磁盘空间和系统用户到备份重要文件。Shell脚本可以让系统管理员的工作变得非常轻松!使用简单的shell脚本就可以自动化执行所有基本的系统管理任务。本章演示了一些可以使用shell脚本完成的任务。
27.1 监视系统统计信息
Linux系统管理员的核心任务之一就是确保系统正确运行。要做到这一点,有许多必须要监视的不同的系统统计信息。创建shell脚本来监视特定情况是必不可少的。
本节描述了如何创建简单的shell脚本来进行监视和立即报告问题,这甚至不需要登录到Linux系统。
27.1.1 监视磁盘空闲空间
多用户Linux系统的最大问题之一就是可用磁盘空间的量。在某些情况下,例如在文件共享服务器上,仅由于一位用户粗心的操作,磁盘空间就可能被立即填满。
此shell脚本将监视特定卷上的可用磁盘空间,并在可用磁盘空间低于设置的阈值时发送一则电子邮件消息。
1. 必须的函数
要自动监视可用的磁盘空间,首先需要使用可以显示这些值的命令。最佳的监视磁盘空间命令是df命令(参见第四章)。df命令的基本输出如下所示:
df命令显示系统上所有真实磁盘和虚拟磁盘的当前磁盘空间的统计信息。对于这个练习,我们将监视根文件系统的大小。我们首先需要解析df命令的结果,以便只提取出根文件系统所在的行。
有多种方法可以完成此操作。最简单地办法是使用sed命令搜索以正斜杠结尾的行:
/dev/hda1 3197228 2453980 580836 81% /
sed脚本的构建方法是使用美元符号(表示行的结尾)和正斜杠(需要进行转义,因为它是sed的特殊字符)。具体如下所示:
$ df | sed -n ’/\/$/p’
/dev/hda1 3197228 2453980 580836 81% /
$
现在,我们得到了根文件系统卷的统计信息,下一步是分离出此行上的百分比值。要完成此操作,需要使用gawk命令:
$ df | sed -n ’/\/$/p’ | gawk ’{print $5}’
81%
$
这已经很接近了,但还是有一个小问题。使用gawk可以过滤出第五个数据字段,但这个值还是包含百分号。必须删除百分号才能够在一个数学等式中使用此值。使用sed命令可以轻松删除:
$ df | sed -n ’/\/$/p’ | gawk ’{print $5}’ | sed ’s/%//’
81
$
成功了!下一步是使用此信息创建脚本。
2. 创建脚本
现在,我们了解了如何提取已经使用的磁盘空间的值,可以使用此公式将值保存到变量中。然后,可以将此值与一个预定值比较,就可以知道使用的空间是否超过了预定的极限。
下面是使用此技术的代码示例:
$ cat diskmon
#!/bin/bash
# monitor available disk space
SPACE=`df | sed -n ’/\/$/p’ | gawk ’{print $5}’ | sed ’s/%//`
if [ $SPACE -ge 90 ]
then
echo "Disk space on root at $SPACE% used" | mail -s "Disk warning"
rich
fi
$
就是这样。一个简单的shell脚本将检查根文件系统的磁盘空间,并在使用的空间超过90%时发送一则电子邮件消息。
3. 运行脚本
在让diskmon脚本自动运行之前,需要手动测试几次以确保它能够正确执行所需的操作。为了测试,可以将检查值更改为比当前磁盘使用百分比低的一个值:
if [ $SPACE -ge 40 ]
在运行脚本时,它应该向您发送一则邮件消息:
$ ./diskmon
Mail version 8.1.2 01/15/2001. Type ? for help.
"/var/mail/rich": 1 message 1 new
›N 1 rich@testbox Tue Feb 5 06:22 16/672 Disk warning
&
Message 1:
From rich@testbox Tue Feb 5 06:22:26 2008
Date: Tue, 5 Feb 2008 06:22:26 -0500
From: rich ‹rich@testbox›
Subject: Disk warning
Disk space on root at 81% used
&q
$
好了!现在可以设置shell脚本来设置它的执行次数以监视磁盘活动。可以通过时间表完成此操作。运行此脚本的频率取决于文件服务器的活跃程度。对于空间较小的文件服务器,只需要一天运行一次:
30 0 * * * /home/rich/diskmon
此时间表项目在每天上午12:30运行shell脚本。对于大型卷文件服务器环境,可能需要一天监视几次:
30 0,8,12,16 * * * /home/rich/diskmon
此时间表项目每天运行四次,分别是上午12:30、上午8:30、下午12:30和下午4:30。
27.1.2 谁在霸占磁盘资源?
如果您负责的Linux服务器上有许多用户,则经常需要解决的一个问题就是谁在使用所有磁盘空间。这个老掉牙的问题有时比其他问题更难以弄清。
不幸的是,虽然跟踪用户磁盘空间使用情况非常重要,但却没有一个Linux命令可以提供此信息。因此,需要编写shell脚本来将其他命令拼凑起来以提取需要查找的信息。本节将演示这个过程。
1. 必须的函数
第一个需要使用的工具是du命令(参见第四章)。此命令显示各个文件和目录的磁盘使用情况。使用-s选项可显示目录级别的概况。这在计算单个用户的磁盘使用情况时非常便利。对/home目录内容使用此命令可总结出每个用户的$HOME目录:
# du -s /home/*
40 /home/barbara
9868 /home/jessica
40 /home/katie
40 /home/lost+found
107340 /home/rich
5124 /home/test
#
好了,这只是个开始。现在,可以查看$HOME目录总计的列表了(以KB为单位)。根据装载/home目录的方式,也许能看到或看不到一个称为lost+found的特殊目录,这不是一个用户帐户。
注意
要获取所有用户$HOME目录的统计信息,在运行脚本时必须作为根用户登录。
要去掉这个目录,可以使用带-v选项的grep命令,将打印出除包含指定文本行以外的所有行:
# du -s /home/* | grep -v lost
40 /home/barbara
9868 /home/jessica
40 /home/katie
107340 /home/rich
5124 /home/test
#
下面,去掉所有的路径名,以便查看用户名。这似乎是sed命令应该做的:
# du -s /home/* | grep -v lost | sed ’s/\/home\//’
40 barbara
9868 jessica
40 katie
107340 rich
5124 test
#
好多了。现在,让我们对此输出按降序排序:
# du -s /home/* | grep -v lost | sed ’s/\/home\///’ | sort -g -r
107340 rich
9868 jessica
5124 test
40 katie
40 barbara
#
sort命令在使用-g选项时将所有数字值排序,并在包括-r选项时按降序排序。
我们感兴趣只有一条信息,即所有用户使用的总磁盘量。下面是获取此值的方法:
# du -s /home
122420 /home
#
以上就是创建磁盘使用信息报告需要的所有信息。现在,我们已经准备好将它放到shell脚本中。
2. 创建脚本
现在,我们知道了如何提取用于报告的原数据,接下来需要创建脚本来读取报告、解析原数据值,最后以可以呈现给用户的格式显示出来。
处理用于报告的数据的最简单方法是使用gawk命令。报告由三个部分构成:
n 头部,用文字标识出各个列。
n 报告主体,显示用户、用户使用的总磁盘空间和用户消耗占总量的百分比。
n 尾部,显示所有用户的总磁盘使用情况。
gawk命令可以将所有这些函数作为单个命令执行,只需使用BEGIN和END标记(参见第16章)。
下面是将所有元素综合在一起的磁盘使用情况的跟踪信息:
# cat diskhogs
#!/bin/bash
# calculate disk usage and report per user
TEMP=`mktemp -t tmp.XXXXXX`
du -s /home/* | grep -v lost | sed ’s/\/home\///’ | sort -g -r ›
$TEMP
TOTAL=`du -s /home | gawk ’{print $1}’`
cat $TEMP | gawk -v n="$TOTAL" ’
BEGIN {
print "Total Disk Usage by User";
print "User\tSpace\tPercent"
}
{
printf "%s\t%d\t%6.2f%\n", $2, $1, ($1/n)*100
}
END {
print "--------------------------";
printf "Total\t%d\n", n
}’
rm -f $TEMP
#
脚本将用于产生原数据的公式得出的结果发送到一个临时文件,然后将总磁盘空间公式的结果保存在$TOTAL中。
然后,脚本在临时文件中检索原数据,并将其发送给gawk命令。gawk命令检索$TOTAL值并将其分配给本地变量n。
gawk命令中的代码首先在BEGIN部分创建报告的头部:
BEGIN {
print "Total Disk Usage by user";
print User\tSpace\tPercent"
}
然后,使用printf命令格式化和重新调整原数据:
{
printf "%s\t%d\t%6.2f%\n", $2, $1, ($1/n)*100
}
此部分的作用是处理du命令输出的每个行。prinf命令允许将输出格式化为一个很好的表。如果愿意在系统上使用长用户名,则可能需要一些格式变换。
此处的另一个技巧是磁盘使用情况脚本将$TOTAL变量值通过gawk命令行参数传递给gawk脚本:
-v n=$TOTAL
现在,gawk的变量n等于用户磁盘空间的总和,可以在gawk脚本中的任意位置使用该值。
最后,脚本在结尾处显示用户已使用的磁盘空间的总和:
END {
print "--------------------------";
printf "Total\t%d\n", n
}’
此处使用了变量n,它包含来自$TOTAL shell变量的值。
3. 运行脚本
都放在一起后,运行脚本时应该得到一个格式完好的报告:
# ./diskhogs
Total Disk Usage by user
User Space Percent
rich 107340 87.68%
jessica 9868 8.06%
test 5124 4.19%
katie 40 0.03%
barbara 40 0.03%
--------------------------
Total 122420
#
现在,我们就得到了一个很有成就感的可以发送给老板的报告了!
注意
如果您的系统上没有Disk Hogs,则du命令在计算所有使用的空间时可能会消耗很长时间。这对看到diskhos脚本的输出造成了一定时间的延迟,请耐心等待!
27.2 监视CPU和内存使用情况
任何Linux系统的核心统计信息应该是CPU和内存使用情况。如果这些值开始失控,那么系统将很快崩溃。本节演示了如何使用几个基本的shell脚本来编写监视和跟踪Linux系统上的CPU和内存使用情况的脚本。
1. 必须的函数
与本章前面介绍的其他脚本一样,第一步是决定脚本需要提取什么样的数据。有几个不同的命令都可以用于从系统提取CPU和内存使用信息。
最基本的系统统计信息命令是uptime命令:
$ uptime
09:57:15 up 3:22, 3 users, load average: 0.00, 0.08, 0.28
$
uptime命令给出了一些我们可以使用的不同的基本信息片段:
n 当前时间
n 系统运行的天、小时和分钟数
n 已登录到系统的用户数
n 1、5和15分钟的装载平均值
另一个提取系统信息的命令是vmstat命令。下面是vmstat命令的输出示例:
$ vmstat
procs- ----memory--------- ---swap-- --io-- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 178660 13524 4316 72076 8 10 80 22 127 124 3 1 92 4 0
$
第一次运行vmstat命令时,将显示自上次重新引导的平均值。要获取当前统计信息,必须使用命令行参数运行vmstat命令:
$ vmstat 1 2
procs- ----memory--------- ---swap-- --io-- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 178660 13524 4316 72076 8 10 80 22 127 124 3 1 92 4 0
0 0 178660 12845 4245 71890 8 10 80 22 127 124 3 1 86 10 0
$
第二行包含Linux系统的当前统计信息。如您所见,vmstat命令的输出有一些隐密的含义。表27-1解释了每个符号的意思。
表27-1
符号 |
描述 |
r |
等待CPU时间的进程数 |
b |
不间断休眠中的进程数 |
swpd |
使用的虚拟内存量(以MB为单位) |
free |
未使用的物理内存量(以MB为单位) |
buff |
用作缓存空间的内存量(以MB为单位) |
cache |
用作高速缓存空间的内存量(以MB为单位) |
si |
从磁盘交换的内存量(以MB为单位) |
so |
交换到磁盘的内存量(以MB为单位) |
bi |
从块设备收到的块数 |
bo |
发送到块设备的块数 |
in |
每秒的CPU中断数 |
cs |
每秒的CPU上下文交换数 |
us |
CPU消耗在运行非内核代码上的时间百分比 |
sy |
CPU消耗在运行内核代码上的时间百分比 |
id |
CPU空间的时间百分比 |
wa |
CPU消耗在等待I/O上的时间百分比 |
st |
从虚拟机窃取的CPU时间百分比 |
信息量很大[j1] 。通常不需要记录来自vmstat命令的所有值,只需要记录各别值。通过空闲内存和空闲的CPU时间百分比就可以了解系统状态的大致情况(截至现在,读者应该大概知道我们将如何从输出中提取这些信息了)。
您可能已经注意到vmstat命令的输出包含表头信息,这不是我们想要的。要解决这个问题,可以使用sed命令以显示只包括数字值的行:
$ vmstat 1 2 | sed -n ’/[0-9]/p’
1 0 172028 8564 5276 62244 9 13 98 28 160 157 5 2 89 5 0
0 0 178660 12845 4245 71890 8 10 80 22 127 124 3 1 86 10 0
$
现在好多了,但现在我们只需要第二行的数据。再一次调用sed编辑器可解析这个问题:
$ vmstat | sed -n ’/[0-9]/p’ | sed -n ’2p’
0 0 178660 12845 4245 71890 8 10 80 22 127 124 3 1 86 10 0
$
现在可以轻松地使用gawk程序提取需要的数据值了。
最后,还需要用日期和时间戳来标记每个数据记录,以便指示抓取快照的时间。date命令非常便利,但date命令的默认输出也许有些不便于处理。可以通过指定另一种格式来简化date命令的输出:
$ date +"%m/%d/%Y %k:%M:%S"
02/05/2008 19:19:26
$
这在输出中看起来好多了。说到输出,还应该考虑如何记录数据值。
对于有规律抽样的数据,通常最好直接将数据输出到日志文件。可以在$HOME目录中创建日志文件,每次运行shell脚本时再追加数据。当想要查看结果时,只需查看日志文件。
还需要花些时间在思考日志文件的格式上。您可能希望确保日志文件中的数据能够便于阅读,这也是此脚本的主要目的。
还有许多不同的方法可以格式化日志文件中的数据。最流行的格式是用逗号分隔各个值(CSV)。这种格式将每个记录的数据分隔到一行中,用逗号分隔记录中的数据字段。由于它便于导入到电子表格,所以这种格式适合热衷于使用电子表格的用户。
然而,创建一个CSV数据文件并不是世界上最好的事情。如果想要提供更美观的报告,可以创建HTML文档。
多年来,HTML早已成为格式化Web页面的标准方法。它使用简单的标记在Web页面中描绘数据类型。然而,HTML并不只用于Web页面。HTML还用于电子邮件消息。取决于MUA客户端,您也许能或不能电子邮件文档中嵌入的HTML。更好的方法是创建HTML报告,然后将其添加为电子邮件附件。
脚本将数据保存在CSV格式的文件中,以便总能够获取原数据并将其导入到电子表格中。当系统管理员运行报告脚本时,报告将被重新格式化为HTML报告。多棒啊!
2. 创建捕获脚本
由于需要在固定时间间隔对系统数据进行抽样,所以需要两个独立的脚本。一个脚本用于捕获数据并将其保存到日志文件中。此脚本应该按时间表有规律地运行。其运行频率取决于Linux系统的繁忙程度。对于大多数系统,每个小时运行一次即可。
第二个脚本应该输出报告数据并以电子邮件方式发送给相应的接收人。通常不希望在每次获取新数据样本时都发送新的电子邮件报告,而是希望第二个脚本以较低的频率按计划任务运行,例如每天一次,或者一天中的第一个任务。
用于捕获数据的第一个脚本称为capstats。如下所示:
$ cat capstats
#!/bin/bash
# script to capture system statistics
OUTFILE=/home/rich/capstats.csv
DATE=`date +%m/%d/%Y`
TIME=`date +%k:%M:%S`
TIMEOUT=`uptime`
VMOUT=`vmstat 1 2`
USERS=`echo $TIMEOUT | gawk ’{print $4}’`
LOAD=`echo $TIMEOUT | gawk ’{print $9}’ | sed ’s/,//’`
FREE=`echo $VMOUT |sed -n ’/[0-9]/p’ |sed -n ’2p’ |gawk ’{print $4}’`
IDLE=`echo $VMOUT |sed -n ’/[0-9]/p’ |sed -n ’2p’|gawk ’{print $15}’`
echo "$DATE,$TIME,$USERS,$LOAD,$FREE,$IDLE" ›› $OUTFILE
$
此脚本从uptime和vmstat命令挖掘统计信息并将它们保存到变量中。然后将值写入到由$OUTFILE变量定义的文件中。对于本示例,我将文件保存到$HOME目录。可以更改此位置以使其适用于您的环境。
创建capstats脚本后,在将其从时间表按规律投入运行之前应该在命令行上进行测试:
$ ./capstats
$ cat capstats.csv
02/06/2008,10:39:57,4,0.26,57076,87
$
脚本创建了新的文件,并将统计信息值放在适当的位置。为了确保后续运行脚本时不会覆盖文件,需要再次测试:
$ ./capstats
$ cat capstats.csv
02/06/2008,10:39:57,4,0.26,57076,87
02/06/2008,10:41:52,4,0.14,46292,88
$
正如我们希望的那样,第二次运行脚本时,新的统计信息数据被追加到了文件的结尾。现在,可以将些脚本按计划任务运行了。要让它每个小时运行一次,可以创建此时间表项:
0 * * * * /home/rich/capstats
在时间表中使用capstats shell脚本的地方需要使用其全路径名。现在,可以每个小时获取一次统计信息,而无需任何其他操作!
3. 生成报告脚本
现在,我们有了一个具有许多原数据的文件,可以开始编写生成提供给老板的报告的脚本了。完成此任务的最佳工具是gawk命令。
gawk命令允许从文件提取原数据并以任何形式显示。首先,从命令行进行测试,使用capstats脚本创建的新的capstats.csv文件:
$ cat capstats.csv | gawk -F, ’{printf "%s %s - %s\n", $1, $2, $4}’
02/06/2008 10:39:57 - 0.26
02/06/2008 10:41:52 - 0.14
02/06/2008 10:50:01 - 0.06
02/06/2008 11:00:01 - 0.18
02/06/2008 11:10:01 - 0.03
02/06/2008 11:20:01 - 0.07
02/06/2008 11:30:01 - 0.03
$
需要使用gawk命令的-F选项将逗号定义为数据中的字段分隔符号。然后,可以按需要检索各个数据字段并进行显示。
对于报告,我们将使用HTML格式。只需要少量的工作就可以创建格式完好的报告。显示报告的浏览器将进行格式化和显示报告的艰巨工作。我们所需要做的只是插入适当的HTML标记以格式化数据。
在HTML中显示电子表格数据的最简单方法就是使用<table>标记。表格标记允许创建带有行和单元格(在HTML中称为区)的表。使用<tr>标记定义行的开始。同样,使用<td>和</td>标记对定义单元格。
完整表格的HTML标记如下所示:
<html>
<body>
<h2>Report title</h2>
<table border="1">
<tr>
<td>Date</td><td>Time</td><td>Users</td>
<td>Load</td><td>Free Memory</td><td>%CPU Idle</td>
</tr>
<tr>
<td>02/05/2008</td><td>11:00:00</td><td>4</td>
<td>0.26</td><td>57076</td><td>87</td>
</tr>
</table>
</body>
</html>
每个数据记录是<tr></tr>标记对的一部分。每个数据字段都位于自己的<td></td>标记对中。
当在浏览器中显示HTML报告时,浏览器将自动创建表,如图27-1所示。
图27-1 在HTML表中显示数据
至于脚本,需要做的只是使用echo命令生成HTML头部的代码,使用gawk命令生成 HTML代码数据,然后关闭表,再次使用echo命令。
生成了HTML报告后,希望将它重定向或通过邮件发送出去。使用mutt命令(参见第26章)可以轻松发送电子邮件附件。
下面是reportstats脚本,将生成HTML报告并通过邮件发送:
$ cat reportstats
#!/bin/bash
# parse capstats data into daily report
FILE=/home/rich/capstats.csv
TEMP=/home/rich/capstats.html
MAIL=`which mutt`
DATE=`date +"%A, %B %d, %Y"`
echo "<html><body><h2>Report for $DATE</h2>" > $TEMP
echo "<table border=\"1\">" >> $TEMP
echo "<tr><td>Date</td><td>Time</td><td>Users</td>" >> $TEMP
echo "<td>Load</td><td>Free Memory</td><td>%CPU Idle</td></tr>" >>
$TEMP
cat $FILE | gawk -F, ’{
printf "<tr><td>%s</td><td>%s</td><td>%s</td>", $1, $2, $3;
printf "<td>%s</td><td>%s</td><td>%s</td>\n</tr>\n", $4, $5, $6;
}’ >> $TEMP
echo "</table></body></html>" >> $TEMP
$MAIL -a $TEMP -s "Stat report for $DATE" rich < /dev/null
rm -f $TEMP
$
由于mutt命令将附加文件的名称用作附件文件名,因此使用mktemp命令创建报告文件并不好。相反,我希望报告的名称更具描述性。脚本的最后将删除文件,所以在何处创建文件并不重要。
警告
多数电子邮件客户端可以通过文件扩展名自动探测附件文件的类型。因此,应该让报告文件以.html结尾。
4. 运行脚本
创建reportstats脚本后,从命令行进行测试并查看结果:
$ ./reportstats
$
图27-2 在Evolution中查看报告附件
这没有什么特别之处。现在真正的测试是查看邮件消息,最好使用图形电子邮件客户端,如KMail或Evolution。图27-2展示了在客户端窗口查看附加的报告。请注意,使用HTML表格后,数据可以具有很好的格式,与在浏览器中查看没有任何区别!
27.2 执行备份
不管您是在商业环境中负责Linux系统或者只是在家庭环境中使用它,丢失数据都是一个灾难。为了防止此类事情发生,执行常规备份都是不错的办法。
然而,好办法和好的执行办法是两码事。制作时间表将重要文件保存起来是一个难题。这是shell脚本的另外一个可取之处。
本节描述了使用shell脚本备份系统上的数据的两种不同方法。
27.2.1 归档数据文件
通常,导致丢失数据的原因不是灾难性的系统崩溃。大多数时候,数据是在你说“噢,不!”的时候丢失的。十有八九是在点击“删除”按钮之后。因此,将正在使用的数据保存为归档副本并放置在系统的另一个位置是一个不错的想法。
如果正在使用Linux系统处理非常重要的项目,则可以创建shell脚本以自动获取正在使用的工作目录的快照,然后将其保存到系统上一个安全的位置。虽然不能防止灾难性的硬盘崩溃,但至少能防止文件被破坏或意外删除。
本节描述了如何创建自动shell脚本以获取正在使用的工作目录快照和保存以往数据版本的归档文件。
1. 必须的函数
在Linux环境中,归档数据时通常使用tar命令(参见第4章)。tar命令用于将整个目录归档为单个文件。下面是使用tar命令创建工作目录归档文件的示例:
$ tar -cf archive.tar /home/rich/test
tar: Removing leading `/’ from member names
$
tar命令返回了一条警告消息,它删除了路径名开始处的正斜杠以将其转换为绝对路径以进行检索。这可以允许在文件系统的任何地方提取tar归档文件。我们希望从脚本中去掉那个消息。可以通过将DTDERR重定向到/dev/null文件(参见第12章)完成此操作:
$ tar -cf archive.tar /home/rich/test 2> /dev/null
$
现在,已经准备好在脚本中使用了。
警告
如果使用包括图形桌面的Linux部署,则请小心归档$HOME目录。虽然只是尝试,但$HOME目录包含许多与图形桌面相关的配置文件和临时文件,创建出的归档文件可能比预计的要大得多。请选择一个子目录保存工作文件,并使用该目录作为归档目录。
创建归档文件后,可以将其发送给最喜爱的压缩工具来缩减其大小:
$ ls -l archive.tar
-rw-rw-r-- 1 rich rich 30720 2008-02-06 12:26 archive.tar
$ gzip archive.tar
$ ls -l archive*
-rw-rw-r-- 1 rich rich 2928 2008-02-06 12:26 archive.tar.gz
$
现在,您的归档系统上有了第一个组件。
下一步是创建滚动的归档系统。如果按固定频率保存工作目录,则可能不需要让最新的归档副本立即覆盖以前的归档副本。
要防止其发生,需要创建一个方法来自动为每个归档副本提供唯一的文件名。最简单的办法是在文件名中使用日期和时间。
如“监视系统统计信息”一节所述,可以格式化date命令以产生需要的任意形式的信息。在创建唯一的文件名时这非常便利。
例如,假设想使用两位数年、月、日的文件名,可以依照下面的方法:
$ DATE=`date +%y%m%d`
$ FILE=tmp$DATE
$ echo $FILE
tmp080206
$
虽然,在文本字符串的末尾挤压$DATE变量看起来似乎很奇怪,但在bash shell是却是合乎语法的。shell将变量值追加到字符串,创建唯一的文件名。
注意
使用日志来唯一标识文件可便于将来查找最近的文件版本。请记住标识日期的格式(如月-日-年)。通常在对文件名排序时,最好可以首先指定年,然后是月,最后是日。
现在我们已经有足够的信息开始创建脚本了。下一章节将带领您创建归档脚本。
2. 创建日常归档脚本
archdaily脚本自动在单独的位置创建工作目录的归档版本,同时使用日期来唯一标识文件。下面是脚本的代码:
$ cat archdaily
#!/bin/bash
# archive a working directory
DATE=`date +%y%m%d`
FILE=archive$DATE
SOURCE=/home/rich/test
DESTINATION=/home/rich/archive/$FILE
tar -cf $DESTINATION $SOURCE 2› /dev/null
gzip $DESTINATION
$
archdaily脚本基于运行时的年、月、日生成唯一的文件名。它还使用环境变量定义源目录以进行归档,所以可以轻松更改此源目录。甚至可以使用命令行参数为archdaily程序添加更多功能。
$DESTINATION变量为归档文件追加了完整的路径名。如果需要,这也可以轻易更改为另一个目录。
测试archdaily脚本的方法非常直接:
$ ./archdaily
$ ls -al /home/rich/archive
total 24
drwxrwxr-x 2 rich rich 4096 2008-02-06 12:50 .
drwx------ 37 rich rich 4096 2008-02-06 12:50 ..
-rw-rw-r-- 1 rich rich 3046 2008-02-06 12:50 archive080206.gz
$
现在,数据被安全地归档在一边了。
3. 创建每小时的归档脚本
如果您处在高卷生产环境中,而文件变更非常迅速,那么每天的归档操作可能远远不够。如果希望将归档频率增加到每小时,则需要再考虑一件事。
如果按每小时归档文件,而使用date命令在文件名中添加时间戳,那么可能很快会发现它们非常难看。您肯定不希望在目录中筛选像下面这样的文件名:
archive080206110233.gz
与其将所有归档文件放在同一文件夹下,不如为归档的文件单独创建一个目录结构。图27-3展示了这个原则。
归档目录包含每年的每个月的目录,将月份用作目录名。每个月的目录依次包含该月每天的目录(使用日期数值作为目录名)。这样可以只对各个归档文件添加时间戳,然后将其放在相应月份和日期下的目录中。
图27-3 创建归档目录结构
现在,有一个新的问题需要解决。脚本必须能够自动创建单独的月份和日期目录,然后知道它们如果已经存在,则不需要再创建。实际上,这没有想像的那么困难。
如果您细读过mkdir命令(参见第三章)的命令行选项,则会发现-p命令行选项。可以通过这一个命令创建目录和子目录,并且在目录已经存在的情况下不产生错误消息。完美极了!
现在我们准备创建archhourly脚本。如下所示:
$ cat archhourly
#!/bin/bash
# archive a working directory hourly
DAY=`date +%d`
MONTH=`date +%m`
TIME=`date +%k%M`
SOURCE=/home/rich/test
BASEDEST=/home/rich/archive
mkdir -p $BASEDEST/$MONTH/$DAY
DESTINATION=$BASEDEST/$MONTH/$DAY/archive$TIME
tar -cf $DESTINATION $SOURCE 2› /dev/null
gzip $DESTINATION
$
此脚本从date命令检索日期和月份的值,还有用于唯一标识归档文件的时间戳。然后使用这些信息创建日期的归档目录(或者在已经存在的情况下以静默方式退出)。最后,脚本使用tar和gzip命令创建归档并进行压缩。
像archdaily脚本一样,在将archhourly脚本放到计划任务表之前应首先对其进行测试:
$ ./archhourly
$ ls -al /home/rich/archive/02/06
total 32
drwxrwxr-x 2 rich rich 4096 2008-02-06 13:20 .
drwxrwxr-x 3 rich rich 4096 2008-02-06 13:19 ..
-rw-rw-r-- 1 rich rich 3145 2008-02-06 13:19 archive1319.gz
$ ./archhourly
$ ls -al /home/rich/archive/02/06
total 32
drwxrwxr-x 2 rich rich 4096 2008-02-06 13:20 .
drwxrwxr-x 3 rich rich 4096 2008-02-06 13:19 ..
-rw-rw-r-- 1 rich rich 3145 2008-02-06 13:19 archive1319.gz
-rw-rw-r-- 1 rich rich 3142 2008-02-06 13:20 archive1320.gz
$
脚本第一次运行的时候是成功的,创建了相应的月份和日期目录,然后创建了归档文件。为了测试彻底,我又运行了一次以查看在处理已存在的目录上是否有问题。脚本再次正常运行,创建了第二个归档文件。现在可以放到时间表中了!
27.2.2 脱机存储备份文件
虽然对重要文件进行归档是一个很好的想法,但这无法取代保存在单独位置的完整备份。在大型的商务Linux环境中,系统管理员通常可以奢侈地使用磁带机将重要文件复制到服务器以外的位置进程安全储存。
对于小型的环境,这并非可行之举。无法负担一种新奇的备份系统的方法并不意味着您的重要数据就要承担风险。可以将shell脚本组合起来,即自动创建归档文件,然后发送到Linux系统以外的位置。本节描述了这种方法。
1. 必须的函数
我们已经学习了归档系统的核心内容,tar和gzip命令。下一个关键就在于将压缩的归档文件放到Linux系统以外的位置。如果已经配置了电子邮件系统(参见第26章),则可以将其作为通往外界的门户。
虽然系统管理员通常不将电子邮件用作归档数据的方式,但这确实是将归档数据保存在另一个安全位置的好方法。本书不建议将整个Linux系统归档并作为电子邮件的附件进行发送,但对工作目录归档并作为附件应该不成问题。
让我们看看这个脚本以及它的工作方式。
2. 创建脚本
mailarch脚本像archdaily和archhourly脚本那样创建了一个常规的归档文件。创建归档文件后,使用Mutt电子邮件客户端将文件发送到远程电子邮件地址。
mailarch脚本如下所示:
$ cat mailarch
#!/bin/bash
# archive a working directory and e-mail it out
MAIL=`which mutt`
DATE=`date +%y%m%d`
FILE=archive$DATE
SOURCE=/home/rich/test
DESTINATION=/home/rich/archive/$FILE
ZIPFILE=$DESTINATION.zip
tar -cf $DESTINATION $SOURCE 2› /dev/null
zip $ZIPFILE $DESTINATION
$MAIL -a $ZIPFILE -s "Archive for $DATE" [email protected] ‹ /dev/null
$
您可能已经注意到了,在mailarch脚本中,我使用了zip压缩工具,而非gzip命令。这可以创建.zip文件,这样在非Linux系统(如Microsoft Windows工作站)上也可以轻松处理这些文件。
3. 运行脚本
mailarch脚本的运行方式与archdaily脚本相同,即将其放到时间表中以便在一天的特定时间运行(通常是在晚上)。在脚本运行时,它将创建归档文件,使用zip命令压缩归档文件,然后将其通过电子邮件消息发送。图27-4展示了收到的电子邮件的形式。
祝贺您,您现在应该掌握了从Linux系统备份重要文件的方法了。
图27-4 带有归档文件的电子邮件消息
27.3 总结
本章将本书中出现的一些shell脚本信息很好地应用于Linux系统管理中。当您负责管理Linux系统时,不管是大型的多用户系统,还是自己的系统,都有许多需要监视的内容。与其大量搜索日志文件和手动运行命令,不如创建shell脚本来为您完成这些任务。
本章介绍了如何使用df命令确定可用的磁盘空间,然后使用sed和gawk命令从数据中检索特定的信息。将命令输出传递给sed和gawk来解析数据是shell脚本的常用方法,所以了解这些命令是非常必要的。
接下来,本章展示了如何使用du命令确定各个用户所使用的磁盘空间。du命令的输出被传递给sed和gawk命令以帮助过滤出我们关心的部分。
下一节演示了如何创建系统日志和报告。capstats shell脚本有规律地捕获关键的系统统计信息,从命令中提取数据并保存在值以逗号分隔的文件中。可以将该文件导入到电子表格中,但本书的做法是创建另一个脚本从数据创建格式化的报告。reportstats shell脚本使用HTML格式将原系统数据放到HTML表格中,然后使用Mutt电子邮件客户端将文件发送给远程用户。
本章最后讨论了使用shell脚本在Linux系统上进行归档和备份数据文件。tar和gzip命令是两个在归档数据时非常受欢迎的命令。本章演示了如何使用它们在shell脚本中创建归档文件,以及在归档目录中管理归档文件。最后,演示了如何通过电子邮件将归档文件发送给远程用户,将其作为备份重要数据文件的一种方法。
感谢您和我一起分享Linux命令行和shell编程的学习之旅。希望您能享受这个过程并了解到如何使用命令行、如何创建shell脚本来节省时间。但不要就此满足。在开源世界中总有新的东西开发出来,可能是新的命令行工具,也可能是完整的shell。多多访问Linux社区,多多了解新的进展和功能。
[j1]