分类: 系统运维
2013-12-30 23:16:40
原文地址:Unix与Linux系统运维进阶最佳实践分享 作者:fengzhanhai
一、最常见的坏习惯每次创建一个目录树:
~ $ mkdir abc
~ $ cd abc
~/abc $ mkdir a
~/abc $ cd a
~/abc/a $ mkdir b
~/abc/a $ cd b
~/abc/a/b/ $ mkdir c
~/abc/a/b/ $ cd c
~/abc/a/b/c $
使用 mkdir 的 -p 选项并在单个命令中创建所有父目录及其子目录要容易得多。所以花时间有意识地养成这个好习惯是值得的。
好习惯 1 的示例:使用一个命令来定义目录树
~ $ mkdir -p abc/a/b/c
您可以使用此选项来创建整个复杂的目录树(在脚本中使用是非常理想的),而不只是创建简单的层次结构。例如:
~ $ mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
二、移动存档解压文件
另一个不良的使用模式是将 .tar 存档文件移动到某个目录,因为该目录恰好是您希望在其中提取 .tar 文件的目录。其实您根本不需要这样做。您可以随心所欲地将任何 .tar 存档文件解压缩到任何目录——这就是 -C 选项的用途。在解压缩某个存档文件时,使用 -C 选项来指定要在其中解压缩该文件的目录:
好习惯 2 的示例:使用选项 -C 来解压缩 .tar 存档文件
tar -xvf pro.tar -C ~
养成使用 -C 的习惯则可将存档文件恢复到指定的某个位置。
三、将命令与控制操作符组合使用
您可能已经知道,在大多数 Shell 中,您可以在单个命令行上通过在命令之间放置一个分号 (;) 来组合命令。该分号是 Shell 控制操作符,虽然它对于在单个命令行上将离散的命令串联起来很有用,但它并不适用于所有情况。例如,假设您使用分号来组合两个命令,其中第二个命令的正确执行完全依赖于第一个命令的成功完成。如果第一个命令未按您预期的那样退出,第二个命令仍然会运行——结果会导致失败。相反,应该使用更适当的控制操作符。只要您的 Shell 支持它们,就值得养成使用它们的习惯。
使用 && 控制操作符来组合两个命令,以便仅当 第一个命令返回零退出状态时才运行第二个命令。换句话说,如果第一个命令运行成功,则第二个命令将运行。如果第一个命令失败,则第二个命令根本就不运行。例如:
好习惯 3 的示例:将命令与控制操作符组合使用
cd /abc/fzh&&rm -rf
在此例中仅当该目录存在时才会执行后续动作。如果该目录不存在,则 rm 命令不会运行。
仅当另一个命令返回非零退出状态时才运行某个命令。类似地,|| 控制操作符分隔两个命令,并且仅当第一个命令返回非零退出状态时才运行第二个命令。换句话说,如果第一个命令成功,则第二个命令不会运行。如果第一个命令失败,则第二个命令才会 运行。在测试某个给定目录是否存在时,通常使用此操作符,如果该目录不存在,则创建它。
好习惯 3 的另一个示例:将命令与控制操作符组合使用
~ $ cd /abc/ff || mkdir -p /abc/ff
您还可以组合使用本部分中描述的控制操作符。每个操作符都影响最后的命令运行:
好习惯 3 的组合示例:将命令与控制操作符组合使用
~ $ cd /abc/fzh || mkdir -p /abc/fzh && tar xvf 123.tar -C /abc/fzh
四、使用转义序列来管理较长的输入
您或许看到过使用反斜杠 (\) 来将较长的行延续到下一行的代码示例,并且您知道大多数 Shell 都将您通过反斜杠联接的后续行上键入的内容视为单个长行。然而,您可能没有在命令行中像通常那样利用此功能。如果您的终端无法正确处理多行回绕,或者您的命令行比通常小(例如在提示符下有长路经的时候),反斜杠就特别有用。反斜杠对于了解键入的长输入行的含义也非常有用,如以下示例所示:
好习惯 4 的示例:将反斜杠用于长输入
~ $ cd acb/a/b/c && \
> mkdir -p acb/a/b/c
然而,当您将输入行划分到多行上时,Shell 始终将其视为单个连续的行,因为它总是删除所有反斜杠和额外的空格。
五、在 find 之外使用 xargs
使用 xargs 工具作为筛选器,以充分利用从 find 命令挑选的输出。find 运行通常提供与某些条件匹配的文件列表。此列表被传递到xargs 上,后者使用该文件列表作为参数来运行其他某些有用的命令,如以下示例所示:
好习惯5:find结合xargs 工具的经典用法示例
find ./ -name "*.LOG" -ctime +1 -type f | xargs -i rm -rf {} \;
然而,不要将 xargs 仅看作是 find 的辅助工具;它是一个未得到充分利用的工具之一,当您养成使用它的习惯时,将会希望进行所有试验,包括以下用法。
您可以发送通过 xargs 来输出文件名的任何工具的输出,以便为其他某些接受文件名作为参数的工具获得参数列表,如以下示例所示:
好习惯实例 6:xargs 工具的使用示例:
[root@LB01 fzh]# ls -1 |xargs
a t.sh zz
[root@LB01 fzh]# ls -1 |xargs file
a: directory
t.sh: ASCII English text
六、了解何时 grep 应该执行计数
避免通过管道将 grep 发送到 wc -l 来对输出行数计数。grep 的 -c 选项提供了对与特定模式匹配的行的计数,并且一般要比通过管道发送到 wc 更快,如以下示例所示:
好习惯 7的示例:使用和不使用 grep 的行计数
[root@LB01 fzh]# time grep hello t.sh|wc -l
2
real 0m0.036s
user 0m0.001s
sys 0m0.005s
#time统计系统资源使用情况
[root@LB01 fzh]# time grep -c hello t.sh
2
real 0m0.004s
user 0m0.001s
sys 0m0.002s
#time统计系统资源使用情况
除了速度因素外,-c 选项还是执行计数的好方法。对于多个文件,带 -c 选项的 grep 返回每个文件的单独计数,每行一个计数,而针对 wc 的管道则提供所有文件的组合总计数。
然而,不管是否考虑速度,此示例都表明了另一个要避免地常见错误。这些计数方法仅提供包含匹配模式的行数——如果那就是您要查找的结果,这没什么问题。但是在行中具有某个特定模式的多个实例的情况下,这些方法无法为您提供实际匹配实例数量 的真实计数。归根结底,若要对实例计数,您还是要使用 wc 来计数。首先,使用 -o 选项(如果您的版本支持它的话)来运行 grep 命令。此选项仅 输出匹配的模式,每行一个模式,而不输出行本身。但是您不能将它与 -c 选项结合使用,因此要使用 wc -l 来对行计数,如以下示例所示:
好习惯 8 的示例:使用 grep 对模式实例计数
grep -o hello t.sh|wc -l
在此例中,调用 wc 要比第二次调用 grep 并插入一个虚拟模式(例如 grep -c)来对行进行匹配和计数稍快一点。
匹配输出中的某些字段,而不只是对行进行匹配
当您只希望匹配输出行中特定字段 中的模式时,诸如 awk 等工具要优于 grep。
下面经过简化的示例演示了如何仅列出 12 月修改过的文件。
坏习惯 9 的示例:使用 grep 来查找特定字段中的模式
[root@LB01 fzh]# ls -l|grep 12-19
总计 12
drwxr-xr-x 4 root root 4096 12-19 02:22 a
-rwxr--r-- 1 root root 350 12-19 02:59 t.sh
在此示例中,grep 对行进行筛选,并输出其修改日期和名称中带12-19 的所有文件。因此,如果12-19.txt等文件是匹配的,即使它自从一月份以来还未修改过。这可能不是您希望的结果。为了匹配特定字段中的模式,最好使用 awk,其中的一个关系运算符对确切的字段进行匹配,如以下示例所示:
好习惯 9 的示例:使用 awk 来查找特定字段中的模式
ls -l|awk '{if($6=="12-19") {print $8}}'
七、禁止对 cat 使用管道
grep 的一个常见的基本用法错误是通过管道将 cat 的输出发送到 grep 以搜索单个文件的内容。这绝对是不必要的,纯粹是浪费时间,因为诸如 grep 这样的工具接受文件名作为参数。您根本不需要在这种情况下使用 cat,如以下示例所示:
好习惯和坏习惯 10 的示例:使用带和不带 cat 的 grep
[root@LB01 fzh]# time cat t.sh|grep hello
read num hello hello
echo "hello kitty"
echo "hello"
real 0m0.003s
user 0m0.001s
sys 0m0.002s
[root@LB01 fzh]# time grep hello t.sh
read num hello hello
echo "hello kitty"
echo "hello"
real 0m0.003s
user 0m0.000s
sys 0m0.001s