Lecture
In this lecture, we continue to learn bash . Today let's talk about combining commands in bash , about the construction of case and some other com *** oh. But first, about the case construction that was undeservedly forgotten in the last lecture.
case is more convenient to use for branching when the value needs to be checked for exact matching and it can take three or more values. Instead of case, one could use if , but such constructions look cumbersome and are not so convenient to “read” in scripts.
The general syntax of the case command is as follows:
For us, case is also important because it is contained in all scripts in the /etc/init.d/ directory. Letters, numbers, strings and patterns of the form [az] , [1-9] , as well as ? - one any character and * - any combination. Although the pattern in general syntax is indicated in parentheses, in practice it is allowed not to write the first bracket. Let's look at a practical example:
As a value, here we used construction $ 1 , which contains the first parameter passed to the script. In the last lecture, we said that parameters can be passed not only to functions, but also to the script. The value begins to be compared with the templates from top to bottom, and as soon as a match is found, a block of commands between the template and ;; . An example of the script:
one 2 3 four five 6 7 eight 9 ten | igor @ adm-ubuntu: ~ / linux $ ./case.sh a abcd igor @ adm-ubuntu: ~ / linux $ ./case.sh k This is the letter k igor @ adm-ubuntu: ~ / linux $ ./case.sh qq These are any two characters. igor @ adm-ubuntu: ~ / linux $ ./case.sh 1 This is the number 1 igor @ adm-ubuntu: ~ / linux $ ./case.sh start This word is stop or restart or start. |
The /etc/init.d/ directory contains Linux service control scripts. Using case , they implement a mechanism for processing parameters passed to a script: start , stop , restart , reload, and others. Below is a fragment of the /etc/init.d/reboot script:
one 2 3 four five 6 7 eight 9 ten eleven 12 13 14 15 sixteen | case "$ 1" in start) # No-op ;; restart | reload | force-reload) echo "Error: argument '$ 1' not supported"> & 2 exit 3 ;; stop) do_stop ;; *) echo "Usage: $ 0 start | stop"> & 2 exit 3 ;; esac |
You will find a similar case in every script in the /etc/init.d/ directory.
I have already said that if we write two keywords of any construction in one line of the script, they must be separated by a symbol ; . The semicolon is the simplest way to combine commands (keywords are also perceived by bash as commands). Commands recorded in this way will be executed sequentially, regardless of the result of the previous command. The examples below can be typed both in the command line and in the script.
one 2 3 four | igor @ adm-ubuntu: ~ / linux $ a = 127; echo $ a; b = 172; echo $ b; let c = $ a + $ b; echo $ c 127 172 299 |
As you can see from the example, there are 6 commands on one line that were executed sequentially.
To run the commands in parallel, use the ampersand already familiar to you. Such commands will be run in the background and will be executed in parallel.
one 2 3 four | igor @ adm-ubuntu: ~ $ sleep 10 & sleep 10 & echo Hello! [1] 8043 [2] 8044 Hello! |
Further more interesting designs. After its execution, any command returns the numeric result code of the command execution. If it is 0, it means com *** and it was successful, if this number is nonzero, it means com *** and ended with an error. You can build the execution of a sequence of commands given this point. To do this, the following elements exist: a double ampersand - && and a double “pipe” - || . If the commands are combined only through && , then each next com *** a will be executed only in case of successful completion of the previous command. As soon as any com *** and chains return a return code other than zero, the commands following it will not be executed. For example, use the com *** s am true (always returns 0) and false (always returns 1).
one 2 | igor @ ubuntu: ~ $ true && echo "1" && false && echo "2" one |
In the example, com *** and true returned 0 and the next com *** and echo “1 ″ was executed and also returned 0, after which com was performed *** and false , which returned 1 and the execution of commands stopped (com ** * and echo 2 is not executed).
Com *** a || works exactly the opposite. That is, the next com *** and will be executed only if the previous com *** a returned a nonzero return code (the rule is valid in this form if all the commands are combined only || ). If the com *** returned 0, then the execution of a further chain of commands is interrupted. If in the example above replace && with || , then only com *** and true will be executed, which will return 0 and further commands will not be executed. If we replace true with false , we get the same result:
one 2 | igor @ ubuntu: ~ $ false || echo "1" || false || echo "2" one |
Combining && and || You can build quite complex options for combining teams. But in this case it is necessary to understand more deeply how the execution of commands takes place with such a combination.
Consider two examples of combining commands and the result of their execution:
one 2 3 four five | igor @ ubuntu: ~ $ false || echo "1" || false || echo "2" one igor @ ubuntu: ~ $ false || echo "1" || false && echo "2" one 2 |
In the first version, com *** and false returns code 1, and the next com will be executed *** and echo “1 ″ , which returns execution code 0. And then the command chain is interrupted as described above. In the second case there should be the same situation, but com *** and echo “2 ″ is performed. The thing is that in fact there is a check of all join operators that participate in the chain. If a com *** a returned 1, and all subsequent union operators && , then it will not execute any com *** a. But if in the chain to meet the operator || , then someone *** and after it will be performed and the check will go on.
Let us consider this chain in more detail:
1) Executes the *** and false and returns the execution code 1
2) Next is the operator || , which means the next com *** will be executed
3) Run the com *** and echo “1 ″ and return code 0
4) Next is the operator || , which means the next com *** and will not be executed
5) The next statement is checked - this is the && operator, so the next comma *** a ( echo “2 ″ ) will be executed.
See some more examples:
one 2 | igor @ ubuntu: ~ $ true || echo "1" && false || echo "2" 2 |
one 2 3 | igor @ ubuntu: ~ $ true && echo "1" || false && echo "2" one 2 |
one 2 3 | igor @ adm-ubuntu: ~ / linux $ true || echo "1" || echo "2" || echo "3" || false && echo "4" && echo "5" || echo "6" four five |
Commands can be combined into blocks using parentheses:
one 2 3 four | igor @ adm-ubuntu: ~ / linux $ true || echo "1" && (echo "2"; echo "3" || echo "4") && echo "5" || echo "6" 2 3 five |
or curly:
one 2 3 four | igor @ adm-ubuntu: ~ / linux $ true || echo "1" && {echo "2"; echo "3" || echo "4"; } && echo "5" || echo "6" 2 3 five |
In the second case, braces must be between the spaces, and after the last command there should be a semicolon.
Differences between round braces and curly braces in that the commands in curly brackets are executed within the same process as the script, and the commands in parentheses are executed as if in its subprocess. Let's see an example script:
one 2 3 four | #! / bin / bash true && (echo a; sleep 1 && exit 0 || echo b) && echo c echo d echo e |
and the result of the execution:
one 2 3 four five | igor @ adm-ubuntu: ~ / linux $ ./script.sh a c d e |
And now the same example with curly braces:
one 2 3 four | #! / bin / bash true && {echo a; sleep 1 && exit 0 || echo b; } && echo c echo d echo e |
and the result of its implementation:
one 2 | igor @ adm-ubuntu: ~ / linux $ ./script.sh a |
In the first case, the *** and the exit interrupted the execution of commands located in parentheses, but not the script as a whole. In the second case, the whole script stops.
At the end of the lecture a few more teams.
If you need to run the executable file from the script, it is enough to write the file name (if it is located in the directory described in the PATH variable) or the full path to the file if it is located in a specific directory:
one | /home/igor/linux/testscript.sh |
In this case, the file testscript.sh will be launched, and the execution of the current script will be suspended and resumed after the completion of the work of the called script. If it is necessary that when the new script or program is called, the current script terminates, then it must be called using the exec command.
one 2 3 four | ... exec /home/igor/linux/testscript.sh echo "1" echo "2" |
With this option, the echo 1 and echo 2 commands will not be executed, since after exec /home/igor/linux/testscript.sh the script will finish its work.
Also, the work of the script can be interrupted anywhere in the *** *** th exit . It is advisable to specify the result code of the script. For example, exit 0 .
Comments
To leave a comment
LINUX operating system
Terms: LINUX operating system