📜 ⬆️ ⬇️

Bash Scripts, Part 5: Signals, Background Tasks, Script Management

Bash scripts: start
Bash scripts, part 2: loops
Bash scripts, part 3: command line options and keys
Bash scripts, part 4: input and output
Bash Scripts, Part 5: Signals, Background Tasks, Script Management
Bash scripts, part 6: functions and library development
Bash scripts, part 7: sed and word processing
Bash scripts, part 8: awk data processing language
Bash scripts, part 9: regular expressions
Bash scripts, part 10: practical examples
Bash scripts, part 11: expect and automate interactive utilities

image

Last time, we talked about working with input, output, and error streams in bash scripts, about file descriptors, and about stream redirection. Now you already know enough to write something of your own. At this stage in the development of bash, you may well have questions about how to manage running scripts, how to automate their launch.



Until now, we entered script names on the command line and pressed Enter, which led to the immediate launch of programs, but this is not the only way to call scripts. Today we will talk about how the script can work with Linux signals, about different approaches to running scripts and managing them while working.
')

Linux signals


In Linux, there are more than three dozen signals that the system or applications generate. Here is a list of the most commonly used, which will probably come in handy when developing command line scripts.
Signal code
Title
Description
one
SIGHUP
Terminal closing
2
SIGINT
Process stop signal by the user from the terminal (CTRL + C)
3
SIGQUIT
Process stop signal by the user from the terminal (CTRL + \) with a memory dump
9
Sigkill
The final completion of the process
15
Sigterm
Process completion request signal
17
Sigstop
Forced suspension of the process, but not the completion of its work
18
Sigtstp
Suspending the terminal process (CTRL + Z), but not shutting down
nineteen
Sigcont
Continuation of the previously stopped process

If the bash shell receives a SIGHUP signal when you close the terminal, it terminates. Before exiting, it sends a SIGHUP signal to all processes running in it, including running scripts.

The SIGINT signal temporarily stops the operation. The Linux kernel no longer allocates processor time to the shell. When this happens, the shell notifies the processes by sending them a SIGINT signal.

Bash scripts do not control these signals, but they can recognize them and execute certain commands to prepare the script for the consequences caused by the signals.

Sending signals to scripts


The bash shell allows you to send signals to scripts using keyboard shortcuts. This is very useful if you need to temporarily stop the running script or terminate it.

Shutdown process


The CTRL + C key combination generates a SIGINT signal and sends it to all processes running in the shell, which leads to their completion.

Run the following command in the shell:

 $ sleep 100 

After that, we will complete her work with the CTRL + C key combination.


Shutting down the process from the keyboard

Pause process


The CTRL + Z key combination allows you to generate a SIGTSTP signal, which pauses the process but does not complete its execution. Such a process remains in memory, its work can be resumed. Run the command in the shell:

 $ sleep 100 

And temporarily stop it with the key combination CTRL + Z


Process suspension

The number in square brackets is the job number that the shell assigns to the process. The shell considers the processes running in it as tasks with unique numbers. The first process is assigned number 1, the second - 2, and so on.

If you pause the task associated with the shell and try to exit it, bash will issue a warning.

You can view suspended tasks with the following command:

 ps –l 


Task list

For a suspended process, T is displayed in column S , which displays the status of the process. This indicates that the command is either suspended or in the trace state.

If you need to shut down a suspended process, you can use the kill command. Details about it can be read here .

Her call looks like this:

 kill processID 

Interception of signals


To enable Linux signal tracking in the script, use the trap command. If the script receives the signal specified when calling this command, it processes it independently, and the shell will not process such a signal.

The trap command allows the script to respond to signals, otherwise they are processed by the shell without its participation.

Consider an example that shows how when you call the trap command, you trap code to be executed and the list of signals separated by spaces that we want to intercept. In this case, this is just one signal:

 #!/bin/bash trap "echo ' Trapped Ctrl-C'" SIGINT echo This is a test script count=1 while [ $count -le 10 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done 

The trap command used in this example displays a text message whenever it detects a SIGINT signal, which can be generated by pressing Ctrl + C on the keyboard.


Interception of signals

Each time you press CTRL + C , the script executes the echo command specified by the trace call instead of letting the shell exit.

Interception of an exit signal from a script


You can intercept the exit signal from the script by using the name of the signal EXIT when calling the trap command:

 #!/bin/bash trap "echo Goodbye..." EXIT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done 


Interception of an exit signal from a script

When exiting the script, be it a normal shutdown or shutdown caused by a SIGINT signal, the interception will trigger and the shell will execute the echo command.

Modification of intercepted signals and cancellation of interception


To modify the signals captured by the script, you can issue the trap command with new parameters:

 #!/bin/bash trap "echo 'Ctrl-C is trapped.'" SIGINT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done trap "echo ' I modified the trap!'" SIGINT count=1 while [ $count -le 5 ] do echo "Second Loop #$count" sleep 1 count=$(( $count + 1 )) done 


Modification of signal interception

After modification, the signals will be processed in a new way.

Interception of signals can be canceled, for this it is enough to execute the trap command, passing it a double dash and the name of the signal:

 #!/bin/bash trap "echo 'Ctrl-C is trapped.'" SIGINT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done trap -- SIGINT echo "I just removed the trap" count=1 while [ $count -le 5 ] do echo "Second Loop #$count" sleep 1 count=$(( $count + 1 )) done 

If the script receives a signal before the interception is canceled, it will process it as specified in the current trap command. Run the script:

 $ ./myscript 

And press CTRL + C on the keyboard.


Signal captured before interception cancellation

The first pressing of CTRL + C was at the time the script was executed, when the signal interception was in effect, so the script executed the echo command assigned to the signal. After the execution reached the intercept cancellation command, the CTRL + C command worked in the usual way, exiting the script.

Running command line scripts in the background


Sometimes bash scripts take a long time to complete a task. In this case, you may need to be able to work normally on the command line, without waiting for the script to complete. Implementing it is not so difficult.

If you saw the list of processes displayed by the ps command, you might have noticed processes that run in the background and are not tied to the terminal.
Let's write this script:

 #!/bin/bash count=1 while [ $count -le 10 ] do sleep 1 count=$(( $count + 1 )) done 

Run it by specifying an ampersand ( & ) after the name:

 $ ./myscipt & 

This will cause it to run as a background process.


Running the script in the background

The script will run in the background process, its identifier will be displayed in the terminal, and when its execution is completed, you will see a message about it.

Note that although the script runs in the background, it continues to use the terminal to display messages in STDOUT and STDERR , that is, the text or error messages it displays can be seen in the terminal.


Process list

With this approach, if you exit the terminal, the script running in the background will also terminate.

What if you want the script to continue working after the terminal is closed?

Execution of scripts that do not shut down when closing the terminal


Scripts can be executed in background processes even after exiting a terminal session. You can use the nohup command to do this. This command allows you to start the program, blocking the SIGHUP signals sent to the process. As a result, the process will be executed even when exiting the terminal in which it was launched.

Apply this technique when running our script:

 nohup ./myscript & 

This is what will be displayed in the terminal.


Nohup command

The nohup command unbinds the process from the terminal. This means that the process will lose references to STDOUT and STDERR . In order not to lose the data output by the script, nohup automatically forwards messages arriving in STDOUT and STDERR to the file nohup.out .

Please note that when running several scripts from the same directory, what they output will fall into one file nohup.out .

View assignments


The jobs command allows you to view current jobs that are running in the shell. Let's write this script:

 #!/bin/bash count=1 while [ $count -le 10 ] do echo "Loop #$count" sleep 10 count=$(( $count + 1 )) done 

Run it:

 $ ./myscript 

And temporarily stop the key combination CTRL + Z


Start and pause script

Let's run the same script in the background, while redirecting the output of the script to a file so that it does not display anything on the screen:

 $ ./myscript > outfile & 

Having now jobs command, we will see information about both the suspended script and the one that works in the background.


Retrieving Script Information

The -l switch when invoking the jobs command indicates that we need information about process ID .

Restart suspended jobs


In order to restart the script in the background, you can use the bg command.

Run the script:

 $ ./myscript 

Press CTRL + Z , which temporarily stops its execution. Run the following command:

 $ bg 


Bg command

Now the script runs in the background.

If you have several suspended tasks, you can transfer its number to the bg command to restart a specific task.

To restart the job in normal mode, use the fg command:

 $ fg 1 

Script Scheduling


Linux provides a couple of ways to run bash scripts at a specified time. This is the at command and the cron job scheduler.

Calling the at command looks like this:

 at [-f filename] time 

This command recognizes multiple time indication formats.


In addition to the possibility of specifying the start time of a job, the at command can also be passed a date using one of its supported formats.


We will not go into this topic, consider a simple way to use the command:

 $ at -f ./myscript now 


Scheduling tasks using the at command

The -M key when calling at used to send what the script displays to the email if the system is properly configured. If sending the email is not possible, this key will simply suppress the output.

To view the list of tasks waiting to be completed, you can use the atq command:

 $ atq 


List of tasks awaiting execution

Deleting tasks waiting to be completed


To remove a task that is pending execution, the atrm command atrm . When you call it indicate the job number:

 $ atrm 18 


Delete job

Run scripts on a schedule


Planning to run scripts once using the at command can make life easier in many situations. But what if you want the script to run at the same time every day, or once a week, or once a month?

Linux has a crontab utility that allows you to schedule scripts to run regularly.

Crontab runs in the background and, based on data in the so-called cron-tables, runs jobs on a schedule.

To view the existing cron job table, use the following command:

 $ crontab –l 

When scheduling a script to run according to a schedule, crontab accepts data on when the task should be performed in the following format:

 , ,  , ,  . 

For example, if it is necessary that a certain script with the name command executed daily at 10:30, this would correspond to the following entry in the task table:

 30 10 * * * command 

Here, the universal symbol " * ", used for the fields that specify the day of the month, the month and the day of the week, indicates that cron must execute the command every day of every month at 10:30.

If, for example, you want the script to run at 4:30PM every Monday, you will need to create the following entry in the task table:

 30 16 * * 1 command 

The numbering of the days of the week starts with 0, 0 means Sunday, 6 means Saturday. Here is another example. Here the command will be executed at 12 noon on the first day of each month.

 00 12 1 * * command 

The numbering of the months starts from 1.
To add an entry to the table, you need to call crontab with the -e key:

 crontab –e 

Then you can enter the schedule generation commands:

 30 10 * * * /home/likegeeks/Desktop/myscript 

Thanks to this command, the script will be called daily at 10:30. If you encounter the error “Resource temporarily unavailable”, execute the following command with root user rights:

 $ rm -f /var/run/crond.pid 

It is even easier to organize the periodic launch of scripts using cron , using several special directories:

 /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly 

If you place the script file in one of them, it will lead, respectively, to its hourly, daily, weekly or monthly launch.

Running scripts at login and at shell startup


Automate the launch of scripts can be based on various events, such as user logon or shell launch. Here you can read about the files that are processed in such situations. For example, these are the following files:

 $HOME/.bash_profile $HOME/.bash_login $HOME/.profile 

To run the script at login, place its call in the .bash_profile file.

What about running scripts when opening a terminal? Organize this will help file .bashrc .

Results


Today we discussed issues related to the management of the life cycle of scenarios, talked about how to run scripts in the background, how to plan their execution on a schedule. Next time, read about functions in bash scripts and library development.

Dear readers! Do you use the tools to schedule the launch of command line scripts on a schedule? If so, please tell us about them.

Source: https://habr.com/ru/post/326826/


All Articles