Shell programming experiment

Experiment 2 Shell programming

1. If there is file f1 in the current directory, but no f2, interpret the result of running the command ls f1 f2 2>ef1 1>&2.

PWN@PWN-PC:~/Desktop$ ls f1 f2 2>ef1 1>&2
PWN@PWN-PC:~/Desktop$ cat ef1 
ls: Inaccessible'f2': does not have that file or directory
echo hello 1>&2 | grep aaa
#The results show:
PWN@PWN-PC:~/Desktop$ echo hello 1>&2 | grep aaa

echo hello 2>&1 | grep aaa
#The results show:
PWN@PWN-PC:~/Desktop$ echo hello 2>&1 | grep aaa

echo hello 1>&2 | grep e
#The results show:
PWN@PWN-PC:~/Desktop$ echo hello 1>&2 | grep e

echo hello 2>&1 | grep e
#The results show:
PWN@PWN-PC:~/Desktop$ echo hello 2>&1 | grep e


  • The execution of the command is divided into correct output and error output. When using the pipe character, the pipe character only receives the correct output from the command in front of the pipe character. At this time, you need to use 2>&1 to change the output type.
  • The pipe character is only transmitted, not stored. Therefore, when 2>ef1 is used for the first time, the obtained error output is redirected to the file ef1, and then 1>&2 is used to treat the correct output as the error output, and then write to ef1 through pipe 2.

Second, use the for loop statement to write a B-shell program to complete the list of all C program files and their target files in the a_sub and b_sub subdirectories of the user registration directory.

PWN@PWN-PC:~$ pwd
PWN@PWN-PC:~$ ls
Desktop  Documents  Downloads  Music  Pictures  Videos
PWN@PWN-PC:~$ mkdir a_sub b_sub
PWN@PWN-PC:~$ ls
a_sub  b_sub  Desktop  Documents  Downloads  Music  Pictures  Videos
PWN@PWN-PC:~$ touch a_sub/file{1..5}.c
PWN@PWN-PC:~$ ls -l a_sub/
Total usage 0
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file1.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file2.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file3.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file4.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file5.c
PWN@PWN-PC:~$ touch a_sub/flag{1..3}
PWN@PWN-PC:~$ ls -l a_sub/
Total usage 0
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file1.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file2.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file3.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file4.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 file5.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 flag1
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 flag2
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:09 flag3
PWN@PWN-PC:~$ touch b_sub/sys_lib{1..5}.c
PWN@PWN-PC:~$ ls -l b_sub/
Total usage 0
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:10 sys_lib1.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:10 sys_lib2.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:10 sys_lib3.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:10 sys_lib4.c
-rw-r--r-- 1 PWN PWN 0 10 Aug 8 22:10 sys_lib5.c
dirlst="a_sub b_sub "
for i in $dirlst
    cd $HOME/$i
    ls -l *.c
    ls -l flag*

3. Master the three basic ways of executing shell programs, pay attention to the difference in the way of writing commands for debugging shell programs?

  • If the script file itself does not have permission to execute, if there is no x permission, the method used, or the script does not specify shebang, then use the method of specifying the interpreter to execute.

  • With x permission, use ./ to execute the script

  • Use . or source to execute

  • redirect write, bash <


    How to Debug Shell Scripts
    \1) Check for syntax errors:
    Generally speaking, we can locate errors by modifying the source code of the shell script to output relevant debugging information. Is there a way to debug the shell script without modifying the source code? The answer is to use the execution option of the shell. The following are the usage of some common options:
    -n only reads shell scripts, but does not actually execute them
    -x Enter trace mode, display each command executed
    -c "string" read commands from strings

    "-n" can be used to test shell scripts for syntax errors, but not to actually execute the command. It is a good practice to first test the script for syntax errors with the "-n" option after the shell script is written, but before the actual execution. Because some shell scripts will affect the system environment during execution, such as generating or moving files, if a syntax error is found during actual execution, you have to manually restore the system environment to continue testing the script.

    The "-c" option causes the shell interpreter to read and execute shell commands from a string instead of a file. You can use this option when you need to temporarily test the execution result of a small script, as follows:
    sh -c 'a=1;b=2;let c= a + a+ a+b;echo "c=$c"'

    The "-x" option can be used to trace the execution of scripts and is a powerful tool for debugging shell scripts. The "-x" option causes the shell to display each command line it actually executes during script execution, with a "+" sign at the beginning of the line. The content of the command line after variable substitution is displayed after the "+" sign, which helps to analyze what command is actually executed. The "-x" option is simple and convenient to use, can easily handle most shell debugging tasks, and should be used as the preferred debugging method.

    \2) Debug tool-bashdb
    Use the shell debugger bashdb, which is a debugging tool similar to GDB, which can complete many functions such as setting breakpoints, single-step execution, and variable observation of shell scripts.

    Common commands for debug ging using bashdb
    1. List code and query code classes:
    l List 10 lines below the current line
    - List the first 10 lines of code being executed
    . go back to the line of code being executed
    w lists the code before and after the line of code being executed
    /pat/ searches backwards for pat
    ? pat? search forward pat

    2.Debug control class:
    h help
    help command to get the specific information of the command
    q quit bashdb
    x Arithmetic expression Calculates the value of an arithmetic expression and displays it
    !!space shell command parameter execute shell command
    Common commands for debug ging using bashdb (cont.)
    Control script execution class:
    n Execute the next statement, encounter a function, do not enter the function to execute, treat the function as a black box
    s n Single step n times, encounter a function and enter the function
    b line number n set a breakpoint at line number n
    del line number n undo the breakpoint at line number n
    c line number n executes until line number n
    R restart
    Finish executes to the end of the program
    cond n expr conditional breakpoint

4. In order to facilitate the system administrator to manage the disk allocation, please write a B-shell program, which will give a corresponding information prompt when the space occupied by the file system /home changes. The required /home occupancy in the system disk is:

  1. When the value is less than 50%, the message "The disk usage load of the user file system is low" is displayed.
  2. When the value is greater than 50% and less than 90%, the message "The disk usage load of the user file system is normal" is displayed.
  3. When the value is greater than or equal to 90%, the prompt "The disk usage load of the user file system is too heavy.

Idea: How to get disk space? Note that the title is to know the space occupancy of a directory, and disk occupancy is not a problem.

Run the df and du commands separately to check the space usage of the user registration directory, and then decide the programming method according to the output of these two commands.

#! /bin/bash
hm=`du -s /home|cut -f 1`
#Use du to query the size of the /home directory, parameter -s to specify the directory, and cut to intercept the content
rt=`df /home|grep /|tr -s [:space:]|cut -f 2 -d " "`
#Use df to get the size of the disk where /home is located, tr to reduce the inconsistent interval into one interval, and cut to intercept the content.
let ret=hm*100/rt
#Use the let operation to calculate the proportion, because let is an integer division and does not display decimals, so first multiply by a 100.
#Debug: echo "$hm,$rt,$ret"
#Debug: ret=30
case $ret in
        9[0-9])echo "User file system disk usage load is too heavy";;
        [5-8][0-9])echo "User file system disk usage load is normal";;
        [0-4][0-9]|[0-9]) echo "User file system disk usage load is small";;

5. Familiar with basic command skills and rules of programming, such as variable naming, quoting, location variables and their use, output statement and output format control, input statement and variable storage, extracting field values ​​from command output, etc.


  • When defining and assigning variables, there must be no space between the variable and the value: var="abcd"

    No need to declare types, and bash treats all variables as strings by default

  • Printing of variables: echo $var, echo ${var}

  • Variable naming rules:

    1. Know your name
    2. Can only contain numbers, letters, and underscores
    3. cannot start with a number
    4. no punctuation
    5. Variable names are strictly case sensitive
  • Scope of variables: Switching shell variables is lost

    1. Local variables only exist in the current shell. When defining shell variables, the variable name does not need to add the $ character. Local variables are only valid in the user's current shell lifetime.

    2. Environment variables, global variables, for the current shell and any of its subprocesses, the environment variables are also divided into custom and built-in environment variables

    3. Local variables: for those defined in shell functions or shell scripts

    4. Positional parameter variables: used for parameters passed in shell scripts (equivalent to parameters and paths when commands are executed)

    5. Special variables: special function variables built into the shell

      $0: Get shell script file name, and script path

      $n: Get the nth parameter of the shell script, n is between 1 and 9, such as $1, $2, 9 , more than the 9 you need to write 9, if it is greater than 9, you need to write 9, if it is greater than 9, you need to write {10}, the parameters are separated by spaces

      $#: Get the total number of parameters following the executed shell script

      ∗ :Obtain s h e l l All parameters of the script, unquoted is equivalent to *: Get all parameters of the shell script, unquoted is equivalent to ∗: Get all the parameters of the shell script. Without quotation marks, it is equivalent to @ function. With quotation marks "$ *", it is mainly used to receive parameters as a single string "$1 $2 $3 $4 $5 $6 $7"

      $@: Without quotation marks, the effect is the same as above, with quotation marks, all parameters are received as independent strings "$1" "$2" "$3" "$4" "$5" "$6" "$7"

    6. special state variables

      $?: This is a status variable, if the last command was executed successfully, it will be 0, error 1-255 (error code)

      echo $?: Used in the script to check whether an instruction is executed successfully

      $$: Get the process ID of the current shell script

      $!: The PID of the last background process

      $_: Get the last parameter of the last executed command

    7. custom variable

  • quote variable

    1. Single-quoted variables, special syntax not recognized
    2. Double-quoted variables, can recognize special symbols
    3. Backtick variable, the variable value will be recognized as a command, and the result of the command execution will be stored as the value of the variable

    Calling the bsh interpreter to execute the script will open a subshell, so the current shell variables are not retained;

    Call source or . symbol to load the script in the current shell environment, so keep variables

  • Environment variable settings

    Environment variables generally refer to variables exported by the export built-in command, which are used to define the operating environment of the shell and ensure the correct execution of shell commands.

    The shell determines the login user name, PATH path, file system and other applications through environment variables.

    Environment variables can be created temporarily on the command line, but when the user exits the shell terminal, the variables will be lost. To take effect permanently, you need to modify the environment variable configuration file.

    • User personal configuration files are in: ~/.bash_profile, ~/.bashrc Remote login user-specific files

    • The global configuration files /etc/profile and /etc/bashrc are recommended to be created in /etc/profile.d instead of directly modifying the main file and modifying the global configuration file, which affects all users who log in to the system

      User-configured environment variables are given priority, followed by global variables.

    • Command to check system environment variables

      1. set, output all variables, including global variables, local variables

        set |wc -l: can display the total number of lines

        set |grep ^name: find variables starting with name

      2. env, only show global variables

      3. declare, output all variables, same as set

      4. export, display and set environment variable values

    • Undo environment variables, delete variables or functions: unset variable-name

    • Set a read-only variable: readonly age=18, after setting the variable can no longer be modified, when the shell ends, the read-only variable is invalid.

      Filter out the names of all environment variables in the environment variables:

      export | awk -F '[:=]' '{print $3}'

6. Completion of writing a shell program: According to the students' grades input from the keyboard, the corresponding grade standards (fail, pass, medium, good and excellent, etc.) are displayed.


read a
case $a in
        9[0-9]|100)echo "excellent";;
        8[0-9])echo "good";;
        7[0-9])echo "middle";;
        6[0-9])echo "Pass";;
        [0-5][0-9])echo "failed";;
        *) echo "Wrong content!";;


7. Assuming that the score.txt file saves the test scores of a certain course of students in three classes, please write a shell program to calculate the number of students and the average score in each class.

Learn how to read files.

If the content of the data file is the content of 5 different courses in 3 classes, how should the program be adjusted?

#The operation of this program has a great relationship with the content format in the target file, that is, the operation is carried out according to the content format of the file

class="Accounting 201 Accounting 202 Accounting 203"
for i in $class
	total=`grep -F $i score.txt|wc -l`
	#Use the class as the keyword to retrieve the relevant rows (grep -F $i) and count the number of rows (wc -l). The number of rows is the number of people.
	average=`grep -F $i score.txt|awk -F: '{sum+=$3}END{print ":",sum/NR}'`
	#The content of the third column is intercepted from the content of a previously retrieved class, and accumulated to obtain the sum, and the sum is divided by the built-in variable NR (number of rows) to obtain the average value.
	echo "$i class:$total people,The average score $average. "
#text format
 Accounting 201:a:75
 Accounting 202:b:76
 Accounting 201:c:77
 Accounting 203:d:78
 Accounting 202:e:79
 Accounting 203:f:80

class="Accounting 201 Accounting 202 Accounting 203"
for i in $class
	total=`grep -F $i score1.txt|wc -l`
	echo "$i class:$total people"
	for j in 3 4 5 6 7
		x=`sed -n '1p' score1.txt|awk -F" " '{print $'$j'}'`
		#The principle is the same as the previous one, here is to simply get the content of the first line, read the subject, and simplify the operation.
		average=`grep -F $i score1.txt|awk -F" " '{sum+=$'$j'}END{print ":",sum/NR}'`
		echo "$i class $x The average score: $average"
#file content format
 Class Name Chinese Mathematics English Computer Network Attack and Defense
 Accounting 201 a 110 130 125 99 100
 Accounting 201 b 99 101 145 80 75
 Accounting 201 c 107 112 126 68 60
 Accounting 201 d 113 135 140 95 95
 Accounting 202 e 121 140 130 68 52
 Accounting 202 f 111 150 30 56 32
 Accounting 202 g 141 123 86 23 51
 Accounting 202 h 90 25 35 60 75
 Accounting 202 i 51 36 85 62 34
 Accounting 203 j 134 62 140 55 66
 Accounting 203 k 111 112 113 70 71
 Accounting 203 l 142 143 144 99 100
 Accounting 203 m 150 150 150 100 100
 Accounting 203 n 100 100 100 100 100
 Accounting 203 o 101 101 101 101 101

Tags: Linux

Posted by valtido on Fri, 14 Oct 2022 03:27:23 +0530