Basic Scripting
In this chapter, we will discuss how the tools you have learned so far can be turned into reusable scripts.
Навигация по статье:
1.1 Shell Scripts in a Nutshell
A shell script is a file of executable commands that has been stored in a text file. When the file is run, each command is executed. Shell scripts have access to all the commands of the shell, including logic. A script can therefore test for the presence of a file or look for particular output and change its behavior accordingly. You can build scripts to automate repetitive parts of your work, which frees your time and ensures consistency each time you use the script. For instance, if you run the same five commands every day, you can turn them into a shell script that reduces your work to one command.
A script can be as simple as one command:
The script, test.sh , consists of just one line that prints the string Hello, World! to the console.
Running a script can be done either by passing it as an argument to your shell or by running it directly:
In the example above, first, the script is run as an argument to the shell. Next, the script is run directly from the shell. It is rare to have the current directory in the binary search path $PATH so the name is prefixed with ./ to indicate it should be run out of the current directory.
The error Permission denied means that the script has not been marked as executable. A quick chmod later and the script works. chmod is used to change the permissions of a file, which will be explained in detail in a later chapter.
There are various shells with their own language syntax. Therefore, more complicated scripts will indicate a particular shell by specifying the absolute path to the interpreter as the first line, prefixed by #! as shown:
The two characters, #! are traditionally called the hash and the bang respectively, which leads to the shortened form of “shebang” when they’re used at the beginning of a script.
Incidentally, the shebang (or crunchbang) is used for traditional shell scripts and other text-based languages like Perl, Ruby, and Python. Any text file marked as executable will be run under the interpreter specified in the first line as long as the script is run directly. If the script is invoked directly as an argument to an interpreter, such as sh script or bash script , the given shell will be used no matter what’s in the shebang line.
1.2 Editing Shell Scripts
UNIX has many text editors, the merits of one over the other are often hotly debated. Two are specifically mentioned in the LPI Essentials syllabus: The GNU nano editor is a very simple editor well suited to editing small text files. The Visual Editor, vi , or its newer version, VI improved ( vim ), is a remarkably powerful editor but has a steep learning curve. We’ll focus on nano .
Type nano test.sh and you’ll see a screen similar to this:
The nano editor has few features to get you on your way. You simply type with your keyboard, using the arrow keys to move around and the delete/backspace button to delete text. Along the bottom of the screen you can see some commands available to you, which are context sensitive and change depending on what you’re doing. If you’re directly on the Linux machine itself, as opposed to connecting over the network, you can also use the mouse to move the cursor and highlight text.
To get familiar with the editor, start typing out a simple shell script while inside nano :
Note that the bottom-left option is ^X Exit which means “press control and X to exit”. Press Ctrl and X together and the bottom will change:
At this point, you can exit the program without saving by pressing the N key, or save first by pressing Y to save. The default is to save the file with the current file name. You can press the Enter key to save and exit.
You will be back at the shell prompt after saving. Return to the editor. This time press Ctrl and O together to save your work without exiting the editor. The prompts are largely the same, except that you’re back in the editor.
This time use the arrow keys to move your cursor to the line that has «The time is” . Press Control and K twice to cut the last two lines to the copy buffer. Move your cursor to the remaining line and press Control and U once to paste the copy buffer to the current position. This makes the script echo the current time before greeting you and saved you needing to re-type the lines.
1.3 Scripting Basics
You got your first taste of scripting earlier in this chapter where we introduced a very basic script that ran a single command. The script started with the shebang line, telling Linux that /bin/bash (which is Bash) is to be used to execute the script.
- Variables, which hold temporary information in the script
- Conditionals, which let you do different things based on tests you write
- Loops, which let you do the same thing over and over
1.3.1 Variables
Variables are a key part of any programming language. A very simple use of variables is shown here:
After the shebang line is a directive to assign some text to a variable. The variable name is ANIMAL and the equals sign assigns the string penguin . Think of a variable like a box in which you can store things. After executing this line, the box called ANIMAL contains the word penguin .
It is important that there are no spaces between the name of the variable, the equals sign, and the item to be assigned to the variable. If you have a space there, you will get an odd error such as “ command not found ”. Capitalizing the name of the variable is not necessary but it is a useful convention to separate variables from commands to be executed.
Next, the script echos a string to the console. The string contains the name of the variable preceded by a dollar sign. When the interpreter sees that dollar sign it recognizes that it will be substituting the contents of the variable, which is called interpolation . The output of the script is then My favorite animal is a penguin .
So remember this: To assign to a variable, just use the name of the variable. To access the contents of the variable, prefix it with a dollar sign. Here, we show a variable being assigned the contents of another variable!
ANIMAL contains the string penguin (as there are no spaces, the alternative syntax without using quotes is shown). SOMETHING is then assigned the contents of ANIMAL (because ANIMAL has the dollar sign in front of it).
If you wanted, you could assign an interpolated string to a variable. This is quite common in larger scripts, as you can build up a larger command and execute it!
Another way to assign to a variable is to use the output of another command as the contents of the variable by enclosing the command in back ticks:
This pattern is often used to process text. You might take text from one variable or an input file and pass it through another command like sed or awk to extract certain parts and keep the result in a variable.
It is possible to get input from the user of your script and assign it to a variable through the read command:
The read command can accept a string right from the keyboard or as part of command redirection like you learned in the last chapter.
There are some special variables in addition to the ones you set. You can pass arguments to your script:
A dollar sign followed by a number N corresponds to the Nth argument passed to the script. If you call the example above with ./test.sh the output will be Hello Linux . The $0 variable contains the name of the script itself.
After a program runs, be it a binary or a script, it returns an exit code which is an integer between 0 and 255. You can test this through the $? variable to see if the previous command completed successfully.
The grep command was used to look for a string within a file with the –q flag, which means “quiet”. The grep , while running in quiet mode, returns 0 if the string was found and 1 otherwise. This information can be used in a conditional to perform an action based on the output of another command.
Likewise you can set the exit code of your own script with the exit command:
The example above shows a comment # . Anything after the hash mark is ignored which can be used to help the programmer leave notes. The exit 1 returns exit code 1 to the caller. This even works in the shell, if you run this script from the command line and then type echo $? you will see it returns 1 .
By convention, an exit code of 0 means “everything is OK”. Any exit codes greater than 0 mean some kind of error happened, which is specific to the program. Above you saw that grep uses 1 to mean the string was not found.
1.3.2 Conditionals
Now that you can look at and set variables, it is time to make your script do different functions based on tests, called branching . The if statement is the basic operator to implement branching.
A basic if statement looks like this:
The next example will run “somecommand” (actually, everything up to the semicolon) and if the exit code is 0 then the contents up until the closing fi will be run. Using what you know about grep , you can now write a script that does different things based on the presence of a string in the password file:
From previous examples, you might remember that the exit code of grep is 0 if the string is found. The example above uses this in one line to print a message if root is in the password file or a different message if it isn’t. The difference here is that instead of an fi to close off the if block, there’s an else . This lets you do one action if the condition is true, and another if the condition is false. The else block must still be closed with the fi keyword.
Other common tasks are to look for the presence of a file or directory and to compare strings and numbers. You might initialize a log file if it doesn’t exist, or compare the number of lines in a file to the last time you ran it. The if command is clearly the one to help here, but what command do you use to make the comparison?
It is important to note that test looks at integer and string comparisons differently. 01 and 1 are the same by numeric comparison, but not by string comparison. You must always be careful to remember what kind of input you expect.
There are many more tests, such as –gt for greater than, ways to test if one file is newer than the other, and many more. Consult the test man page for more.
test is fairly verbose for a command that gets used so frequently, so there is an alias for it called [ (left square bracket). If you enclose your conditions in square brackets, it’s the same as running test . So, these statements are identical.
While the latter form is most often used, it is important to understand that the square bracket is a command on its own that operates similarly to test except that it requires the closing square bracket.
The if statement has a final form that lets you do multiple comparisons at one time using elif (short for else if ).
The code above compares the first argument passed to the script. If it is hello , the first block is executed. If not, the script checks to see if it is goodbye and echos a different message if so. Otherwise, a third message is sent. Note that the $1 variable is quoted and the string comparison operator is used instead of the numeric version ( -eq ).
The if / elif / else tests can become quite verbose and complicated. The case statement provides a different way of making multiple tests easier.
The case statement starts off with a description of the expression being tested: case EXPRESSION in . The expression here is the quoted $1 .
Next, each set of tests are executed as a pattern match terminated by a closing parenthesis. The previous example first looks for hello or hi ; multiple options are separated by the vertical bar | which is an OR operator in many programming languages. Following that are the commands to be executed if the pattern returns true, which are terminated by two semicolons. The pattern repeats.
The * pattern is the same as an else because it matches anything. The behavior of the case statement is similar to the if / elif / else statement in that processing stops after the first match. If none of the other options matched the * ensures that the last one will match.
With a solid understanding of conditionals you can have your scripts take actions only if necessary.
1.3.3 Loops
Loops allow code to be executed repeatedly. They can be useful in numerous situations, such as when you want to run the same commands over each file in a directory, or repeat some action 100 times. There are two main loops in shell scripts: the for loop and the while loop.
for loops are used when you have a finite collection over which you want to iterate, such as a list of files, or a list of server names:
The script first sets a variable containing a space separated list of server names. The for statement then loops over the list of servers, each time it sets the S variable to the current server name. The choice of S was arbitrary, but note that the S has no dollar sign but the $SERVERS does, showing that $SERVERS will be expanded to the list of servers. The list does not have to be a variable. This example shows two more ways to pass a list.
The first loop is functionally the same as the previous example, except that the list is passed to the for loop directly instead of using a variable. Using a variable helps the clarity of the script as someone can easily make changes to the variable rather than looking at a loop.
The second loop uses a * which is a file glob . This gets expanded by the shell to all the files in the current directory.
The other type of loop, a while loop, operates on a list of unknown size. Its job is to keep running and on each iteration perform a test to see if it should run another time. You can think of it as “while some condition is true, do stuff.”
The example above shows a while loop that counts from 0 to 9. A counter variable, i , is initialized to 0 . Then a while loop is run with the test being “is $i less than 10 ?” Note that the while loop uses the same notation as an if statement!
Within the while loop the current value of i is echoed and then 1 is added to it through the $(( arithmetic )) command and assigned back into i . Once i becomes 10 the while statement returns false and processing continues after the loop.
Введение в Bash Shell
Всем привет. Это перевод из книги по подготовке к экзамену RedHat RHCE. На мой взгляд очень доступно рассказывается об основах bash.
Сценарии оболочки — наука сама по себе. Не вдаваясь в подробности всего, что происходит «под капотом», вы узнаете, как применять базовые элементы для написания собственных скриптов, и анализировать, что происходит в сторонних сценариях оболочки.
Понимание основных элементов сценариев оболочки
По сути, сценарий оболочки представляет собой список команд, которые выполняются последовательно, а также некоторую логику, позволяющую выполнять код только при определённых условиях.
Чтобы понять сложные сценарии оболочки, рекомендуется начать с базовых сценариев.
Ниже показан очень простой скрипт:
Здесь содержатся несколько элементов, которые должны использоваться во всех скриптах. Для начала, есть shebang — это строка #!/bin/bash. Когда скрипт запускается из родительской оболочки, он открывает подоболочку, в которой и выполняются команды, указанные в скрипте.
Эти команды могут быть интерпретированы различными способами. Для того, чтобы понять, как именно они должны интерпретироваться, используется shebang. В примере выше shebang ясно даёт понять, что скрипт должен выполняться оболочкой bash.
Также могут быть указаны другие оболочки. Например, если ваш скрипт содержит код на языке Perl, shebang должен быть #!/usr/bin/perl. Начинать сценарий с shebang является хорошей практикой; если он опущен, код сценария будет выполняться такой же оболочкой, которая используется для запуска скрипта.
Сразу после shebang расположена часть, объясняющая, о чем сценарий. Несколько строк комментариев в начале каждого сценария — хорошая идея. В коротком скрипте часто очевидно, что он делает, но когда сценарий становится длиннее, и по мере того, как всё больше людей вовлекаются в его написание и поддержку, становится менее понятно, что авторы намереваются сделать.
Чтобы избежать такой ситуации, убедитесь, что вы добавили строки комментариев, начиная каждую символом #. Комментарии могут быть не только в первых строках, но и в начале каждого подраздела сценария. Это наверняка поможет, если вы прочитаете свой скрипт через несколько месяцев!
Вы также можете комментировать не только подразделы, но и отдельные строки.
Независимо от того, в какой позиции он используется, всё от символа # и до конца строки является комментарием.
После блока комментариев расположено тело сценария. В вышеуказанном примере это несколько команд, выполняющихся последовательно. Тело сценария оболочки может увеличиваться по мере его развития.
В конце скрипта я включил инструкцию exit 0. Оператор выхода сообщает родительской оболочке, был ли сценарий успешным. Состояние выхода последней команды в сценарии является состоянием выхода самого сценария, если только команда exit 0 не используется в конце сценария.
Полезно знать, что вы можете работать с exit, чтобы сообщить родительской оболочке, как все прошло.
После создания сценария убедитесь, что он может быть выполнен. Самый распространённый способ сделать это — применить к нему бит выполнения. Итак, если имя файла скрипта — hello, используйте команду chmod +x ./hello для того, чтобы сделать его исполняемым.
Сценарий также может быть выполнен в качестве аргумента команды bash. В этом случае введите bash ./hello для запуска скрипта hello. Если сценарий запускается как аргумент команды bash, файл скрипта не обязательно должен быть исполняемым.
По сути, вы можете хранить скрипт в любом месте, но если вы собираетесь хранить его в каталоге, который не включён в переменную $PATH, вам нужно выполнить его с ./ перед именем скрипта.
Введите ./hello для того, чтобы запустить сценарий, или поместите его в стандартный каталог, который включён в переменную $PATH, например, /usr/local/bin.
Также вы можете разместить сценарий в каталоге /bin, после чего в любом месте файловой системы просто ввести имя файла, и сценарий выполнится.
Командой vi /bin/datetime создадим в каталоге /bin файл с именем datetime. В созданный файл вставим это содержимое:
Сохранив файл, введите chmod +x /bin/datetime, чтобы дать файлу права на выполнение. Перейдите, к примеру, в домашний каталог с помощью команды cd
и просто введите datetime.
Перейдите, к примеру, в домашний каталог cd
и просто введите datetime.
Использование переменных и входных данных
bash-скрипты — это гораздо больше, чем просто список команд, которые выполняются последовательно. Одна из приятных сторон скриптов заключается в том, что они могут работать с переменными и входными данными, чтобы сделать скрипт гибким. В этом разделе вы узнаете, как с ними работать.
Использование позиционных параметров
При запуске скрипта можно использовать аргументы. Аргумент — это всё, что вы помещаете за командой сценария. Аргументы могут быть использованы для того, чтобы сделать скрипт более гибким. Возьмём команду useradd lisa. В этом примере команда — это useradd, а её аргумент — lisa — указывает, что нужно сделать.
В результате выполнения такой команды должен быть создан пользователь с именем lisa.
В тексте сценария первый аргумент обозначается $1, второй аргумент — $2 и т. д. Листинг 1 показывает, как можно использовать аргументы. Попробуйте запустить этот код, указав в качестве параметров любые имена пользователей.
Под параметрами подразумевается ввод данных перед запуском скрипта. В данном случае в качестве параметров после имени скрипта argument я указал lisa, lori и bob:
Если вы попытались запустить пример кода, то могли заметить, что его содержимое не идеально. Если вы используете три аргумента при выполнении скрипта из листинга 1, он будет работать отлично. Если используете только два аргумента, третий выводится без значения $3.
Если же используете четыре аргумента, четвёртое значение (которое будет храниться в $4) никогда не отобразится. Итак, если вы хотите использовать аргументы, вам лучше использовать более гибкий подход.
В Листинге 2 представлены два новых элемента, которые относятся к аргументам:
- $# — это счетчик, который показывает, сколько аргументов было использовано при запуске скрипта.
- $@ — список всех аргументов, которые использовались при запуске скрипта.
Итак, пока есть аргументы, тело сценария выполняется.
Тело цикла for всегда начинается с do и закрывается done, а между этими двумя ключевыми словами перечисляются команды, которые необходимо выполнить. Таким образом, пример сценария будет использовать echo для отображения значения каждого аргумента и останавливаться, когда больше нет доступных аргументов.
Давайте попробуем воспользоваться скриптом из листинга 2 в этом примере:
- Введите vi argument, чтобы создать файл argument и скопируйте содержимое из скрипта листинга 2 в этот файл.
- Сохраните файл и сделайте его исполняемым.
- Запустите команду ./argument a b c. Вы увидите, что отобразятся три строки.
- Запустите команду ./argument a b c d e f. Вы увидите, что помимо a b c отобразятся и d e f.
Переменные
Переменная — это метка, которая используется для обозначения определённого места в памяти, которое содержит определённое значение. Переменные могут быть определены статически с помощью NAME=value или динамическим способом. Существует два решения для динамического определения переменной:
- Используйте ключевое слово read в скрипте, чтобы запросить данные у пользователя, запускающего скрипт.
- Используйте подстановку команд, чтобы использовать результат команды и назначить его переменной. Например, команда date +%d-%m-%y показывает текущую дату в формате день-месяц-год. Чтобы сделать это в сценарии, вы можете использовать TODAY=$(date +%d-%m-%y). Для подстановки команд вам просто нужно поместить команду, результат которой вы хотите использовать, между скобками.
Листинг 3. Пример скрипта, использующего команду read
В сценарии листинга 3 оператор if… then… else… fi используется для проверки существования аргумента $1. Это делается с помощью test (test — это отдельная команда). Команда test может быть написана двумя способами*: test или [… ]. В примере строка if [ -z $1 ] . выполняется, чтобы увидеть тест (проверку) -z $1.
* — на самом деле тремя источник (прим. переводчика)
-z test проверяет, существует или нет $1. Иначе говоря, строка if [ -z $1 ] проверяет, является ли $1 пустым, что означает, что при запуске этого сценария не было предоставлено никаких аргументов. Если это так, команды после оператора then выполняются.
Обратите внимание, что при написании команды test с квадратными скобками важно использовать пробелы после открывающей скобки и перед закрывающей скобкой, без пробелов команда не будет работать.
Обратите внимание, что оператор then следует сразу за test. Это возможно, потому что используется точка с запятой (;). Точка с запятой является разделителем команд и может заменить новую строку в скрипте.
В операторе then выполняются две команды: команда echo, которая отображает сообщение на экране, и команда read.
Команда read останавливает сценарий, чтобы пользовательский ввод мог быть обработан и сохранен в переменной TEXT. Поэтому read TEXT помещает все введённые пользователем данные в переменную TEXT, которая будет использоваться позже в скрипте.
Следующая часть представлена оператором else. Команды после оператора else выполняются во всех других случаях, что в данном случае означает «иначе, если аргумент был предоставлен». Если это так, то определяется переменная TEXT и ей присваивается текущее значение $1.
Обратите внимание, как определяется переменная: непосредственно после имени переменной стоит знак =, за которым следует $1. Обратите внимание, что вы никогда не должны использовать пробелы при определении переменных.
Затем условия if замыкается с помощью оператора fi. После завершения условия if вы точно знаете, что переменная TEXT определена и имеет значение. Предпоследняя строка скрипта считывает значение переменной TEXT и отображает это значение в STDOUT с помощью команды echo. Обратите внимание, что для запроса текущего значения переменной ссылается на имя переменной, начиная со знака $ перед ним.
Вы можете попрактиковаться на этом примере при работе с вводом.
- Откройте редактор и создайте файл с именем text. Введите содержимое кода из листинга 3 в этот файл.
- Запишите файл на диск и выполните chmod +x text, чтобы сделать его исполняемым.
- Запустите скрипт, выполнив ./text и без дополнительных аргументов. Вы увидите, что он запрашивает ввод.
- Запустите скрипт, используя «hello» в качестве аргумента (./text hello). Результат отобразит «you have entered the text hello» в STDOUT.
Использование условий и циклов
Как вы уже видели, в скрипте могут использоваться условные операторы. Эти условные операторы выполняются только в том случае, если определённое условие выполняется.
В bash есть несколько условных операторов и циклов, которые часто используются.
- if… then… else — используется для выполнения кода, если определенное условие выполняется
- for — используется для выполнения команд для диапазона значений
- while — используется для выполнения кода, если выполняется определенное условие
- before — используется для выполнения кода, пока не выполнено определенное условие
- case — используется для оценки ограниченного количества конкретных значений
if then else
Основная конструкция if есть if… then… fi.
Она сравнивает одно условие, как показано в следующем примере:
В листинге 3 вы увидели, как можно оценить два условия, включая else в выражении. В листинге 4 показано, как можно оценить несколько условий от if до else. Это полезно, если нужно проверить много разных значений.
Обратите внимание, что в этом примере также используются несколько команд test.
Листинг 4. Пример с if then else
Вместо написания полных операторов if… then вы можете использовать логические операторы || а также &&. || является логическим «ИЛИ» и выполнит вторую часть оператора, только если первая часть не верна; && является логическим «И» и выполнит вторую часть оператора только в том случае, если первая часть верна.
Рассмотрим эти две строки:
В первом примере выполняется проверка, чтобы увидеть, пуст ли $1. Если эта проверка верна (что, в основном, означает, что команда завершается с кодом выхода 0), выполняется вторая команда.
Во втором примере команда ping используется для проверки доступности хоста.
В этом примере используется логическое «ИЛИ» для вывода текста «node is not available» в случае неудачной команды ping.
Вы обнаружите, что часто вместо условного оператора if будут использоваться && и ||. В упражнении ниже вы можете попрактиковаться в использовании условных операторов, используя либо if… then… else, либо && и ||.
Упражнение. Использование if… then… else
В этом упражнении вы поработаете над сценарием, который проверяет что является файлом, а что каталогом.
- Запустите редактор и создайте скрипт с именем filechk.
- Скопируйте содержимое из листинга 4 в этот скрипт.
- Запустите с ним пару тестов, такие как ./filechk /etc/hosts, ./filechck /usr, ./filechk non-existing-file.
Цикл for
Цикл for представляет собой отличное решение для обработки диапазонов данных. В листинге 5 вы можете увидеть первый пример с for, где диапазон определяется и обрабатывается, пока в этом диапазоне есть необработанные значения.
Цикл for всегда начинается с ключевого слова for, за которым следует условие, которое необходимо проверить. Затем следует ключевое слово do, за которым следуют команды, которые должны быть выполнены, если условие истинно, завершается цикл с помощью ключевого слова done.
В примере, приведённом в листинге 5, вы можете увидеть, что условие представляет собой диапазон чисел в круглых скобках, назначенных переменной COUNTER.
Маленькое пояснение
Внутри ((… )) вычисляются арифметические выражения и возвращается их результат. Например, в простейшем случае, конструкция a=$(( 5 + 3 )) присвоит переменной «a» значение выражения «5 + 3», или 8. Кроме того, двойные круглые скобки позволяют работать с переменными в стиле языка C.
Сначала переменная инициализируется значением 100, и до тех пор, пока значение больше 1, в каждой итерации вычитается 1. Пока условие истинно, значение переменной $COUNTER отображается с использованием команды echo.
В листинге 6 вы можете увидеть один из моих любимых однострочников с for. Диапазон определяется на этот раз как последовательность чисел, начиная со 100 и доходя до 104.
Обратите внимание, как определяется диапазон: сначала вы указываете первое число, затем две точки и указываете последнее число в диапазоне. При этом с for i in для каждого из этих номеров присваивается переменная i. Каждое из этих чисел присваивается переменной i и затем выполняется команда ping, где опция -c 1 гарантирует, что отправляется только один запрос.
Результат выполнения команды ping не учитывается, поэтому её вывод перенаправляется в /dev/null. На основании состояния выхода команды ping выполняется часть выражения за &&. Таким образом, если хост доступен, отображается строка, указывающая, что он работает.
Понимание while и until
Сценарий в листинге 7 состоит из двух частей. Во-первых, есть цикл while. Во-вторых, есть всё, что нужно выполнить, когда цикл while больше не оценивается как true.
Ядром цикла while является команда ps, которая имеет значение $1.
Обратите внимание на использование grep -v grep, который исключает строки, содержащие команду grep, из результата. Помните, что команда ps будет включать в себя все запущенные процессы, включая команду grep, которой передаётся вывод команды ps. Это может привести к ложному положительному совпадению.
Вывод команды ps aux перенаправляются в /dev/tty11. Это позволяет позже прочитать результаты из tty11, если это необходимо, но они не отображаются по умолчанию.
После операторов while следуют команды, которые необходимо выполнить, если проверяемое условие истинно. В данном случае это команда sleep 5, которая приостанавливает выполнение скрипта на 5 секунд.
Пока условие оператора while истинно, цикл продолжает выполняться. Если же условие ложно (что в данном случае означает, что процесс больше не доступен), то цикл останавливается и могут выполняться команды, следующие за ним.
Вам должны быть знакомы все эти команды, кроме последней. В строке mail -s “process $1 has stopped” root < . сообщение отправляется пользователю root с использованием внутренней почтовой системы, которая по умолчанию работает на Linux*. Команда mail принимает в качестве первого аргумента тему сообщения, указанную с помощью опции -s.
* — по крайней мере в CentOS по умолчанию работает. (при. переводчика)
Обратите внимание на < . в конце команды.
Обычно при использовании команды mail в интерактивном режиме открывается редактор, в котором можно написать тело сообщения. Этот редактор закрыт, предоставляя строку, которая имеет только точку. В этой команде точка предоставляется путём перенаправления STDIN. Это позволяет обрабатывать сообщение без каких-либо дополнительных требований к пользовательской активности.
Цикл while — это противоположность циклу until, пример которого приведён в листинге 8. until запускает итерацию, которая длится до тех пор, пока условие не станет истинным.
В листинге 8 он используется для фильтрации выходных данных команды users по вхождению $1, которое будет именем пользователя. Пока эта команда не верна, итерация продолжается. Когда имя пользователя найдено в выводе пользователей, итерация закрывается, и после цикла until выполняются остальные команды.
Понимание case
Последний из важных итерационных циклов — это case*. Оператор case используется для оценки ряда ожидаемых значений. В частности, инструкции case важны в сценариях запуска Linux, которые в предыдущих версиях использовались для запуска служб.
В операторе case вы определяете каждый ожидаемый вами конкретный аргумент, за которым следует команда, которую необходимо выполнить, если этот аргумент использовался.
В листинге 9 вы можете увидеть работу оператора case, который использовался в ранней версии для запуска практически любой службы.
case имеет несколько особенностей. Сначала идет строка — case последовательность in. Затем следует список всех возможных значений, которые необходимо оценить. Каждый элемент закрывается скобкой ).
Затем следует список команд, которые необходимо выполнить, если использовался конкретный аргумент. Список команд закрывается двойной точкой с запятой ;; может использоваться непосредственно после последней команды и может использоваться в отдельной строке.
Также обратите внимание, что *) относится ко всем другим параметрам, не указанным ранее. Это «всеохватывающий» оператор.
Цикл итераций case завершается оператором esac.
Обратите внимание, что последовательности в case выполняются по порядку. Когда будет выполнено первое совпадение, оператор case не будет ничего оценивать.
В рамках оценки могут использоваться шаблоны, подобные шаблону. Это показано в *) последовательности, которая соответствует всему. Но вы также можете использовать последовательности, такие как start|Start|START), чтобы соответствовать использованию другого case.
Отладка скриптов в Bash
Когда скрипт не делает того, что вы ожидаете, полезно выполнить некоторую отладку. Для начала, попробуйте выполнить его как аргумент команды bash -x. Это покажет вам построчно, что пытается сделать скрипт, а также конкретные ошибки, если он не работает как надо.
В листинге 10 показан пример использования bash -x, где сразу становится ясно, что команда grep не знает, что она должна делать, так как пропущен аргумент для её работы.
Shell script что это
A shell script is a text file containing shell commands. When such a file is used as the first non-option argument when invoking Bash, and neither the -c nor -s option is supplied (see Invoking Bash), Bash reads and executes commands from the file, then exits. This mode of operation creates a non-interactive shell. The shell first searches for the file in the current directory, and looks in the directories in $PATH if not found there.
When Bash runs a shell script, it sets the special parameter 0 to the name of the file, rather than the name of the shell, and the positional parameters are set to the remaining arguments, if any are given. If no additional arguments are supplied, the positional parameters are unset.
A shell script may be made executable by using the chmod command to turn on the execute bit. When Bash finds such a file while searching the $PATH for a command, it creates a new instance of itself to execute it. In other words, executing
is equivalent to executing
if filename is an executable shell script. This subshell reinitializes itself, so that the effect is as if a new shell had been invoked to interpret the script, with the exception that the locations of commands remembered by the parent (see the description of hash in Bourne Shell Builtins) are retained by the child.
Most versions of Unix make this a part of the operating system’s command execution mechanism. If the first line of a script begins with the two characters ‘ #! ’, the remainder of the line specifies an interpreter for the program and, depending on the operating system, one or more optional arguments for that interpreter. Thus, you can specify Bash, awk , Perl, or some other interpreter and write the rest of the script file in that language.
The arguments to the interpreter consist of one or more optional arguments following the interpreter name on the first line of the script file, followed by the name of the script file, followed by the rest of the arguments supplied to the script. The details of how the interpreter line is split into an interpreter name and a set of arguments vary across systems. Bash will perform this action on operating systems that do not handle it themselves. Note that some older versions of Unix limit the interpreter name and a single argument to a maximum of 32 characters, so it’s not portable to assume that using more than one argument will work.
Bash scripts often begin with #! /bin/bash (assuming that Bash has been installed in /bin ), since this ensures that Bash will be used to interpret the script, even if it is executed under another shell. It’s a common idiom to use env to find bash even if it’s been installed in another directory: #!/usr/bin/env bash will find the first occurrence of bash in $PATH .
Shell Script
A shell provides us with an interface to the Unix system. It gathers input and executes based on the input and provides output. Shell is an environment in which we can run our commands, programs, and shell scripts
Shells could be one of the following :
- The Bourne Shell
- The C Shell
- The Korn Shell
- The GNU Bourne-Again Shell
A shell script is a computer program designed to be run by the Unix/Linux shell.
A Bash script is a plain text file which contains a series of commands
Creating Script File and Steps to run
- Create empty file and save the file with .sh extension to make the file as script file.
- To check the file is executable. run ls -l command.
- drwr-r—rw the file has only read and write access.
- drwxr-xr-x the file has read, write and execution access.
- To make file to execute: run chmod -x <file name> command
- To run script add #!/path to shell e.g: #!/bin/sh as first line in the script file
- #! is called shebang and echo : is for printing the line
- variables are declared as <variable name>=<value>