欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux?Shell任務控制的實現(xiàn)示例

 更新時間:2024年01月09日 10:55:42   作者:恒友成  
本文主要介紹了Linux?Shell任務控制的實現(xiàn)示例,包括向腳本發(fā)送信號、修改腳本的優(yōu)先級以及在腳本運行時從暫停切換到運行模式,感興趣的可以了解一下

通常情況下運行腳本的方式就是以實時模式在命令行界面上直接運行,除此之外還有很多其他的運行腳本的方式,如后臺運行,定時運行等等。除運行方式外,還可以對腳本程序的運行進行控制,包括向腳本發(fā)送信號、修改腳本的優(yōu)先級以及在腳本運行時從暫停切換到運行模式。

1)信號

Linux利用信號與運行在系統(tǒng)中的進程進行通信,可以通過對腳本進行編程,使其在收到特定信號時執(zhí)行特定命令。

信號描述
1SIGHUP掛起進程
2SIGINT終止進程
3SIGQUIT停止進程
9SIGKILL無條件終止進程
15SIGTERM盡可能終止進程
17SIGSTOP無條件停止進程,但不是終止進程
18SIGTSTP停止或暫停進程,但不終止進程
19SIGCONT繼續(xù)運行停止的進程

默認情況下,交互式shell終端本身的進程會忽略收到的任何 SIGQUIT (3) 和 SIGTERM (5) 信號,因此其不會被意外終止。

如果bash shell收到了 SIGHUP 信號,比如當要離開一個交互式shell時,它就會退出。但在退出之前,它會將 SIGHUP 信號傳給所有由該shell所啟動的進程。

通過鍵盤生成信號

Ctrl+C組合鍵會生成 SIGINT 信號,并將其發(fā)送給當前在shell中運行的所有進程

Ctrl+Z組合鍵會生成一個 SIGTSTP 信號,停止shell中運行的任何進程。這樣可以在進程運行期間暫停進程,而無需終止它。這樣可以在不終止進程的情況下使用戶深入腳本內部一窺究竟。

停止進程會讓程序繼續(xù)保留在內存中,并能從上次停止的位置繼續(xù)運行。

要想啟動停止的進程可以使用fgbg在前臺和后臺啟動。

$ sleep 100
# ^Z
# [1]+  已停止               sleep 100

方括號中的數(shù)字是shell分配的作業(yè)號 (job number)。

可以用 ps 命令來查看已停止的作業(yè)。

$ ps -l
# F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
# 0 T  1001  116014  113239  0  80   0 -  2791 do_sig pts/0    00:00:00 sleep

在 S 列中(進程狀態(tài)), ps 命令將已停止作業(yè)的狀態(tài)為顯示為 T 。這說明命令要么被跟蹤,要么被停止了。

在有已停止作業(yè)存在的情況下退出shell會終止已停止作業(yè)。

trap 命令捕獲信號

trap命令允許用戶來指定shell腳本要監(jiān)視并從shell中攔截的Linux信號。當腳本收到了 trap 命令中列出的信號,會執(zhí)行用戶指定的操作。

trap命令的格式:

trap commands signals

示例,

#!/bin/bash

trap "echo 'Ctrl-C Pressed'" SIGINT

echo This is a test

c=1
while [ $c -le 5 ]
do
    echo "Loop #$c"
    sleep 1
    c=$[ $c + 1 ]
done

執(zhí)行,

$ ./test.sh 
# This is a test
# Loop #1
# Loop #2
# ^CCtrl-C Pressed
# Loop #3
# Loop #4
# Loop #5

上面腳本中trap 命令會在每次檢測到 SIGINT 信號時捕獲這些信號,阻止用戶用bash shell組合鍵Ctrl+C來停止程序。

除了在shell腳本中捕獲中斷信號,也可以在shell腳本退出時捕獲退出信號EXIT。以在shell完成任務時執(zhí)行特定的命令。

#!/bin/bash

trap "echo 'Running Finished.'" EXIT

echo This is a test

c=1
while [ $c -le 5 ]
do
    echo "Loop #$c"
    sleep 1
    c=$[ $c + 1 ]
done

執(zhí)行,

$ ./test.sh 
# This is a test
# Loop #1
# Loop #2
# Loop #3
# Loop #4
# Loop #5
# Running Finished.

要修改移除捕獲,在腳本中的不同位置進行不同的捕獲處理,只需重新使用帶有新選項的 trap 命令。

#!/bin/bash

trap "echo 'Caught SIGINT'" SIGINT

echo "This is first caughtion of SIGINT"

c=1
while [ $c -le 3 ]
do
    echo "Loop #$c"
    sleep 1
    c=$[ $c + 1 ]
done

trap "echo 'Redefine SIGINT '" SIGINT
echo "This is Mutated caughtion of SIGINT"
sleep 10

執(zhí)行,

$ ./test.sh
# This is first caughtion of SIGINT
# Loop #1
# ^CCaught SIGINT
# Loop #2
# Loop #3
# This is Mutated caughtion of SIGINT
# ^CRedefine SIGINT

修改了信號捕獲之后,腳本處理信號的方式就會發(fā)生變化。如果一個信號是在捕獲被修改前接收到的,那么腳本仍然會根據(jù)最初的 trap 命令進行處理。

想刪除已設置好的捕獲,只需要在 trap 命令與希望恢復默認行為的信號列表之間加上兩個破折號即可。

trap -- SIGINT

2)在后臺運行腳本

直接在命令行界面運行shell腳本,腳本在運行時,沒法在終端會話里做別的事情。

在用 ps 命令時,會看到運行在Linux系統(tǒng)上的一系列不同進程。這些進程顯然都不是運行在當前的終端顯示器上的,這種模式稱為在后臺運行進程。在后臺模式中,進程運行時不會和終端會話上的 STDIN 、 STDOUT 以及 STDERR 關聯(lián)。

命令后加 & 符

前面介紹過,以后臺模式運行shell腳本,只要在命令后加個 & 符就行。

$ ./test.sh &
# [1] 118347

方括號中的數(shù)字是shell分配給后臺進程的作業(yè)號。下一個數(shù)是Linux系統(tǒng)分配給進程的進程ID(PID)。當后臺進程結束時,它會在終端上顯示出一條消息:

# [1]+  已完成               ./test.sh

通過./test.sh &命令將腳本放在后臺運行還存在兩個問題,一個是當前bash shell終端關閉時后臺運行中的進程仍然會被終止,第二個時放入后臺的腳本輸出仍然會顯示在顯示器上,會與新輸入命令的輸入混淆在一起

運行多個后臺作業(yè)時,通過 ps 命令,可以看到
所有腳本處于運行狀態(tài)。

 ./test.sh &
 ./test.sh &
$ ps
# F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
# 0 S  1001  118703  118697  0  80   0 -  3178 do_wai pts/3    00:00:00 test.sh
# 0 S  1001  118707  118703  0  80   0 -  2791 hrtime pts/3    00:00:00 sleep
# 0 S  1001  118714  118697  0  80   0 -  3178 do_wai pts/3    00:00:00 test.sh
# 0 S  1001  118718  118714  0  80   0 -  2791 hrtime pts/3    00:00:00 sleep

使用nohub命令

當需要在終端會話中啟動shell腳本,然后讓腳本一直以后臺模式運行到結束,且終端會話退出仍不影響腳本運行時,前面介紹的&符號的方式就不適合了,這時需要使用nohub命令。

nohup 命令運行的后臺任務會阻斷所有發(fā)送給該進程的 SIGHUP信號,這可以在退出終端會話時阻止進程退出。

nohup 命令的格式:

$ nohup ./test.sh &
# [1] 119226
# nohup: 忽略輸入并把輸出追加到'nohup.out'

由于 nohup 命令會解除終端與進程的關聯(lián),進程也就不再同 STDOUT 和 STDERR 聯(lián)系在一起。
為了保存該命令產(chǎn)生的輸出, nohup 命令會自動將 STDOUT 和 STDERR 的消息重定向到一個名為
nohup.out的文件中。值得注意的是,當在同個目錄同時啟動多個nohub命令時,會輸出到同一個nohub.out文件中

3)作業(yè)控制

jobs 命令可以查看分配給shell的作業(yè)。

通過test.sh啟動兩個作業(yè),

$ ./test.sh
# This is first caughtion of SIGINT
# Loop #1
# ^Z
# [1]+  已停止
$ ./test.sh > test.out &
# [2] 119480
$ jobs
# [1]+  已停止               ./test.sh
# [2]-  運行中               ./test.sh > test.out &

要想查看作業(yè)的PID,可以在 jobs 命令中加入 -l 選項。jobs 命令輸出中的加號和減號的含義是帶加號的作業(yè)會被當做默認作業(yè),在使用作業(yè)控制命令時,如果未在命令行指定任何作業(yè)號,該作業(yè)會被當成作業(yè)控制命令的操作對象。當前的默認作業(yè)完成處理后,帶減號的作業(yè)成為下一個默認作業(yè)。任何時候都只有一個帶加
號的作業(yè)和一個帶減號的作業(yè)。在前面介紹的重新啟動停止的作業(yè)的命令fg/bg不帶參數(shù)時,啟動的就是+號對應的作業(yè)。

更多jobs命令的選項參數(shù),可以通過命令jobs --help查看。

4)調度優(yōu)先級

調度優(yōu)先級決定了內核分配給進程的CPU時間。在Linux系統(tǒng)中,由shell啟動的所有進程的調度優(yōu)先級默認都是相同的,都是0。調度優(yōu)先級是個整數(shù)值,從-?20(最高優(yōu)先級)到+19(最低優(yōu)先級)。

要改變一個shell腳本的優(yōu)先級,可以通過 nice 命令做到。

nice命令

nice 命令允許你設置命令啟動時的調度優(yōu)先級。要讓命令以更低的優(yōu)先級運行,只要用 nice的 -n 命令行來指定新的優(yōu)先級即可。

$ nice -n 10 ./test.sh > test.out &
# [2] 120413
$ ps -p 120413 -o pid,ppid,ni,cmd
#     PID    PPID  NI CMD
#  120413  118697  10 /bin/bash ./test.sh

通過ps命令可以看到調度優(yōu)先級已經(jīng)被調整到了10。

nice 命令阻止普通系統(tǒng)用戶來提高命令的優(yōu)先級,需要使用root權限。

renice 命令

renice命令用來改變系統(tǒng)上已運行命令的優(yōu)先級。通過指定運行進程的PID來改變它的優(yōu)先級。

$ renice -n 10 -p 120756
# 120756 (process ID) 舊優(yōu)先級為 0,新優(yōu)先級為 10

5)定時運行作業(yè)

Linux系統(tǒng)提供了多個在預選時間運行腳本的方法: at 命令和 cron 表。

at

at 命令允許指定Linux系統(tǒng)何時運行腳本,相當于是預約執(zhí)行任務。

at 的守護進程 atd 會以后臺模式運行,檢查作業(yè)隊列來運行作業(yè)。大多數(shù)Linux發(fā)行版會在啟動時運行此守護進程

atd 守護進程會檢查系統(tǒng)上的一個特殊目錄(通常位于/var/spool/at)來獲取用 at 命令提交的作業(yè)。默認情況下, atd 守護進程會每60秒檢查一下這個目錄。有作業(yè)時, atd 守護進程會檢查作業(yè)設置運行的時間。如果時間跟當前時間匹配, atd` 守護進程就會運行此作業(yè)。

at 命令的基本格式:

at [-f filename] time
  • -f 參數(shù)來指定用于讀取命令(腳本文件)的文件名。
  • time 參數(shù)指定了Linux系統(tǒng)何時運行該作業(yè)。

at 命令能識別多種不同的時間格式:

  • 標準的小時和分鐘格式,比如22:15
  • AM/PM指示符,比如10:15 PM
  • 特定可命名時間,比如now、noon、midnight或者teatime(4 PM)
  • 通過不同的日期格式指定特定的日期
    • 標準日期格式,比如MMDDYY、MM/DD/YY或DD.MM.YY
    • 文本日期,比如Jul 4或Dec 25,加不加年份均可
    • 指定時間增量:當前時間+25 min。
$ at -f test.sh  21:23
# warning: commands will be executed using /bin/sh
# job 3 at Mon Jan  8 21:23:00 2024

作業(yè)隊列的字母排序越高,作業(yè)運行的優(yōu)先級就越低,nice值更高。默認情況下, at 的作業(yè)會被提交到 a 作業(yè)隊列。如果想以更高優(yōu)先級運行作業(yè),可以用 -q 參數(shù)指定不同的隊列字母。

在使用 at 命令時,最好在腳本中對 STDOUT 和 STDERR 進行重定向

atq 命令可以查看系統(tǒng)中有哪些作業(yè)在等待。

$ atq
# 1	Mon Jan  8 21:17:00 2024 = rob
# 6	Tue Jan  9 20:24:00 2024 a rob
# 3	Mon Jan  8 21:23:00 2024 = rob
# 4	Tue Jan  9 20:24:00 2024 a rob
# 5	Tue Jan  9 20:24:00 2024 a rob

可以用 atrm 命令來刪除等待中的作業(yè)。

$ atrm 6
$ atq
# 1	Mon Jan  8 21:17:00 2024 = rob
# 3	Mon Jan  8 21:23:00 2024 = rob
# 4	Tue Jan  9 20:24:00 2024 a rob
# 5	Tue Jan  9 20:24:00 2024 a rob

定期執(zhí)行命令

at 命令可以在預設時間安排腳本執(zhí)行,但如果需要腳本在每天的同一時間運行或是每周一次、每月一次就需要使用新方法。

Linux系統(tǒng)使用cron程序來安排要定期執(zhí)行的作業(yè)。 cron程序會在后臺運行并檢查cron時間表,以獲知已安排執(zhí)行的作業(yè)。

可以使用crontab -e來編輯cron時間表:

$ crontab -e
# GNU nano 4.8                                 /tmp/crontab.hABXZo/crontab                                         
# # Edit this file to introduce tasks to be run by cron.
# # 
# # Each task to run has to be defined through a single line
# # indicating with different fields when the task will be run
# # and what command to run for the task

表中每一行表示一個定期執(zhí)行的任務,其格式為:

# m h  dom mon dow   command

m表示分鐘,h表示小時,dom表示幾號,mon表示月份,dow表示星期幾,*`表示任意日期。

分別是:minute (m), hour (h), day of month (dom), month (mon),# and day of week (dow) or use '*' in these fields (for 'any')

示例:

# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/

表示每周一凌晨5點將home.tgz解壓到/home路徑中。

每月最后一天執(zhí)行的任務設置方式,

# 00 12 * * * if [ ` date +%d -d tomorrow ` = 01 ] ; then ; command

列出crontab中的任務

crontab -l

如果待執(zhí)行的腳本對精確的執(zhí)行時間要求不高,用預配置的cron腳本目錄會更方便。在/etc/路徑下有4個基本目錄:cron.hourly、daily、monthlyweekly。譬如,如果腳本需要每天運行一次,只要將腳本復制到daily目錄,cron就會每天執(zhí)行它。

cron程序的唯一問題是它假定Linux系統(tǒng)是7×24小時運行的,如果系統(tǒng)存在關機重啟,有可能會錯誤定時任務,處理這種情況最好是能在開機時檢查是否有錯過的定時任務,而cron并不會去檢查,很多Linux發(fā)行版還包含了anacron程序可以解決這個問題

anacron程序只會處理位于cron目錄的程序,比如/etc/cron.monthly。它用時間戳來決定作業(yè)是否在正確的計劃間隔內運行了。每個cron目錄都有個時間戳文件,該文件位于/var/spool/anacron。

$ sudo cat /var/spool/anacron/cron.monthly
# 20240104

到此這篇關于Linux Shell任務控制的實現(xiàn)示例的文章就介紹到這了,更多相關Linux Shell任務控制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論