9.4 KiB
系统管理员的Bash指南
每种交易都有一个掌握该交易最常用的工具。 对于许多系统管理员来说,这个工具就是他们的shell。 在大多数Linux和其他类Unix系统上,默认的shell是Bash。
Bash是一个相当古老的程序——它起源于20世纪80年代后期——但它建立在更多更老的shell上,比如C shell(csh),作为前辈,csh很轻松经历了10年。 因为shell的概念是那么古老,所以有大量的神秘知识等待着系统管理员去吸收,从而让他们的生活更容易。
我们来看看一些基础知识。
在某些时候,谁曾经无意中以root身份运行命令并导致某种问题? 举手
我很确定我们很多人一度都是那个人。 这很痛苦。 这里有一些非常简单的技巧可以防止你再次碰上这类问题。
使用别名
首先,为**mv
和rm
**等命令设置别名,指向mv -i
和rm -i
。 这将确保在运行rm -f / boot
时至少需要你确认。 在Red Hat企业版Linux中,如果你使用root帐户,则默认设置这些别名。
如果你还要为普通用户帐户设置这些别名,只需将这两行放入家目录下名为.bashrc的文件中(这些也适用于sudo):
alias mv='mv -i'
alias rm='rm -i'
让你的root提示脱颖而出
你可以采取的防止意外发生的另一项措施是确保你很清楚在使用root帐户。 在日常工作中,我通常会让root提示从使用的提示中脱颖而出。
如果将以下内容放入root的家目录中的.bashrc文件中,你将看到一个黑色背景上的红色根root示符,清楚地表明你(或其他任何人)应该谨慎行事。
export PS1="\[$(tput bold)$(tput setab 0)$(tput setaf 1)\]\u@\h:\w # \[$(tput sgr0)\]"
实际上,你应该尽可能避免以root用户身份登录,而是通过sudo运行大多数sysadmin命令,但这是另一回事。
使用了一些小技巧用于防止使用root帐户时的“不小心的副作用”之后,让我们看看Bash可以帮助你在日常工作中做的一些好事。
控制你的历史
你可能知道在bash中你按向上的箭头时能看见能使用所有的(好吧,大多数)你之前的命令。这是因为这些命令已经保存到了你家目录下的名为.bash_history的文件中。这个历史文件附带了一组有用的设置和命令。
首先,你可以通过键入 **history
来查看整个最近的命令历史记录,或者你可以通过键入history 30
**将其限制为最近30个命令。但这是非常标准的(vanilla原为香草,后引申没拓展的,标准的,比如vanilla C++ compiler意为标准C++编译器)。 你可以更好地控制Bash保存的内容以及保存方式。
例如,如果将以下内容添加到.bashrc,那么任何以空格开头的命令都不会保存到历史记录列表中:
HISTCONTROL=ignorespace
如果你需要以明文形式将密码传递给一个命令,这就非常有用。 (是的,这太可怕了,但它仍然会发生。)
如果你不希望在历史记录中显示经常执行的命令,请使用:
HISTCONTROL=ignorespace:erasedups
这样,每次使用一个命令时,都会从历史记录文件中删除之前出现的所有相同命令,并且只将最后一次调用保存到历史记录列表中。
我特别喜欢的历史记录设置是**HISTTIMEFORMAT
**设置。 这将在历史记录文件中在所有的条目前面添加上时间戳。 例如,我使用:
HISTTIMEFORMAT="%F %T "
当我输入**history 5
**时,我得到了很好的完整信息,如下所示:
1009 2018-06-11 22:34:38 cat /etc/hosts
1010 2018-06-11 22:34:40 echo $foo
1011 2018-06-11 22:34:42 echo $bar
1012 2018-06-11 22:34:44 ssh myhost
1013 2018-06-11 22:34:55 vim .bashrc
这使我更容易浏览我的命令历史记录并找到我两天前用来建立到我家实验室的SSH连接(我再次忘记,再次,再次......)。
Bash最佳实践
I'll wrap this up with my top 11 list of the best (or good, at least; I don't claim omniscience) practices when writing Bash scripts.
在编写Bash脚本时,我将用最好的(或者至少是好的,我不要求无所不知)11项列表列出来。
-
Bash脚本可能变得复杂,注释也很方便。 如果你想知道是否要添加注释,那么就添加一个注释。 如果你在周末之后回来并且不得不花时间搞清楚你上周五想要做什么,那你是忘了添加注释。
-
用花括号括起所有变量名,比如**
${myvariable}
**。 养成这个习惯可以使${variable}_suffix
成为可能,还能提高整个脚本的一致性。 -
计算表达式时不要使用反引号; 请改用**
$()
**语法。 所以使用:
for file in $(ls); do
而不使用
for file in `ls`; do
前一个选项是可嵌套的,更易于阅读的,还能让一般的系统管理员群体感到满意。 不要使用反引号。
8. 一致性是好的。 选择一种风格并在整个脚本中坚持下去。 显然,我喜欢人们在反引号中选择**`$()`** 语法并将其变量包在花括号中。 我更喜欢人们使用两个或四个空格而不是制表符来缩进,但即使你选择了错误的方式,也要一贯地错下去。
7. 使用适当的shebang(LCTT译者注:**Shebang**,也称为 **Hashbang** ,是一个由井号和叹号构成的字符序列 *#!* ,其出现在文本文件的第一行的前两个字符。 在文件中存在 Shebang 的情况下,类 Unix 操作系统的程序载入器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,并将载有 Shebang 的文件路径作为该解释器的参数)作为Bash脚本。 因为我正在编写Bash脚本,只打算用Bash执行它们,所以我经常使用**`#!/usr/bin/bash`**作为我的shebang。 不要使用**`#!/bin/sh`**或**`#!/usr/bin/sh`**。 你的脚本会被执行,但它会以兼容模式运行——可能会产生许多意外的副作用。 (当然,除非你想要兼容模式。)
- 比较字符串时,在if语句中给变量加上引号是个好主意,因为如果你的变量是空的,Bash会为这样的行抛出一个错误:
if [ ${myvar} == "foo" ]; then
echo "bar"
fi
对于这样的行,将判定为false:
if [ "${myvar}" == "foo" ]; then
echo "bar"
fi
此外,如果你不确定变量的内容(例如,在解析用户输入时),请给变量加引号以防止解释某些特殊字符,并确保该变量被视为单个单词,即使它包含空格。
-
我想这是一个品味问题,但我更喜欢使用双等号(
==
),即使是比较Bash中的字符串。 这是一致性的问题,尽管对于字符串比较,只有一个等号会起作用,我的思维立即变为“单个等于是一个赋值运算符!” -
使用适当的退出代码。 确保如果你的脚本无法执行某些操作,则会向用户显示已写好的失败消息(最好通过解决问题的方法)并发送非零退出代码:
# we have failed
echo "Process has failed to complete, you need to manually restart the whatchamacallit"
exit 1
这样可以更容易地以编程方式从另一个脚本调用你的脚本并验证其成功完成。
- 使用Bash的内置机制为变量提供合理的默认值,或者如果未定义你希望定义的变量,则抛出错误:
# this sets the value of $myvar to redhat, and prints 'redhat'
echo ${myvar:=redhat}
# this throws an error reading 'The variable myvar is undefined, dear reader' if $myvar is undefined
${myvar:?The variable myvar is undefined, dear reader}
-
特别是如果你正在编写大型脚本,或者是如果你与其他脚本一起处理该大型脚本,请考虑在函数内部定义变量时使用**
local
**关键字。 **local
**关键字将创建一个局部变量,该变量只在该函数中可见。 这限制了变量冲突的可能性。 -
每个系统管理员有时必须这样做:在控制台上调试一些东西,可以是数据中心的真实服务器,也可以是虚拟化平台的虚拟服务器。 如果你必须以这种方式调试脚本,你会感谢你自己记住了这个:不要让你的脚本中的行太长!
在许多系统上,控制台的默认宽度仍为80个字符。 如果你需要在控制台上调试脚本并且该脚本有很长的行,那么你将成为一个悲伤的熊猫。 此外,具有较短行的脚本—— 默认值仍为80个字符——在普通编辑器中也更容易阅读和理解!
我真的很喜欢Bash。 我可以花几个小时写这篇文章或与其他爱好者交流优秀的技巧。 就希望你们能在评论中留下赞美
via: https://opensource.com/article/18/7/admin-guide-bash
作者:Maxim Burgerhout 选题:lujun9972 译者:Flowsnow 校对:校对者ID