mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-21 02:10:11 +08:00
Merge pull request #9785 from Flowsnow/bash-guide
[translated by Flowsnow] A sysadmin's guide to Bash
This commit is contained in:
commit
3a69e84480
@ -1,198 +0,0 @@
|
||||
translating by Flowsnow
|
||||
A sysadmin's guide to Bash
|
||||
======
|
||||
|
||||

|
||||
|
||||
Each trade has a tool that masters in that trade wield most often. For many sysadmins, that tool is their [shell][1]. On the majority of Linux and other Unix-like systems out there, the default shell is Bash.
|
||||
|
||||
Bash is a fairly old program—it originated in the late 1980s—but it builds on much, much older shells, like the C shell ([csh][2]), which is easily 10 years its senior. Because the concept of a shell is that old, there is an enormous amount of arcane knowledge out there waiting to be consumed to make any sysadmin guy's or gal's life a lot easier.
|
||||
|
||||
Let's take a look at some of the basics.
|
||||
|
||||
Who has, at some point, unintentionally ran a command as root and caused some kind of issue? raises hand
|
||||
|
||||
I'm pretty sure a lot of us have been that guy or gal at one point. Very painful. Here are some very simple tricks to prevent you from hitting that stone a second time.
|
||||
|
||||
### Use aliases
|
||||
|
||||
First, set up aliases for commands like **`mv`** and **`rm`** that point to `mv -I` and `rm -I`. This will make sure that running `rm -f /boot` at least asks you for confirmation. In Red Hat Enterprise Linux, these aliases are set up by default if you use the root account.
|
||||
|
||||
If you want to set those aliases for your normal user account as well, just drop these two lines into a file called .bashrc in your home directory (these will also work with sudo):
|
||||
```
|
||||
alias mv='mv -i'
|
||||
|
||||
alias rm='rm -i'
|
||||
|
||||
```
|
||||
|
||||
### Make your root prompt stand out
|
||||
|
||||
Another thing you can do to prevent mishaps is to make sure you are aware when you are using the root account. I usually do that by making the root prompt stand out really well from the prompt I use for my normal, everyday work.
|
||||
|
||||
If you drop the following into the .bashrc file in root's home directory, you will have a root prompt that is red on black, making it crystal clear that you (or anyone else) should tread carefully.
|
||||
```
|
||||
export PS1="\[$(tput bold)$(tput setab 0)$(tput setaf 1)\]\u@\h:\w # \[$(tput sgr0)\]"
|
||||
|
||||
```
|
||||
|
||||
In fact, you should refrain from logging in as root as much as possible and instead run the majority of your sysadmin commands through sudo, but that's a different story.
|
||||
|
||||
Having implemented a couple of minor tricks to help prevent "unintentional side-effects" of using the root account, let's look at a couple of nice things Bash can help you do in your daily work.
|
||||
|
||||
### Control your history
|
||||
|
||||
You probably know that when you press the Up arrow key in Bash, you can see and reuse all (well, many) of your previous commands. That is because those commands have been saved to a file called .bash_history in your home directory. That history file comes with a bunch of settings and commands that can be very useful.
|
||||
|
||||
First, you can view your entire recent command history by typing **`history`** , or you can limit it to your last 30 commands by typing **`history 30`**. But that's pretty vanilla. You have more control over what Bash saves and how it saves it.
|
||||
|
||||
For example, if you add the following to your .bashrc, any commands that start with a space will not be saved to the history list:
|
||||
```
|
||||
HISTCONTROL=ignorespace
|
||||
|
||||
```
|
||||
|
||||
This can be useful if you need to pass a password to a command in plaintext. (Yes, that is horrible, but it still happens.)
|
||||
|
||||
If you don't want a frequently executed command to show up in your history, use:
|
||||
```
|
||||
HISTCONTROL=ignorespace:erasedups
|
||||
|
||||
```
|
||||
|
||||
With this, every time you use a command, all its previous occurrences are removed from the history file, and only the last invocation is saved to your history list.
|
||||
|
||||
A history setting I particularly like is the **`HISTTIMEFORMAT`** setting. This will prepend all entries in your history file with a timestamp. For example, I use:
|
||||
```
|
||||
HISTTIMEFORMAT="%F %T "
|
||||
|
||||
```
|
||||
|
||||
When I type **`history 5`** , I get nice, complete information, like this:
|
||||
```
|
||||
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
|
||||
|
||||
```
|
||||
|
||||
That makes it a lot easier to browse my command history and find the one I used two days ago to set up an SSH tunnel to my home lab (which I forget again, and again, and again…).
|
||||
|
||||
### Best Bash practices
|
||||
|
||||
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.
|
||||
|
||||
11. Bash scripts can become complicated and comments are cheap. If you wonder whether to add a comment, add a comment. If you return after the weekend and have to spend time figuring out what you were trying to do last Friday, you forgot to add a comment.
|
||||
|
||||
|
||||
10. Wrap all your variable names in curly braces, like **`${myvariable}`**. Making this a habit makes things like `${variable}_suffix` possible and improves consistency throughout your scripts.
|
||||
|
||||
|
||||
9. Do not use backticks when evaluating an expression; use the **`$()`** syntax instead. So use:
|
||||
```
|
||||
for file in $(ls); do
|
||||
```
|
||||
|
||||
|
||||
not
|
||||
```
|
||||
for file in `ls`; do
|
||||
|
||||
```
|
||||
|
||||
The former option is nestable, more easily readable, and keeps the general sysadmin population happy. Do not use backticks.
|
||||
|
||||
|
||||
|
||||
8. Consistency is good. Pick one style of doing things and stick with it throughout your script. Obviously, I would prefer if people picked the **`$()`** syntax over backticks and wrapped their variables in curly braces. I would prefer it if people used two or four spaces—not tabs—to indent, but even if you choose to do it wrong, do it wrong consistently.
|
||||
|
||||
|
||||
7. Use the proper shebang for a Bash script. As I'm writing Bash scripts with the intention of only executing them with Bash, I most often use **`#!/usr/bin/bash`** as my shebang. Do not use **`#!/bin/sh`** or **`#!/usr/bin/sh`**. Your script will execute, but it'll run in compatibility mode—potentially with lots of unintended side effects. (Unless, of course, compatibility mode is what you want.)
|
||||
|
||||
|
||||
6. When comparing strings, it's a good idea to quote your variables in if-statements, because if your variable is empty, Bash will throw an error for lines like these:
|
||||
```
|
||||
if [ ${myvar} == "foo" ]; then
|
||||
|
||||
echo "bar"
|
||||
|
||||
fi
|
||||
|
||||
```
|
||||
|
||||
And will evaluate to false for a line like this:
|
||||
```
|
||||
if [ "${myvar}" == "foo" ]; then
|
||||
|
||||
echo "bar"
|
||||
|
||||
fi
|
||||
```
|
||||
|
||||
Also, if you are unsure about the contents of a variable (e.g., when you are parsing user input), quote your variables to prevent interpretation of some special characters and make sure the variable is considered a single word, even if it contains whitespace.
|
||||
|
||||
|
||||
|
||||
5. This is a matter of taste, I guess, but I prefer using the double equals sign ( **`==`** ) even when comparing strings in Bash. It's a matter of consistency, and even though—for string comparisons only—a single equals sign will work, my mind immediately goes "single equals is an assignment operator!"
|
||||
|
||||
|
||||
4. Use proper exit codes. Make sure that if your script fails to do something, you present the user with a written failure message (preferably with a way to fix the problem) and send a non-zero exit code:
|
||||
```
|
||||
# we have failed
|
||||
|
||||
echo "Process has failed to complete, you need to manually restart the whatchamacallit"
|
||||
|
||||
exit 1
|
||||
|
||||
```
|
||||
|
||||
This makes it easier to programmatically call your script from yet another script and verify its successful completion.
|
||||
|
||||
|
||||
|
||||
3. Use Bash's built-in mechanisms to provide sane defaults for your variables or throw errors if variables you expect to be defined are not defined:
|
||||
```
|
||||
# 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}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
2. Especially if you are writing a large script, and especially if you work on that large script with others, consider using the **`local`** keyword when defining variables inside functions. The **`local`** keyword will create a local variable, that is one that's visible only within that function. This limits the possibility of clashing variables.
|
||||
|
||||
|
||||
1. Every sysadmin must do it sometimes: debug something on a console, either a real one in a data center or a virtual one through a virtualization platform. If you have to debug a script that way, you will thank yourself for remembering this: Do not make the lines in your scripts too long!
|
||||
|
||||
On many systems, the default width of a console is still 80 characters. If you need to debug a script on a console and that script has very long lines, you'll be a sad panda. Besides, a script with shorter lines—the default is still 80 characters—is a lot easier to read and understand in a normal editor, too!
|
||||
|
||||
|
||||
|
||||
|
||||
I truly love Bash. I can spend hours writing about it or exchanging nice tricks with fellow enthusiasts. Make sure you drop your favorites in the comments!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/7/admin-guide-bash
|
||||
|
||||
作者:[Maxim Burgerhout][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/wzzrd
|
||||
[1]:http://www.catb.org/jargon/html/S/shell.html
|
||||
[2]:https://en.wikipedia.org/wiki/C_shell
|
173
translated/tech/20180731 A sysadmin-s guide to Bash.md
Normal file
173
translated/tech/20180731 A sysadmin-s guide to Bash.md
Normal file
@ -0,0 +1,173 @@
|
||||
系统管理员的Bash指南
|
||||
======
|
||||
|
||||

|
||||
|
||||
每种交易都有一个掌握该交易最常用的工具。 对于许多系统管理员来说,这个工具就是他们的[shell][1]。 在大多数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项列表列出来。
|
||||
|
||||
11. Bash脚本可能变得复杂,注释也很方便。 如果你想知道是否要添加注释,那么就添加一个注释。 如果你在周末之后回来并且不得不花时间搞清楚你上周五想要做什么,那你是忘了添加注释。
|
||||
|
||||
|
||||
10. 用花括号括起所有变量名,比如**`${myvariable}`**。 养成这个习惯可以使`${variable}_suffix`成为可能,还能提高整个脚本的一致性。
|
||||
|
||||
|
||||
9. 计算表达式时不要使用反引号; 请改用**`$()`**语法。 所以使用:
|
||||
```
|
||||
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`**。 你的脚本会被执行,但它会以兼容模式运行——可能会产生许多意外的副作用。 (当然,除非你想要兼容模式。)
|
||||
|
||||
|
||||
6. 比较字符串时,在if语句中给变量加上引号是个好主意,因为如果你的变量是空的,Bash会为这样的行抛出一个错误:
|
||||
```
|
||||
if [ ${myvar} == "foo" ]; then
|
||||
echo "bar"
|
||||
fi
|
||||
```
|
||||
|
||||
对于这样的行,将判定为false:
|
||||
```
|
||||
if [ "${myvar}" == "foo" ]; then
|
||||
echo "bar"
|
||||
fi
|
||||
```
|
||||
|
||||
此外,如果你不确定变量的内容(例如,在解析用户输入时),请给变量加引号以防止解释某些特殊字符,并确保该变量被视为单个单词,即使它包含空格。
|
||||
|
||||
5. 我想这是一个品味问题,但我更喜欢使用双等号(**`==`**),即使是比较Bash中的字符串。 这是一致性的问题,尽管对于字符串比较,只有一个等号会起作用,我的思维立即变为“单个等于是一个赋值运算符!”
|
||||
|
||||
|
||||
4. 使用适当的退出代码。 确保如果你的脚本无法执行某些操作,则会向用户显示已写好的失败消息(最好通过解决问题的方法)并发送非零退出代码:
|
||||
```
|
||||
# we have failed
|
||||
echo "Process has failed to complete, you need to manually restart the whatchamacallit"
|
||||
exit 1
|
||||
```
|
||||
|
||||
这样可以更容易地以编程方式从另一个脚本调用你的脚本并验证其成功完成。
|
||||
|
||||
3. 使用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}
|
||||
```
|
||||
|
||||
2. 特别是如果你正在编写大型脚本,或者是如果你与其他脚本一起处理该大型脚本,请考虑在函数内部定义变量时使用**`local`**关键字。 **`local`**关键字将创建一个局部变量,该变量只在该函数中可见。 这限制了变量冲突的可能性。
|
||||
|
||||
|
||||
1. 每个系统管理员有时必须这样做:在控制台上调试一些东西,可以是数据中心的真实服务器,也可以是虚拟化平台的虚拟服务器。 如果你必须以这种方式调试脚本,你会感谢你自己记住了这个:不要让你的脚本中的行太长!
|
||||
|
||||
在许多系统上,控制台的默认宽度仍为80个字符。 如果你需要在控制台上调试脚本并且该脚本有很长的行,那么你将成为一个悲伤的熊猫。 此外,具有较短行的脚本—— 默认值仍为80个字符——在普通编辑器中也更容易阅读和理解!
|
||||
|
||||
我真的很喜欢Bash。 我可以花几个小时写这篇文章或与其他爱好者交流优秀的技巧。 就希望你们能在评论中留下赞美
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/7/admin-guide-bash
|
||||
|
||||
作者:[Maxim Burgerhout][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/wzzrd
|
||||
[1]:http://www.catb.org/jargon/html/S/shell.html
|
||||
[2]:https://en.wikipedia.org/wiki/C_shell
|
Loading…
Reference in New Issue
Block a user