These eight suggestions derive from the experience and lessons learned from key writers who have been writing shell scripts for several years. In fact, began to write more than these several, and then pondered repeatedly, remove a few insignificant, finally left eight. It is no exaggeration to say that each is a carefully chosen one, although a few are commonplace.
1. Specify bash
The first line of the shell script, what should it be after #!? If you ask someone about this question, different people may answer differently.
I've seen/usr/bin/env bash, I've seen/bin/bash, and/usr/bin/bash, and/bin/sh, and/usr/bin/env Sh. This is the programming world "' anise ' word four writing".
In most cases, the above five types of formulations are equivalent. However, people who have written the procedure know that "few situations" often hide unexpected pits.
What if the system's default shell is not bash? For example, a version of a Linux distribution, the default SH is not bash.
What if the system bash is not in/usr/bin/bash?
I recommend using/usr/bin/env Bash and/bin/bash. The former adds an intermediate layer through the env, lets env search for bash in $path, and the latter is the official endorsement, the customary bash location, and/usr/bin/bash is just a symbolic link to it.
2. Set-e and Set-x
OK, after some discussion, the first line is now set. Now it's time to start writing the second line, right?
Wait! Before you begin to conceive and write down specific code logic, insert a row of set-e and a row of set-x.
Set-x will output the execution content when executing each line of shell scripts. It lets you see the current execution, and the variables involved are replaced with the actual values.
SET-E will end the program when an error occurs, just like "throw an exception" in another language. (To be exact, not all errors will end the program, see note below)
Note: The set-e end of the program is more complex, in the man bash inside, a full use of a phrase to describe the various scenarios. Most executions will exit when an error occurs, unless the shell command is in the following situations:
A pipeline part of a piece, such as an error | Ok
A non-end part of a combination statement, such as OK && Error | | Other
The end of a series of statements, such as error; Ok
In a judgment statement, including Test, if, while, and so on.
These two combinations are used together to save you a lot of time when you debug. For defensive programming, it is necessary to insert them before writing the first line of specific code. Ask yourself, how many times can you write the code at once? Most code, before committing, usually undergoes a process of repeated debugging and modification. Instead of introducing these two configurations at the end of the day, it's better to leave the debug room at the start. After the code is finally ready to be submitted, it is not too late to consider whether to keep them.
3. Take the Shellcheck
OK, now I have three lines (boilerplate) code, the specific business logic does not write a line. Is it time to start writing?
Wait! 工欲善其事, its prerequisite. This time, I'll introduce a shell scripting artifact: Shellcheck
Ashamed to say that, although several years of shell script, some of the syntax I still do not remember. At this time will rely on shellcheck pointing. In addition to reminding grammatical problems, Shellcheck can also check out bad code that is common to shell scripting. Originally my n suggestions inside, there are a few are about these bad code, but considering that Shellcheck can dig out these problems, so reluctantly they are removed out. There is no doubt that using Shellcheck has made a huge leap for my shell writing skills.
The so-called "standing on the Shoulders of giants", although we recruit eggs, the skills are not as strong as veterans, but we can catch each other on the equipment Ah! A hands-on installation, you can meet a persuasive "teacher", why not?
By the way, Shellcheck was actually written in Haskell. Who says Haskell can only be used to install force?
4. Variable expansion
In a shell script, you can occasionally see this approach: Echo $xxx | Awk/sed/grep/cut ..... It looks like a big picture, but it just wants to change the value of a variable. Why use a sledgehammer to kill a chicken? Bash's built-in variable expansion mechanism is enough to meet your various needs! Still the old way, read the f**k manaul! Man bash and then search parameter expansion, here's what you want.
5. Note that the local
As the code writes more and more, you begin to refine the repetitive logic into functions. It's possible you'll fall into a hole in bash. In bash, if you don't add a local qualifier, the variables are global by default. Variable Default global-this is similar to JS and Lua; but relatively few bash tutorials tell you the truth from the start. In the top-level scope, it doesn't matter whether it is a global variable. But in a function, declaring a global variable can contaminate other scopes (especially if you don't notice it at all). So, for variables declared within a function, be sure to remember to add the local qualifier.
6. Trap Signal
If you've written a slightly more complex program running in the background, you should know what "signal" is in the POSIX standard. If you don't know, just look at the next paragraph. Like other languages, the shell also supports processing signals. The trap Sighandler int can call the Sighandler function when SIGINT is received. How other signals are captured and so on.
But the main application of the trap is not which signal to capture. The trap command supports "capturing" many different processes--accurately, allowing users to inject function calls into specific processes. One of the most common is trap func exit and trap func ERR.
Trap Func exit allows functions to be called at the end of a script. Since the registered function can be invoked regardless of normal exit or exit, I use it to register the cleanup function in a scenario where a cleanup function needs to be invoked, rather than simply calling the cleanup function at the end of the script.
Trap Func ERR allows a function to be invoked when a run error occurs. A common technique is to use the global variable error to store the error message and then complete the corresponding error report based on the stored value in the registered function. It can sometimes work wonders to focus the original fragmented error-handling logic on one place. Remember, however, that when a program exits abnormally, it calls both the exit-registered function and the Err-registered function.
7. Before you leap
These are the specific recommendations, the remaining two comparative retreat.
The advice is called "reconsider". In fact, no matter what code to write, even if only a secondary script, must think twice, avoid carelessness. No, this is more to remember when writing scripts. Many times, after all, a complex script starts with a few lines of small commands. The person who started writing this script probably thought it was just a one-time task. There are some assumptions about external conditions in the code that may be normal at the time, but as the external environment changes, these are hidden reefs. To make matters worse, almost no one will test the script. Unless you run it, you don't know if it's going to work.
To slow down the decay rate of your script code, you need to identify which dependencies are dependent and which scripts are necessary to run correctly when you write. To have the appropriate abstraction, write the code that can be changed, and the sense of defensive programming, a moat to your code.
8. Avoid weaknesses
Sometimes, using a shell to write a script means that it is difficult to migrate, make it difficult to handle errors uniformly, and handle data easily.
Although the use of external commands can quickly and easily achieve a variety of complex functions, but as the reverse side of the coin, you have to rely on grep, SED, awk and other tools to glue them together.
If you have multiple platform-compatible requirements, be careful to avoid weird traps like BSD and GNU Coreutils,bash versions.
Lack of perfect data structures and consistent Api,shell scripts are not enough to handle complex logic.
Use the right tools to solve specific problems. Knowing when to use the shell and when to switch to another, more general scripting language (such as Ruby/python/perl) is also a knack for writing reliable shell scripts. If your task can be combined with common commands and only involves simple data, then the shell script is the right hammer. If your task contains more complex logic and the data structure is complex, then you need to write scripts in languages such as Ruby/python.
The above is a small set to introduce the shell script to write 8 reliable suggestions (worth collecting), hope to help everyone, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!