Shell programming. Scripts


Language shell programming has several designs that will give flexibility to your programs:

  • Commentaries will allow you to describe the functions of the program;
  • "here document" allows you to include lines in the program's shell that will be redirected as input to some of the program's shell commands;
  • The exit command allows you to terminate the program at the desired point and use return codes;
  • designs for loop, while allow you to repeat a group of commands in a loop;
  • conditional commands if and case execute a group of commands if some condition is met;
  • The break command allows you to unconditionally exit a loop.

9.3.1. Comments

To place comments in the program, use the # sign. If a # sign appears after a command, the command itself is executed and the comment is ignored. Comment line format:

#comment

9.3.2. "Here document"

"Here document" allows you to place lines in a shell program that are redirected as command input in that program. This is one way to provide input for a command in a shell program without using a separate file. The entry consists of a redirection character<< и разделителя, который указывает начало и конец строк ввода. В качестве разделителя может использоваться один символ или строка символов. Чаще всего это знак!.

The command format is as follows:

Command<...input lines... delimiter

9.3.3. Using ed in a shell program

"Here document" suggests a way to use ed in a shell program. Let's say you want to create a shell program that will call the ed editor, make global changes to a file, write the changes to the file, and then exit ed. The following screen shows the contents of the ch.text program, which performs these tasks:

$ cat ch.text echo Type in the filename read file1 echo Type in the exact text to be changed. read old_text echo Type in the exact new text to replace the above. read new_text ed - $file1<

Note the - (minus) sign in the ed command. This option prevents the character counter from being printed on the screen. Also note the format of the ed command for global replacement:

G/$old_text/s//$new_text/g

The program uses 3 variables: file1, old_text, new_text. When run, this program uses the read command to obtain the values ​​of these variables. These variables contain the following information:
file - name of the file that will be edited;
old_text - text that will be changed;
new_text - new text.

Variables are introduced into the program, here document redirects the global replace command, the write command, and the end command to the ed command. Run the ch.text program. Get the following screen:

$ch.text Type in the filename memo Type in the exact text to be changed. Dear John: Type in the exact new text to replace the above. To what it may concern: $ cat memo To what it may concern: $

9.3.4. Completion codes

Most shell commands return codes that indicate whether the command completed successfully. If the return value is 0 (zero), then the command completed successfully. Return codes are not printed automatically, but can be obtained as the value of the special shell $? parameter.

9.3.4.1. Checking completion codes

After running a command interactively, you can see the exit code when you type:

Consider the following example:

$ cat hi This is file hi. $echo$? 0 $ cat hello cat: cannot open hello $ echo $? $2

In the first case, the file hi exists in your directory and you have read permission. Using the cat command you can print the contents of a file. The result of the cat command is the return code 0, which you will get by specifying the $? parameter. In the second case, the file either does not exist or you do not have read permission. The cat command prints a diagnostic message and returns code 2.

shell program exits normally when the last command in the file is executed. However, you can use the exit command to terminate the program. More importantly, you can use the exit command to obtain shell program return codes.

9.3.5. Cycles

The for and while loop statements allow you to execute a command or sequence of commands multiple times.

9.3.5.1. for statement

The for statement executes a sequence of commands for each element of the list. It has the format:

For variable in a_list_of_values do command_1 command_2 . . . last command done

For each iteration of the loop, the next element of the list is assigned to the variable given in the for statement. This variable can be referenced anywhere in commands within a do statement. When constructing each section of commands, you need to make sure that for each do there is a corresponding done at the end of the loop.

The variable can have any name. For example, if your variable is named var, then a reference to $var in the command list will make the value available. If the in operator is omitted, then the value for var will be the set of arguments given in the command and available in special parameter$*. The list of commands between the do and done keywords will be executed for each value.

When the commands are executed for the last element of the list, the program will execute the line below done.

9.3.5.2. while statement

Operator while loop uses 2 groups of commands. It will execute the sequence of commands in the second group (the do ... done list) until the last command in the first group (the while list) returns true, meaning that the expression after the do can be executed.

The general format of the while loop statement is:

While command_1 . . . last command do command_1 . . . last command done

For example, the enter.name program uses a while loop to enter a list of names into a file. The program consists of the following command lines:

$ cat enter.name while read x do echo $x>>xfile done $

After making some additions, we get the following program:

$ cat enter.name echo Please type in each person"s name and than a echo Please end the list of names with a<^d>while read x do echo $x>>xfile done echo xfile contains the following names: cat xfile $

Note that after the loop completes, the program executes the commands below done.

The first two echo commands use Special symbols, so you must use quotes to escape the special value. The following screen shows the output of enter.name:

$enter.name Please type in each person"s name and than a Please end the list of names with a<^d>Mary Lou Janice <^d>xfile contains the following names: Mary Lou Janice $

After the loop completes, the program will print out all the names contained in the xfile.

9.3.6. Using /dev/null

The file system has a file /dev/null where you can store unwanted output. For example, if you simply enter the who command, the system will answer who is working on the system. If you redirect the output of this command to /dev/null:

Who > /dev/null

then you won't get an answer.

9.3.7. Conditional statements

if...then statement

The if command tells the shell program to execute the sequence of commands after then if the last command in the if statement's list of commands completed successfully. If constructs end with the fi keyword.

The general format of the if construct is:

If command_1 . . . last command then command_1 . . . last command fi

For example, the search shell program demonstrates the use of the if ... then construct. The search program uses the grep command to search for a word in a file. If grep is successful, the program displays the word found. The screen will look like this:

$ cat search echo Type in the word and the file name. read word file if grep $word $file then echo $word is in $file fi $

This program displays the output of the grep command. If you want to store the system's response to the grep command in your program, use the /dev/null file, changing the if command line to the following:

If grep $word $file > /dev/null

Now run the search command. It will only respond with the message specified after the echo command.

The if ... then ... else construct can execute an alternative set of commands after the else if the if sequence is false. The format of this construct is as follows:

If command_1 . . . last command .linthen command_1 . . . last command else command_1 . . . last command fi

With this construct, you can improve the search program so that it will tell you both the word found and the word not found. In this case, the search program will look like this:

$ cat search echo Type in the word and the file name. read word file if grep $word $file > /dev/null then echo $word is in $file else echo $word is NOT in $file fi $

test command

The test command is used to organize a loop. It tests certain conditions for truth and is useful for organizing conditional structures. If the condition is true, the loop will continue. If the condition is false, the loop will end and the next command will be executed. Some examples of using the test command:

Test -r file true if the file exists and is readable; test -w file true if the file exists and is writable; test -x file true if the file exists and is executable; test -s file true if the file exists and has at least one character; test var1 -eq var2 true if var1 is equal to var2; test var1 -ne var2 true if var1 is not equal to var2.

Example. Let's create a shell program that moves all executable files from the current directory to your bin directory. To do this, we will use the test -x command to select executable files. The mv.file program will look like this:

$ cat mv.file echo type in the directory path read path for file do if test -x $file then mv $file $path/$file fi done $

The case ... esac construct allows you to select one of several patterns and then execute a list of commands for that pattern. The pattern expression must begin with the in keyword, and a right parenthesis must be placed after the last character of each pattern. The sequence of commands for each pattern ends with two characters;;. The case construct must be terminated with the esac keyword.

The general format of the case construct is:

Case word in pattern1) command line 1 . . . last command line ;;pattern2) command line 1 . . last command line ;;pattern3) command line 1 . . last command line ;; *)command line 1 . . last command line ;;esac

The case construct tries to find a word with the pattern pattern in the first pattern section. If the search is successful, the program executes the command lines after the first pattern until the corresponding characters;;.

If the first template is not found, then the transition to the second template is carried out. If any pattern is found, the program does not consider the remaining patterns, but moves on to the command following esac. The * is used as a pattern to search for any word and thus gives you a set of commands that will be executed if no other pattern is found. Therefore, the asterisk (*) pattern is placed as the last pattern in the case construct so that the other patterns are checked first. This will help you detect incorrect and unexpected input.

Templates can use metacharacters *, ?, . This provides program flexibility.

Let's look at an example. The set.term program sets the TERM variable according to the type of terminal you are using. The following command line is used:

TERM=terminal_name

The * template is the last one in the list of templates. It issues a warning message that there is no matching pattern for the specified terminal type and allows you to complete the case construct.

$ cat set.term echo If you have a TTY 4420 type in 4420 echo If you have a TTY 5410 type in 5410 echo If you have a TTY 5420 type in 5420 read term case term in 4420) TERM-T4 ;; 5410) TERM-T5 ;; 5420) TERM-T7 ;; *) echo not a correcr terminal type ;; esac export TERM echo end of programm $

9.3.8. Unconditional transfer of control

The break command unconditionally stops the execution of any loop in which it is encountered and transfers control to the command following the done, fi, or esac keywords.

In the previous example set.term program, you could use the break command instead of echo to exit the program, as in the following example:

$ cat set.term echo If you have a TTY 4420 type in 4420 echo If you have a TTY 5410 type in 5410 echo If you have a TTY 5420 type in 5420 read term case term in 4420) TERM-T4 ;; 5410) TERM-T5 ;; 5420) TERM-T7 ;; *) break ;; esac export TERM echo end of programm $

The continue command will cause the program to immediately move to the next iteration of the while or for loop without executing the remaining commands in the loop.

What is a shell and why is it needed?

Command shell in any unix-like systems, which includes GNU/Linux, is regular program, launched both in a text console (which is used less and less) and in a graphical environment - in the window of a terminal emulator, available on any Linux system.

Its task is simple and obvious: accept a line (or lines) of input, produce them parsing and, based on the results of this analysis, react accordingly - execute a command, run a program, display a diagnostic message, etc.

Almost all Linux distributions assign users the default shell to bash (Bourne Again SHell is another Bourne shell; Steve Bourne is the author of the first shell on Unix, sh). In fact, it has become an unofficial standard, and improvements to it functionality continues continuously. There are other command shells - tcsh ( C-shell version), ksh (Korn Shell), zsh, etc. – each has its own advantages and disadvantages, as well as its own fan groups. However, bash is more familiar to a wide range of users with different levels of experience, which is why I chose it. It is also worth noting that no matter what capabilities the various shells have, they are all compatible with their ideological progenitor - the Bourn Shell (sh). In other words, a script written for sh will work correctly in any modern shell (the reverse is generally not true).

Benefits of the Command Line

The question may arise: why bother with the command line if there are convenient and beautiful graphical interfaces? There are many reasons for this. Firstly, not all operations are more convenient or faster to perform using GUI. Second, every program follows the fundamental principle of Unix systems: do a well-defined job and do it well. In other words, you always understand what happens when you run a particular utility (if something is not entirely clear, you should refer to the man manual). Thirdly, by mastering commands, trying their combinations and combinations of their parameters, the user studies the system, gaining valuable practical experience. You get access to powerful tools such as pipelines that allow you to organize a chain of commands for processing data, I/O redirection tools, and you can also program directly from the command shell. Perhaps it’s worth dwelling on programming in more detail, especially since many system scripts in Linux (for example, startup scripts system services) are written for the shell.

Command shell as a programming language

So, the command shell can be considered as a programming language and as a software runtime at the same time. Of course, this language is not compiled, but interpreted. It allows the use of variables: system or own. The sequence of execution of program commands is changed using condition checking constructs and selecting the appropriate option: if-then-else and case. While, until, and for loops allow you to automate repetitive actions. It is possible to combine groups of commands into logical blocks. You can even write real functions that pass parameters to them. Thus, all the signs and characteristics of a full-fledged programming language are available. Let's try to get double benefit from this - along with learning the basics of programming, we will automate our daily work.

Hello, World! Simple backup system

About the need for regular Reserve copy Everyone knows the data, but users never have enough time for this boring operation. The solution is simple - organize automatic creation backup copies. This will be our first shell programming task.

#!/bin/bash # # Backup directories and files from the home directory # This batch script can be run automatically using cron # cd $HOME if [ ! -d archives ] then mkdir archives fi cur_date=`date +%Y%m%d%H%M` if [ $# -eq 0 ] ; then tar czf archive$(cur_date).tar.gz projects bin else tar czf archive$(cur_date).tar.gz $* fi if [ $? = 0 ] ; then mv archive$(cur_date).tar.gz $HOME/archives echo "$cur_date – Backup completed successfully." else echo "$cur_date - ERROR during backup." fi

Any command script (script is a script, as command shell programs are called) begins with an identifier line, in which the command interpreter is explicitly specified, indicating the full path to it. The full path is a sequential listing of all directories, starting from the root, that must be entered to get to the target file, and, of course, the name of this file. Recording the full path is extremely important to uniquely identify each file in the file system hierarchy.

Four lines of comments follow. Once the shell encounters the "#" character, it treats all subsequent characters as comments and completely ignores them until the end of the current line. Therefore, you can start a comment not from the very beginning of the line, but accompany it with some command.

After the comments there is an empty line. It means nothing to the command shell, and no action is taken. In scripts, blank lines are usually inserted to make the code easier to read.

We finally got to the first “real” team. It allows you to change the directory (Change Directory), i.e. move from the current directory to another one passed to the command as an argument. In most cases, the target directory is specified explicitly, for example, cd /tmp or cd projects, but in our case, the predefined system variable HOME is used - it contains the full path to the home directory of the current user under whose name the command script is being executed. This eliminates the need to make code changes every time we change users, because the command returns everyone to their personal directory. The dollar sign "$" in front of a variable name means that you need to extract the value contained in that variable and substitute it in place of its name on the command line. It should be especially noted that in command language letter case shells are important, i.e. HOME, Home and home are three different variables. By convention, uppercase letters denote the names of system variables: HOME, PATH, EDITOR, etc. This convention does not prevent users from creating their own variables with names from capital letters, but why complicate your life by violating generally accepted norms and rules? It is also not recommended to change the values ​​of system variables unless absolutely necessary. In general, we follow a simple rule: we use system variables for read-only purposes, and if we need our own, we write its name in lowercase letters.

Our first command could be written more briefly:

cd ~

Here the "~" symbol also means the current user's home directory. Veterans command line expressed even more succinctly:

CD

The idea is that when the cd command is given no argument, it changes to the home directory.

Next up is the classic software design for checking conditions and making the appropriate decision. The general scheme is this:

if<условие>then<одна или несколько команд>fi

The last word of the construct (if in reverse order) acts as a closing parenthesis, i.e. boundaries of the list of commands executed when the condition is true. The presence of fi is mandatory, even if there is only one team on the list.

To check a condition, as a rule, the test command or its alternative form of notation in square brackets is used. In other words, records

if [! -d archives ] if test ! -d archives

absolutely equivalent. I prefer square brackets, since they more clearly define the boundaries of the condition being tested. Both the right and left parentheses must be separated from the condition by spaces.

The criteria for checking the condition are determined by various flags. The test command recognizes a very large list of them. In our example, the -d flag is used, which allows us to check whether the name specified after the flag corresponds to an actual directory. The following flags are most often used when working with files:

F – whether a regular file with the given name exists;

R – whether the specified file has the right to read from it;

W – whether the specified file has the right to write to it;

X – whether the specified file has the right to execute it;

S – whether the specified file has a non-zero size.

In our case, the condition is preceded by Exclamation point, denoting the operation of logical negation, so the meaning of the condition being tested becomes completely opposite. Let's try to write down the meaning of these commands in ordinary Russian:

if [! -d archives ] If the archives directory (in the current directory) does not exist, then start executing the command block: mkdir archives create the archives directory (in the current directory) fi end executing the command block.

As you can see, everything turned out to be not so complicated. With a little practice, you can easily read and create similar designs yourself. The directory creation command is so obvious that no further explanation is required.

On the next line we create our own local variable, cur_date. In the vast majority of cases, variables are created by simply assigning a specific value, for example:

ten=10 string="This is a line of text"

But in our example, a little trick is used. Please note that after the equal sign - the assignment symbol - the command is written in back quotes. This form of notation allows you to assign to a variable not the string itself, but the result of its execution. Here is the output of the date command which returns current date and time in a format defined by a list of parameters:

%Y – current year in full form, i.e. of four digits (for example, 2009);

%m – number of the current month (for example, 09 – for September);

%d – current day number;

%H – current hour in 24-hour format;

%M – current minute.

Thus, if you run the command

cur_date=`date +%Y%m%d%H%M`

on the tenth of September 2009 at 22:45, the variable cur_date will be assigned the string value "200909102245". The purpose of this trick is to create a unique, non-repeating name for the archive file. If you intend to run several instances of the program within one minute, you can improve the uniqueness of the names by adding the current seconds. How? Study the date utility manual (man date) - there is nothing complicated about it.

Before we start creating an archive file, we need to determine which directories we will save in it. For greater flexibility, we can specify a set of directories to be archived by default, but provide the ability to replace this set with a list of directories passed as an argument to our command script. For this purpose, special command shell variables are used: $# – the number of parameters passed to the script and $* – all parameters passed, written in one line format.

if [ $# -eq 0 ] ; then

Checking the condition “if the number of passed parameters is zero”, then execute the following command. Note that keyword then can be written on the condition line, separating it from the conditional expression with a semicolon.

tar czf archive$(cur_date).tar.gz projects bin

The command to create an archive file and compress this file. The tar utility itself does not perform compression, but only collects everything specified files and directories into a single tar file. The first flag is intended for this - c (create). Compression performs external program– here it is gzip, called by the second flag - z. If you have the more efficient bzip2 compression program installed on your system, you can take advantage of it by modifying the command as follows:

tar cjf archive$(cur_date).tar.bz2 projects bin

The third flag f indicates that what follows is the name of the archive file, so it is always the last one in the list of flags. Note that when substituting, the variable name is enclosed in braces. This is done to explicitly highlight the variable on the line surrounding it, thereby eliminating many potential problems. Extensions archive file are not assigned automatically; you fill in everything you need yourself. I've specified projects and bin as the default directories to archive, but you can write down the names of your most valuable directories here.

The else keyword opens an alternative branch of execution. The commands of this block begin to work if the condition check returns the result “false” (in our example: “the number of parameters passed is non-zero,” i.e. the user specified directory names). In this case the command will look like this:

tar czf archive$(cur_date).tar.gz $*

Here the default directories are replaced by a directory name string accepted externally. It is possible to accept and process each external parameter separately, but it is more convenient for us to pass the entire string.

At the end of the program, another check is performed. In Unix environments, all commands return a completion status code. If the command was successful, it returns code 0, otherwise the exit code will be non-zero. To check the success of the previous archiving command, we will use another special variable $?, which always contains the value of the completion code of the most recent command. If in the variable $? contains 0, i.e. The backup file was successfully created, then we move it to the archive directory:

mv archive$(cur_date).tar.gz $HOME/archives

and display the corresponding message:

echo "$cur_date – Backup completed successfully."

If the check shows that the completion code of the archiving operation is not zero, then an error message is displayed:

echo "$cur_date - ERROR during backup."

This completes our command script.

To test the operation of our program, we need to save the source code described above in a file, for example, named bckp, and then, for convenience, make it executable:

chmod 750 bckp

and run:

./bckp

to create a backup of the default directories, and

./bckp docs progs works

to create a backup copy of the listed directories (specify the names of the directories that actually exist on your system, otherwise you will receive an error message).

You can place the bckp file in one of the directories specified in the system PATH variable. The most preferred locations are /usr/local/bin or $HOME/bin if you have them. After this you can run bckp as a system command.

How to automate scheduled backup operations

A few words about backup automation. For this purpose, the system cron scheduler is used, which reads work instructions from a special crontab file. To define such instructions, you need to create and edit your crontab file using the command:

crontab -e

Instructions are written in a strictly defined format (fields are separated by spaces):

minutes hours day_of_month month day_of_week command

One option for scheduling backup operations might look like this:

30 23 10,20,30 * * /usr/local/bin/bckp

This means that the backup script (you must provide the full path to this file) will run at 23:30 on the 10th, 20th and 30th of each month, regardless of the day of the week. (Asterisks indicate the entire permissible range of values, in this case: every month - in the 4th field, any day of the week - in the 5th field)

If you prefer to summarize your results by week, and your system runs 24/7, then it makes sense to schedule backups during off-peak hours:

0 5 * * 3.5 /usr/local/bin/bckp

Here backups will be created at 5:00 on Wednesdays and Fridays in each month (asterisk in the 4th field), regardless of the date (asterisk in the 3rd field).

You can read about all the intricacies of scheduling in the man 5 crontab manual.

Results and conclusions

The backup script discussed in this article has modest functional properties. But that was not his point the main task, but so that the reader understands what can be done on the command line, and not only copies and executes the proposed command file, but becomes interested in expanding its functions, and begins to explore the immense possibilities provided by command shells. And if someone, after reading this article, tries to improve the code given here, or writes own version, or implements his independent idea, then I will consider that the main goal has been achieved.

Resources for download

static.content.url=http://www.site/developerworks/js/artrating/

ArticleID=458335

ArticleTitle=Shell Programming Basics

MOSCOW 2007

Laboratory workshop on the course: “Operating systemRedHatLinux

Laboratory work No. 5

Programming inSHELL

Goal of the work : Based on previously acquired skills in working with the BASH command interpreter, master initial programming skills in the BASH command interpreter to create script files - SHELL scripts.

Theoretical information

Executing individual commands in the shell is not always an effective way to work with the SHELL shell. Quite often, you need to perform the same sequence of actions when working with the Linux operating system every month, every week, every day, and sometimes several times a day. For example, let's say you work for a company as a software tester (Test Manager). Every day you need to perform one set of actions in the Linux command shell, namely: mounting a CD-ROM device; copying all information from it to a folder, say, /opt/program on your hard drive; dismantling CD-ROM; reading the readme file from this folder; installing the program from hard drive from the /opt/program folder; creating a new report file in the /home/user/report_program directory and deleting the entire contents of the distribution from the hard drive. And this despite the fact that your main job is to test the software to identify bugs. The task at first glance is simple, but it is inconvenient to perform such actions several times a day, despite the fact that you are also doing other things. Or, for example, you work in a company as a system administrator and service about 50 computers. Every day you need to copy the same file to all computers with instructions for the current day from the director of the company for all subordinates. In addition, your tasks also include, at the end of the working day, saving all the data of each user on a common company server from the personal computers of subordinates. The task is also simple at first glance, but typing commands in a command interpreter for 50 computers will take a lot of time. What if, in addition, you make mistakes while typing, for example, due to fatigue? The data is very important for the director and its owner, and you cannot lose it. But these are still simple actions. Imagine that the names of report files, the names of data folders, and computer names will change every time? What to do then? There is only one way out - write script file , i.e. create text file, in which you need to describe the entire sequence of commands with paths, options, arguments, expressions, actions, and so on to execute a specific script. For example, data backup. After entering commands into a text script file, the file is made executable or its special command interpreter execution statements are executed. Using script files is especially effective if you very often need to execute a sequence of large number commands It is also an effective tool if the execution of subsequent commands depends on the results of previous commands. Using script files, you can also use arithmetic and logical expressions and create loops that repeatedly execute a group of Linux commands.

Creating script files. Scripting is a sequential set of commands, shell statements and some other symbols in a text file. Script files are also called scripts, and command interpreters are called SHELL. Due to the fact that today there are different command interpreters, writing a script file using additional symbols, for example, metasymbols, together with commands should not contradict the syntax rules of the selected command interpreter in which this script is supposed to be executed. The process of writing such files is called SHELL programming. Let's look at the programming process using the BASH interpreter as an example. Thus, the scripts and scripting rules in this lab may not be portable to other interpreters, such as the C Shell or TC Shell.

Subsequence #!. Writing any script begins with its belonging to one of the command interpreters. The first line of the script usually contains the sequence #! , which tells the system which interpreter should execute the commands in the given script. If the first character is a space, the script is considered to be written in BASH or PDKSH. If the script begins with only the # symbol, then TC Shell is required to execute it. If the # character is followed by a ! character, the kernel will launch the interpreter whose path is indicated later in this line. For example, for BASH the entry would be: #!/bin/sh . A space or a single # character at the beginning of a script is sufficient for the BASH Shell and TC Shell interpreters only if they will read their script. In order for one interpreter to recognize the scripts of another, it is necessary to include #! characters in the script. , followed by the path of the interpreting program. Then, when the script is called, the current interpreter will be terminated, a different type of script will be loaded instead, and then the script will be executed. It is recommended to always start all scripts with the sequence #! . Also, lines starting with the # symbol can be used to comment on user actions in the script. When the shell encounters a # symbol, it ignores this line. Each comment must end with a line ending character. The use of comments is a sign of good manners.

Extending and running scripts. Typically, script files have not only names, but also extensions. Most often, a combination of letters is used as extensions sh from Latin word shell. With this extension, without opening the file, it is immediately clear that this is a shell script, since again it is clear to us that the file with the extension . c most likely an input file for high-level languages ​​C and C++. After typing the contents of the file, the file is saved. There are two ways to run a file: either make it executable using the chmod command, or run it using special shell operators: sh and. Typically, users set the script file to octal values ​​of 750 or 550. In the following example, we will make the script.sh script executable using the chmod command and run it from the current directory in the background.

chmod u+x script.sh

./ script.sh &

Now let's return the previous attributes to the file and launch it for execution using the BASH statement.

chmod u-x script.sh

sh script.sh&

Team echo . Besides the list of standard Linux commands, the simplest thing you can use in a script is to display text comments to the user using the echo command. For example, this command can be used to invite a user to perform an action or used to greet the user. The following example uses echo to display a greeting.

echo "Good afternoon!"

Teamread . When you create scripts, you can also use variables and scripts written for other interpreters and commands. The read command serves as a command to prompt the user for input. It is combined with a hint to the user, which invites the user to enter the required information. Here's an example of using read.

echo "Enter your name: "

read your _ name

echo “ Kind day "your_name"!

This script is more complicated than the previous one. This uses the variable your_name , the value of which is then applied in conjunction with the text.

Using variables. Like programming languages, you can also use variables in the shell; you can assign values ​​to variables using the assignment operator equal to “=”. First, enter the name of the variable, then the “=” sign without a space, then the value of the variable without a space. The variable name can consist of any number of alphabetic characters, including the underscore character. The name can contain numbers, but must not begin with a number. All other characters (in particular, exclamation point, ampersand and space) should not be included in the name. Such symbols are reserved by the interpreter for special purposes. As a consequence, the name can only consist of one word, because when parsing commands, the interpreter treats the space as a delimiter between command names and arguments. The value of a variable can consist of any sequence of characters. In the following example, we will assign the value “www123yyy” to the variable “ppp”.

ppp =” www 123 yyy

If you are using a string value as a variable value, use double quotes. Once a value is assigned, you can use the variable name to refer to that value, such as using it as an argument to script commands. The value of a variable can be referenced by its name, which is preceded by the $ operator. The dollar sign is a special operator that uses the name of a variable to refer to its value, that is, to actually evaluate it. Now, using the familiar echo command and the “ppp” variable, you can display the value of this variable.

echo $ppp

www123yyy

Command line arguments. In a script, just like in Linux commands, you can use arguments. An argument in a script is indicated by the $ operator followed by a position number on the command line. The numbering of parameters starts with one and ends with nine. The first parameter is set to $1, the second to $2, etc. The $0 argument is reserved for the name of the shell script, which is the first word on the command line. By default, it is possible to set 9 variables from $1 to $9. If you enter multiple arguments, you can refer to each one separately by its number. The following example enters three arguments on the command line. Let's first create an arguments script with arguments, and then execute it.

Please note that if you need to use a multi-word argument(s), you must enclose the argument(s) in double quotes on the command line. Sometimes you need to specify the exact number of arguments in a script, this can be done using the $# argument. The $* option allows you to specify all arguments on the command line.

Variableexport. Sometimes, for different script files, you need to use a certain variable that has already been defined. Variables you define in the shell are local to it. In a sense, such a variable belongs to its interpreter. You cannot directly define a variable for another interpreter, but you can export a variable definition from one interpreter to another using the export command. The export command contains an instruction for the system, according to which a copy of this variable will be defined for each newly formed shell. Each new shell will have its own copy of the exported variable. In the following example, we will define the variable “rrr” and export it for other interpreters using the export command.

Arithmetic operations - commandlet . The let command is a BASH shell command that performs operations on arithmetic values. You can use this command to compare numeric values ​​or perform arithmetic operations on them, such as addition or multiplication. Command format: let value1 operator value2. Let's give an example.

$ let 2*5

10

Arithmetic expressions that use the let operator can also include assignment operators. The following example assigns the result of multiplying two numbers to the variable total.

$ let “total=2*5”

$ echo $total

10

$

Comparison operators are often used to compare numeric values ​​in control constructs such as loops and conditional branches. In the following example, the file1 script commands display the word "Hello!" four times. In this case, the let "ttt" operator is used to control the exit from the loop<= 4", а для увеличения переменной цикла again на единицу - оператор let "ttt = ttt + 1". Обратите внимание на то, что при изменении переменной again ее вычислять не требуется.

File1

ttt=l

while let "ttt<= 4"

do

echo $ttt Hello!

let "ttt = ttt + 1"

done

Executing the script:

$file1

Hello!

Hello!

Hello!

In addition, you can also use other arithmetic operators. Table 1 lists the Bash Shell arithmetic and comparison operators.

Table 1 - BASH shell statements

Arithmetic operators

Functions

Multiplication

Addition

Subtraction

Division with remainder

Comparison Operators

Functions

More than

Less than

Greater than or equal to

Less than or equal to

Equality in Expressions

Equality in the let command

Not equal

Logical AND

Logical OR

Logical NOT

Control structures. Control constructs are designed to control the execution of shell script commands. These constructs allow you to organize repeated execution of a certain sequence of commands or select commands to execute that are necessary in a particular situation. The control structure consists of two main components: check operations and commands. The result of a comparison (testing a condition) is returned as true or false, and then specific commands are executed based on the result. There are two types of control structures: cyclic (cycles) And conditional (uslovia). A cyclic construct is used to repeatedly execute commands, whereas a conditional construct is used to execute a sequence command., which satisfies certain conditions. The BASH shell interpreter allows you to use three looping constructs, while, for, and for-in, and two conditional constructs, if and case.

The while and if control constructs are general-purpose constructs that are commonly used to solve problems such as iterative calculations and testing various conditions. The control constructs case and for are focused on a narrower range of tasks. The case construct is a multivariate operator and is a special case of the if conditional operator. This design is often used when creating menus. The for construct is a loop that processes all the information once for each value included in the list until the end of the list is encountered.

In addition to comparing values ​​or variables, if and while control constructs can be used to test whether a Linux system command succeeded or failed. Recall that in Linux, every command executed returns an exit code. If the command was successful, its exit code is 0. If for some reason the command was not executed successfully, the exit code will be some positive value indicating the type of error. The if and while control constructs allow you to check whether the exit code was equal to 0 or some other value. If the exit code is zero, the command execution was successful and the if or while control construct will be completed.

Teamtest . You can compare values ​​not only using conditional control constructs, but also using the test command. When comparing two values, test returns 0 if the comparison is successful. The test command allows you to compare integers, strings, and even perform logical operations. Together with the test command, use options that specify the type of comparison. A complete list of options is given in Table 2.

Table 2. Operations performed by the BASH shell test command

Integer Comparison

Function

More than

Less than

More than equal

Less than equal

Not equal

String comparison

Function

Checking for an empty string

Checking for the presence of a string value

Testing strings for equality

Checking strings for inequality

Checking for a string consisting of zeros

Logical operations

Function

Logical AND

Logical OR

Logical NOT

Checking files

Function

Establishing the existence of a file and its regularity

Checks if the file is empty

Checking the ability to read from a file

Checking whether a file can be written to or modified

Checks if the file is executable

Checks if the file name is a directory name

Checks if the file name is a symbolic link

Checks whether the file name denotes a byte-oriented device

Checks whether the name denotes a block-oriented device

The test command has the following syntax:

test value -option value

test string = string

The following example will show an example of using the test command. Let's compare integer values; for this we use the equality option –eq. To check the result of the comparison operation, we use the completion code of the last executed command, test, which is stored in the variable $? interpretershell.

$ tot = 4

$test$ tot -eq 7

$echo$?

1

The command test $tot –eq 7 can also be written in another form:

$ [ $tot –eq 7 ]

Conditional constructions:if, if-else, elif, case . The BASH shell interpreter includes several conditional control constructs (Table 3) that allow you to select specific Linux commands to execute. Many of these constructs resemble conditional control constructs in programming languages, but there are some differences.

Table 3 – Interpreter control structuresbashShell

Conditional control structures

Function

if command then fi command

The if construct causes an action to be executed if the test result is true

if command then command else fi command

The if-else construct causes an action to be executed if the completion code of the command being tested is true, otherwise the else action is executed.

if command then command elif command then command else fi command

The elif construct allows you to nest if clauses, allowing you to choose from many options; if the condition tested by the first if construction is true, the commands provided in it are executed and control is not transferred to the next elif construction

case string in pattern) command;; esac

The case construct compares a string value with one of several patterns. When a match is found, commands matching this pattern are executed

command && command

The logical AND operation returns 0 (true) if both instructions return 0; if one of the commands returns a non-zero value, the result of the AND operation is false and this operation returns a non-zero value

team | | team

A logical OR operation that returns 0 (true) if one or both instructions return 0 (true); if both commands return a non-zero value, then the result of the OR operation is false and the operation returns a non-zero value

Team

Logical operation NOT, inverts the command completion code

while command do commands done

The while construct performs the action until the test command returns true.

until command do commands done

The until construct performs the action until the test command returns false.

Cyclic control structures

Function while, until, for, for-in, select

for variable in value-list do command done

The for-in construct is designed to process a list of values. The variable is sequentially assigned values ​​from the list

for variable do of command done

The for construct is designed to process script arguments sequentially. The variable is assigned the value of each argument sequentially

select line in element-list do command done

The select construct creates a menu based on the items in the given list, and then executes the specified command (usually a case command)

Conditional constructionif - then . The conditional if construct sets a condition for the execution of a command. This condition is the exit code of a specific Linux command. If the command completed successfully (that is, the exit code is 0), then the commands inside the if statement are executed. If the exit code is different from 0, then the commands inside the if construct will not be executed. Sometimes you need to choose one of two options, depending on how the Linux command was executed. The else keyword in the if clause allows you to choose one of two options. Here is the syntax of the if-then-else command.

The command language shell (translated as shell, shell) is actually a very high-level programming language. In this language, the user controls the computer. Typically, after logging in, you begin interacting with the command shell. A sign that the shell is ready to receive commands is the prompter it displays on the screen. In the simplest case it is one dollar (“$”). Shell is not necessary and the only command language (although it is the one that is standardized within the framework of POSIX, the mobile systems standard). For example, the cshell language is quite popular; there are also kshell, bashell and others. Moreover, each user can create his own command language. Can simultaneously work with different command languages ​​on one instance of the operating system. shell is one of many UNIX commands. That is, the “shell” command set includes the “sh” command - calling the “shell” interpreter. The first "shell" is called automatically when you log in and displays a programmer. After this, you can call any commands for execution, including the “shell” itself, which will create a new shell for you inside the old one. So for example, if you prepare the file "file_1" in the editor:

Echo Hello!

then this will be a regular text file containing the “echo” command, which, when executed, displays everything written to the right of it on the screen. You can make file "file_1" executable using the command "chmod 755 file_1". But it can be done by explicitly calling the "sh" ("shell") command:

Sh file_1

Sh< file1

The file can also be executed in the current shell instance. There is a specific command for this "." (dot), i.e.

File_1

Since UNIX is a multi-user system, you can even work on a personal computer in parallel on, say, 12 screens (change from screen to screen ALT/function key), having on each screen a new (or the same) user with his own command shell. You can also open a large number of windows in X-Window graphical mode, and each window can have its own user with its own command shell... The core element of the shell language is the command.

Command structures:

Commands in the shell usually have the following format:

<имя команды> <флаги> <аргумент(ы)>

For example:

Ls -ls /usr/bin

Where ls is the name of the command to output the contents of the directory, -ls is the flags ("-" is a sign of flags, l is the long format, s is the volume of files in blocks), /usr/bin is the directory for which the command is executed. This command will display the contents of the /usr/bin directory in long format, and will add information about the size of each file in blocks. Unfortunately, this command structure is not always followed. The flags are not always preceded by a minus, and the flags are not always one word. Yes variety in the presentation of arguments. Commands with exotic formats include such “running” commands as cc - calling the C language compiler, tar - working with archives, dd - copying a file with conversion, find - searching for files and a number of others As a rule, the shell perceives the first word as a command. Therefore, on the command line

the first word will be decrypted by the shell as a command (concatenation), which will display a file called "cat" (the second word) located in the current directory. Command redirection Standard input (input) - "stdin" in UNIX OS is carried out from the terminal keyboard, and standard output (output) - "stdout" is directed to the terminal screen. There is also a standard diagnostic message file - “stderr”, which will be discussed a little later. A command that can operate on standard input and output is called FILTER. The user has convenient means of redirecting input and output to other files (devices). The ">" and ">>" symbols indicate output redirection. ls >file_1 The "ls" command will generate a list of files in the current directory and place it in the file "file_1" (instead of printing it to the screen). If the file "file_1" existed before, it will be overwritten by the new one.

Pwd >>file_1

pwd team will form full name current directory and will place it at the end of the file "file_1", i.e. ">>" appends to the file if it is non-empty. Symbols "<" и "<<" обозначают перенаправление ввода.

Wc -l

will count and display the number of lines in the file file_1.

Ed file_2<

will create the file "file_2" using the editor, directly from the terminal. The end of the input is determined by the character to the right "<<" (т. е. "!"). То есть ввод будет закончен, когда первым в очередной строке будет "!". Можно сочетать перенаправления. Так

Wc -l file_4

Wc -l >file_4

are performed in the same way: the number of lines in the file "file_3" is counted and the result is placed in the file "file_4". The means that combines the standard output of one command with the standard input of another is called a PIPELINE and is indicated by a vertical bar "|".

ls | wc -l

a list of files in the current directory will be sent to the input of the "wc" command, which will display the number of lines in the directory. The pipeline can also combine more than two commands, when all of them, possibly except the first and last, are filters:

Cat file_1 | grep -h result | sort | cat -b > file_2

This pipeline from the file "file_1" ("cat") will select all lines containing the word "result" ("grep"), sort ("sort") the resulting lines, and then number ("cat -b") and print the result in file "file_2". Because UNIX devices are represented by special files, they can be used in redirections. Special files are located in the "/dev" directory. For example, "lp" - print; "console" - console; "ttyi" - i-th terminal; "null" is a dummy (empty) file (device). Then, for example,

Ls > /dev/lp

will print the contents of the current directory, and file_1< /dev/null обнулит файл "file_1".

Sort file_1 | tee /dev/lp | tail -20

In this case, the file "file_1" will be sorted and printed, and the last 20 lines will also be printed on the screen. Let's go back to output redirection. Standard files are numbered:

0 - stdin, 1 - stdout 2 - stderr. If you do not want to have an error message on the screen, you can redirect it from the screen to the file you specify (or completely throw it away by redirecting it to the “empty device” file - /dev/null). For example, when executing the command

Cat file_1 file_2

which should display the contents of the files “file_1” and “file_2” sequentially on the screen, it will give you, for example, the following

111111 222222 cat: f2: No such file or directory

where 111111 222222 is the contents of file "file_1" and file "file_2" is missing, which the "cat" command reported to the standard diagnostic file, by default, as is the standard output represented by the screen. If you do not want such a message on the screen, you can redirect it to the file you specify:

Cat file_1 file_2 2>f-err

error messages will be sent (as indicated by the "2>" redirection) to the "f-err" file. By the way, you can send all the information to one file “ff”, using in this case the construction

Cat file_1 file_2 >>ff 2>ff

You can specify not only which standard file to redirect, but also which standard file to redirect to.

Cat file_1 file_2 2>>ff 1>&2

Here, first "stderr" is redirected (in append mode) to file "ff", and then standard output is redirected to "stderr", which by this point is file "ff". That is, the result will be similar to the previous one. The construction "1>&2" means that in addition to the number of the standard file to redirect to, you must put "&" in front; the entire structure is written without spaces.<- закрывает стандартный ввод. >- closes standard output. Command files. There are several options for allowing a text file to be used as a command. Let's use an editor to create a file called "cmd" containing one line like this:

Date; pwd; ls

You can call the shell as a command, denoted "sh", and pass it a "cmd" file as an argument or as a redirected input, i.e.

$ sh cmd

$sh

The result of executing any of these commands will be the date, then the name of the current directory, and then the contents of the directory. A more interesting and convenient option for working with a batch file is to turn it into an executable one, i.e. just make it a command, which is achieved by changing the security code. To do this, you must allow execution of this file. For example,

Chmod 711 cmd

will make the security code "rwx__x__x". Then a simple call

will execute the same three commands. The result will be the same if the file with the contents

Date; pwd; ls

is represented in the form: date pwd ls since the transition to another line is also a separator in the sequence of commands. Thus, executable files can be not only files obtained as a result of compilation and assembly, but also files written in the shell language. They are executed in interpretation mode using a shell interpreter

Debugging batch files

SHELL uses two mechanisms for debugging batch files. The first one is: set -v prints out the command file lines as they are read. This mode is used when searching for syntax errors. To use it, you do not need to modify the command file, for example: sh -v proc... here proc is the name of the command file. The -v switch can be used in conjunction with the -n switch, which prevents execution of subsequent commands (the set -n command blocks the terminal until the EOF flag is entered). The set -x command displays commands as they are executed, and the program lines are output to the terminal and their values ​​are substituted in place of the variables. To cancel the -x and -v switches, you can use the set command - and to install, assign the corresponding value to a macro variable. SHELL ENVIRONMENT (VARIABLES AND PARAMETERS) In the shell language, you can write batch files and use the "chmod" command to make them executable. After this, they are no different from other UNIX OS commands.

Shell variables

A shell variable name is a sequence of letters, numbers, and underscores starting with a letter. The value of a shell variable is a string of characters. The fact that there are only two types of data in the shell: a string of characters and a text file, on the one hand, makes it easy to involve end users in programming who have never done programming before, and on the other hand, causes a certain internal protest among many programmers who are accustomed to significantly greater diversity and greater flexibility of linguistic means. However, it is interesting to observe how highly qualified programmers, having become familiar with the “rules of the game” of the shell, write programs in it many times faster than in C, but, what is especially interesting, in some cases these programs run even faster than those implemented in C. A variable name is similar to the traditional idea of ​​an identifier, i.e. a name can be a sequence of letters, numbers, and underscores, starting with a letter or underscore. The assignment operator "=" can be used to assign values ​​to variables.

Var_1=13 - "13" is not a number, but a string of two digits. var_2="UNIX OS" - Double quotes (" ") are required here because there is a space in the string.

Other ways of assigning values ​​to shell variables are also possible. For example, the recording

DAT=`date`

causes the "date" command to be executed first (the backticks indicate that the enclosed command must be executed first), and the result of its execution, instead of being output to the standard output, is assigned as the value of a variable, in this case " DAT". You can also assign a value to a variable using the "read" command, which ensures that the value of the variable is received from the (keyboard) display in dialog mode. Usually the "read" command in the batch file is preceded by the "echo" command, which allows you to pre-display some message on the screen. For example:

Echo -n "Enter a three-digit number:" read x

When executing this portion of the command file, after the message is displayed

Enter a three-digit number:

the interpreter will stop and wait for a value to be entered from the keyboard. If you entered, say, "753" then this will become the value of the variable "x". One "read" command can read (assign) values ​​to several variables at once. If there are more variables in "read" than are entered (separated by spaces), the remaining ones are assigned an empty string. If there are more transmitted values ​​than variables in the "read" command, then the extra ones are ignored. When accessing a shell variable, you must precede the name with the "$" symbol. So the commands echo $var_2 echo var_2 will display on the screen

UNIX OS var_2 Escaping

Let's take a closer look at the escaping techniques used in the shell. Double quotes (" "), single quotes (" "), and backslashes (\) are used as escape devices. Their action is obvious from the examples: You can write several assignments in one line.

X=22 y=33 z=$x A="$x" B="$x" C=\$x D="$x + $y + $z" E="$x + $y + $z " F=$x\ +\ $y\ +\ $z

(the assignment G=$x+$y would fail because of the spaces) Then

Echo A = $A B = $B C = $C echo D = $D E = $E F = $F eval echo evaluated A = $A eval echo evaluated B = $B eval echo evaluated C = $C

Will be displayed on the screen

A = 22 B = $x C = $x D = 22 + 33 + 22 E = $x + $y + $z F = 22 + 33 + 22 evaluated A = 22 evaluated B = 22 evaluated C = 22

Let's give some more examples related to escaping line feeds. Let the variable "string" be assigned the value of a 2x3 "array": abc def Note that to avoid assigning extra spaces, the second line of the array starts from the first position of the following line: string="abc def" Then there are three options for writing the variable in the "echo" echo command $string echo "$string" echo "$string" will give respectively three different results: abc def $string abc def and the sequence of commands echo "str_1 str_2" > file_1 echo "str_1 str_2" > file_2 cat file_1 file_2 will give sequentially identical files file_1 and file_2: str_1 str_2 str_1 str_2 Note also that the backslash (\) not only escapes the character that follows it, which allows special characters to be used simply as characters representing themselves (it can also escape itself - \\), but in a command file, a backslash allows you to concatenate lines into one (escape the end of the line). For example, the command line example given earlier:

Cat file_1 | grep -h result | sort | cat -b > file_2

could be written in a batch file, say like

Cat file_1 | grep -h\result | sort | cat -b > file_2

By the way, the conveyor symbol also provides the effect of continuing the command line. In this case it might give a nicer result, like this:

Cat file_1 | grep -h result | sort | cat -b > file_2

Manipulations with shell variables Despite the fact that shell variables are generally perceived as strings, i.e. “35” is not a number, but a string of two characters “3” and “5”, in a number of cases they can be interpreted differently, for example as integers. The "expr" command has a variety of capabilities. Let's illustrate some with examples: Executing a batch file:

X=7 y=2 a=`expr $x + $y` ; echo a=$a a=`expr $a + 1` ; echo a=$a b=`expr $y - $x` ; echo b=$b c=`expr $x "*" $y` ; echo c=$c d=`expr $x / $y` ; echo d=$d e=`expr $x % $y` ; echo e=$e

will display on the screen

A=9 a=10 b=-5 c=14 d=3 e=1

The multiplication operation ("*") must be escaped, since in the shell this icon is perceived as a special character, meaning that any sequence of characters can be substituted in this place. With the "expr" command, not only (integer) arithmetic operations are possible, but also string ones:

A=`expr "cocktail" : "cock"` ; echo $A B=`expr "cocktail" : "tail"` ; echo $B C=`expr "cocktail" : "cook"` ; echo $C D=`expr "cock" : "cocktail"` ; echo $D

Numbers will be displayed on the screen showing the number of matching characters in the chains (from the beginning). The second line cannot be longer than the first:

4 0 0 0

Exporting variables UNIX OS has the concept of a process. A process occurs when a command is executed. For example, when typing "p" on the keyboard "process "p" is spawned. In turn, "p" can spawn other processes. Let us assume that "p" calls "p1" and "p2", which sequentially spawn the corresponding processes. Each process has its own environment - a set of variables available to it For example, before launching "p" there was already an environment in which some variables were already defined. Launching "p" spawns a new environment; "p1" and "p2" will already be generated in it. Variables are local to the process in which they declared, i.e. where they are assigned values. In order for them to be available to other spawned processes, they must be passed explicitly. To do this, use the built-in "export" command.

Options

Parameters can be passed to the command file. The shell uses positional parameters (that is, the order in which they appear is important). In the command file, the variables corresponding to the parameters (similar to shell variables) begin with the symbol "$", followed by one of the numbers from 0 to 9: Let "examp-1" be called with the parameters "cock" and "tail". These parameters go into the new environment under the standard names "1" and "2". The (standard) variable named "0" will store the name of the called calculation. When accessing parameters, the number is preceded by the dollar symbol "$" (as when accessing variables): $0 corresponds to the name of this command file; $1 is the first parameter in order; $2 second parameter, etc. Since the number of variables to which parameters can be passed is limited to one digit, i.e. 9th (“0”, as already noted, has a special meaning), then to transfer a larger number of parameters a special “shift” command is used. The "set" command provides a unique approach to parameters. For example, fragment

Set a b with echo first=$1 second=$2 third=$3

will display on the screen

First=a second=b third=c

those. the "set" command sets the parameter values. This can be very convenient. For example, the "date" command displays the current date, say "Mon May 01 12:15:10 2000", consisting of five words, then

Set `date` echo $1 $3 $5

will display on the screen

Mon 01 2000

The "set" command also allows you to control the execution of the program, for example: set -v lines are output to the terminal, read by the shell. set +v cancels the previous mode. set -x prints commands to the terminal before execution. set +x cancels the previous mode. The "set" command without parameters displays the state of the software environment to the terminal.

Shell substitutions

Before directly interpreting and executing commands contained in batch files, the shell executes different kinds substitutions: 1. SUBSTITUTION OF RESULTS. All commands enclosed in backquotes are executed and the result is substituted in their place. 2. SUBSTITUTION OF VALUES OF PARAMETERS AND VARIABLES. That is, words starting with "$" are replaced with the corresponding values ​​of variables and parameters. 3. INTERPRETING GAPS. Escaped spaces are ignored. 4. GENERATION OF FILE NAMES. Words are checked for the presence of special characters ("*", "?","") and the corresponding generations are performed. Software Environment Every process has an environment in which it runs. Shell uses a number of these environment variables. If you type the "set" command without parameters, the screen will display information about a number of standard variables created at login (and then passed on to all your new processes "inherited"), as well as variables created and exported by your processes. The specific type and content of the information output depends to a large extent on what version of UNIX is used and how the system is installed.

The result of executing the set command without parameters (not complete):

HOME=/root PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11: IFS= LOGNAME=sae MAIL=/var/spool/mail/sae PWD=/home/ sae/STUDY/SHELL PS1=$(PWD):" " PS2=> SHELL=/bin/bash

Let's comment on the values ​​of the variables. HOME=/root is the name of the home directory where the user ends up after logging in. That is, having entered the name and password correctly, I will find myself in the “/root” directory. PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11 - this variable specifies the sequence of files that the shell looks for in search of a command. File names are separated here by colons. The viewing sequence corresponds to the order of names in the trail. But initially the search occurs among the so-called built-in commands. The built-in commands include the most commonly used commands, such as "echo", "cd", "pwd", "date". After this, the system looks through the “/bin” directory, which may contain the commands “sh”, “cp”, “mv”, “ls”, etc. Then the directory "/usr/bin" with the commands "cat", "ss", "expr", "nroff", "man" and many others. Next, the search takes place in the current directory (".", or another designation "empty", i.e. ""), where the commands you wrote are most likely located. After typing the command line and pressing "shell" (after performing the necessary substitutions) recognizes the name corresponding to the command and searches for it in the directories listed in PATH. If the command is placed outside of these directories, it will not be found. If there are several commands with the same name, the one located in the directory viewed first will be called. PATH, like other variables, can be easily changed by adding, rearranging, or deleting directories. IFS= (Internal Field Separator) lists characters that serve to separate words (fields). These are “space”, “tab” and “line feed”, so here nothing is visible to the left of the assignment and two lines are occupied. LOGNAME=root - login name (“user name”). MAIL=/var/spool/mail/root - the name of the file into which (e-mail) mail is received. PWD=/root - name of the current directory PS1=$(PWD): " " - type of directory. In this case, the prompter will display the name of the current directory followed by a colon and a space. That is, there will be "/root: ". PS2=> - this prompt (here ">") is used as an invitation to continue entering (in the next line) an unfinished command. For example, type the opening bracket "(" and after pressing in the next line you will see this prompter. If you don't know what to do next, type the closing bracket ")" and it will disappear. SHELL=/bin/sh - This variable specifies the shell the user is using. In this case, the standard shell ("sh") is used. The initial environment is installed automatically upon login using files like "/etc/rc" and "/etc/.profile". One way to simply change the environment (for example, command search path, program type, shell type, screen color, etc.) is by placing this information in your home directory in specialized file".profile" ($(HOME)/.profile), assigning the desired values ​​to the environment variables. That is, call this file into the editor and write whatever you want). Then, every time you log in, this file will automatically be executed and install a new environment. This file MUST be placed in your HOME directory (login directory). It should be kept in mind that file names starting with a dot generally have a special status. Thus, they are not displayed on the screen with a simple "ls" command - you must call this command with the "-a" flag. By the way, they are not destroyed indiscriminately by the “rm *” command. The shell interpreter itself automatically assigns values ​​to the following variables (parameters): ? the value returned by the last command; $ process number; ! background process number;

  1. the number of positional parameters passed to the shell;
  • list of parameters as one line;

@ list of parameters, as a set of words; - flags passed to the shell. When accessing these variables (that is, when using them in a command file - shell program), you should put "$" in front. An important role in creating unique files is played by the special variable "$$", the value of which corresponds to the number of the process performing this calculation. Each new calculation performed by a computer initiates one or more processes that automatically receive numbers in order. Therefore, by using the process number as the file name, you can be sure that each new file will have a new name (will not be written in place of the existing one). The advantage is also the main disadvantage of this method of naming files. It is not known what names will be assigned to the files. And, if within the framework of this process you can find a file “without looking,” that is, by accessing it using $$, then such files can easily be lost. This creates additional problems when debugging programs. Calling the interpreter After registering the user in the system (using the login command), the SHELL language interpreter is called. If the user's registration directory contains a .profile file, then before at least one command is received from the terminal, the interpreter executes this file (it is assumed that the .profile file contains commands). When calling, the following keys can be specified: -c string Commands are read from the given string. -s Commands are read from standard input. Interpreter messages are written to a standard diagnostics file. -i Interactive operating mode. If the first character of the "0" parameter is a - sign, then the commands are read from the .profile file.

PROGRAM STRUCTURES===

As in any programming language, shell text can contain comments. The "#" symbol is used for this. Everything that is on the line (in the command file) to the left of this character is perceived by the interpreter as a comment. For example,

# This is a comment.

Like any procedural programming language, the shell language has operators. A number of operators allow you to control the sequence of command execution. In such operators, it is often necessary to check the condition, which determines the direction in which the calculations continue.

Test("") command

The test command checks that a certain condition is met. Shell language select and loop statements are generated using this (built-in) command. Two possible formats commands:

Test condition

[ condition ]

we will use the second option, i.e. Instead of writing the word “test” before the condition, we will enclose the condition in parentheses, which is more common for programmers. In fact, the shell will recognize this command by the opening bracket "[" as the word corresponding to the "test" command. There must be spaces between the brackets and the condition they contain. There must also be spaces between the values ​​and the comparison or operation symbol. The shell uses conditions of various "types". FILE CHECKING CONDITIONS: -f file file "file" is a regular file; -d file file "file" - directory; -с file file "file" is a special file; -r file has permission to read the file "file"; -w file has permission to write to file "file"; -s file file "file" is not empty.

CONDITIONS FOR TESTING STRINGS: str1 = str2 strings "str1" and "str2" match; str1 != str2 strings "str1" and "str2" are not the same; -n str1 string "str1" exists (non-empty); -z str1 string "str1" does not exist (empty). Examples.

X="who is who"; export x; [ "who is who" = "$x" ]; echo $? 0 x=abc ; export x ; [ abc = "$x" ] ; echo $? 0 x=abc ; export x ; [ -n "$x" ] ; echo $? 0 x="" ; export x ; [ -n "$x" ] ; echo $? 1

Additionally, there are two standard condition values ​​that can be used in place of condition (no parentheses are needed for this). CONDITIONS FOR COMPARING INTEGERS: x -eq y "x" is equal to "y", x -ne y "x" is not equal to "y", x -gt y "x" is greater than "y", x -ge y "x" is greater than or equal to "y", x -lt y "x" less than "y", x -le y "x" less than or equal to "y". COMPLEX CONDITIONS: Implemented using standard logical operations: ! (not) reverses the exit code value. -o (or) matches logical "OR". -a (and) matches logical "AND".

Conditional statement "if"

In general, the "if" statement has the structure

If condition then list

Here "elif" a shortened version of "else if" can be used along with the full one, i.e. attachment allowed any number"if" statements (as well as other statements). Of course, the “list” in each case must be meaningful and acceptable in the given context. The most truncated structure of this operator

If condition then list fi

if the condition is met (usually this is where the completion code "0" is received), then the "list" is executed, otherwise it is skipped. Examples: Let "if-1" be written

If [ $1 -gt $2 ]

then pwd else echo $0: Hello!

Then calling if-1 12 11 will produce /home/sae/STUDY/SHELL and if-1 12 13 will produce if-1: Hello!

Call operator ("case")

The "case" selection operator has the structure:

Case string in

template) list of commands;; template) list of commands;; ... template) list of commands;;

Here "case", "in" and "esac" are function words. The "string" (this can be a single character) is compared with the "pattern". The "command list" of the selected line is then executed. “;;” looks unusual at the end of selection lines, but write “;” here it would be a mistake. Multiple commands can be executed for each alternative. If these commands are written on one line, then the symbol ";" will be used as a command separator. Usually last line selection has the pattern "*", which in the "case" structure means "any value". This line is selected if the value of the variable (here $z) does not match any of the previously written patterns delimited by the ")" bracket. The values ​​are viewed in the order they were written.

Enumerated loop operator ("for")

The "for" loop operator has the structure:

For name

do list of commands done where "for" is an auxiliary word that defines the type of loop, "do" and "done" are auxiliary words that highlight the body of the loop. Let the "lsort" command be represented by a batch file

For i in file_1 file_2 file_3 do proc_sort $i done

In this example, the name "i" acts as a loop parameter. This name can be considered as a shell variable to which the listed values ​​are sequentially assigned (i=file_1, i=file_2, i=file_3), and the "proc_sort" command is executed in a loop. The form "for i in *" is often used, meaning "for all files in the current directory". Let "proc_sort" in turn be represented by a batch file

Cat $1 | sort | tee /dev/lp > $(1)_sorted

those. the specified files are sorted sequentially, the sorting results are printed ("/dev/lp") and sent to the files file_1_sorted file_2_sorted and file_3_sorted

Loop statement with true condition ("while")

The "while" structure, which also performs calculations, is preferable when the exact list of parameter values ​​is unknown in advance or this list must be obtained as a result of calculations in a loop. The "while" loop statement has the structure:

While condition

do list of commands done where "while" is an auxiliary word that determines the type of loop with a true condition. The list of commands in the loop body (between "do" and "done") is repeated until the condition remains true (i.e. the exit code of the last command in the loop body is "0") or the loop is not interrupted from within special teams(“break”, “continue” or “exit”). When you first enter the loop, the condition must be true. The "break [n]" command allows you to break out of a loop. If "n" is missing, then it is equivalent to "break 1". "n" indicates the number of nested loops from which to exit, for example, "break 3" - exit from three nested loops. Unlike the "break" command, the "continue [n]" command only stops the execution of the current loop and returns to the BEGINNING of the loop. It can also be with a parameter. For example, "continue 2" means exit to the beginning of the second (counting from depth) nested loop. The "exit [n]" command allows you to exit the procedure altogether with a return code of "0" or "n" (if the "n" parameter is specified). This command can be used in more than just loops. Even in a linear sequence of commands, it can be useful in debugging to stop the (current) calculation at a given point.

Loop statement with false condition ("until")

The "until" loop operator has the structure:

Until condition

do list of commands done where "until" is an auxiliary word that determines the type of loop with a false condition. The list of commands in the body of the loop (between "do" and "done") is repeated until the condition remains false or the loop is interrupted from the inside by special commands ("break", "continue" or "exit"). The first time you enter the loop, the condition should not be true. The difference from the "while" operator is that the loop condition is checked for falsehood (for a non-zero exit code of the last command of the loop body) and is checked AFTER each (including the first!) execution of commands in the loop body. Example.

Until false do

read x if [ $x = 5 ] then echo enough ; break else echo some more fi

Here the program waits in an infinite loop for words to be entered (repeating the phrase "some more" on the screen) until "5" is entered. After this, "enough" is issued and the "break" command stops executing the loop.

Empty operator

The empty statement has the format

:

Doing nothing. Returns the value "0".

Functions in shell

The function allows you to prepare a list of shell commands for subsequent execution. The function description looks like:

Name() (command list)

after which the function is called by name. When the function is executed, no new process is created. It runs in the environment of the corresponding process. The function's arguments become its positional parameters; the name of the function is its zero parameter. You can interrupt the execution of a function using the "return [n]" operator, where (optional) "n" is the return code.

Interrupt handling ("trap")

It may be necessary to protect program execution from interruption. Most often you encounter the following interruptions corresponding to signals: 0 exit from the interpreter, 1 hang up (disconnection of the remote subscriber), 2 interruption from , 9 destruction (not intercepted), 15 end of execution. To protect against interrupts, there is a "trap" command, which has the format:

Trap "command list" signals

If interrupts occur in the system, whose signals are listed separated by a space in the “signals”, then the “command list” will be executed, after which (if the “exit” command was not executed in the command list) control will return to the interruption point and execution of the command file will continue. For example, if before interrupting the execution of a command file it is necessary to delete files in “/tmp”, then this can be done with the “trap” command:

Trap "rm /tmp/* ; exit 1" 1 2 15

which precedes other commands in the file. Here, after deleting the files, the command file will be exited.







2024 gtavrl.ru.