shell腳本學習七(作業控制)

命令執行過裎中按 Ctrl+Z 快捷鍵,命令在後臺處於暫停狀態

進程: 

進程是一個程序對某個數據集的執行過程,是分配資源的基本單位。

 作業:

作業是用戶需要計算機完成的某項任務,是要求計算機所做工作的集合

作業的調度屬於高級調度,進程的調度屬於低級調度

作業就是從外存放到內存的一個過程,它可以包含一個或多進程。

        進程和作業的概念也有區別。一個正在執行的進程稱爲一個作業,而且作業可以包含一個或多個進程,尤其是當使用了管道和重定向命令。例如“nroff -man ps.1|grep kill|more”這個作業就同時啓動了三個進程。

        作業控制指的是控制正在運行的進程的行爲。比如,用戶可以掛起一個進程,等一會兒再繼續執行該進程。shell將記錄所有啓動的進程情況,在每個進程過程中,用戶可以任意地掛起進程或重新啓動進程。作業控制是許多shell(包括bash和tcsh)的一個特性,使用戶能在多個獨立作業間進行切換。

       一般而言,進程與作業控制相關聯時,才被稱爲作業。

 

       在大多數情況下,用戶在同一時間只運行一個作業,即它們最後向shell鍵入的命令。但是使用作業控制,用戶可以同時運行多個作業,並在需要時在這些作業間進行切換。這會有什麼用途呢?例如,當用戶編輯一個文本文件,並需要中止編輯做其他事情時,利用作業控制,用戶可以讓編輯器暫時掛起,返回shell提示符開始做其他的事情。其他事情做完以後,用戶可以重新啓動掛起的編輯器,返回到剛纔中止的地方,就象用戶從來沒有離開編輯器一樣。這只是一個例子,作業控制還有許多其他實際的用途。

 jobs:該命令用於查看當前終端後臺運行的任務。

ps:該命令用於查看瞬間進程的動態

控制腳本:

 1、處理信號

      1.1  重溫常見LInux信號

          信  號               值                     描  述
             1              SIGHUP             掛起進程

             2              SIGINT               終止進程 

             3             SIGQUIT             停止進程

             9              SIGKILL         無條件終止進程

            15          SIGTERM         儘可能終止進程

            17           SIGSTOP      無條件停止進程,但不是終止進程

            18           SIGTSTP      停止或暫停進程,但不終止進程

            19           SIGCONT      繼續運行停止的進程 
          默認情況下,bash shell會忽略收到的任何SIGQUIT (3)和SIGTERM (15)信號(正因爲這樣, 交互式shell纔不會被意外終止)。但是bash shell會處理收到的SIGHUP (1)和SIGINT (2)信號。

        如果bash shell收到了SIGHUP信號,比如當你要離開一個交互式shell,它就會退出。但在退 出之前,它會將SIGHUP信號傳給所有由該shell所啓動的進程(包括正在運行的shell腳本)。

        通過SIGINT信號,可以中斷shell。Linux內核會停止爲shell分配CPU處理時間。這種情況發 生時,shell會將SIGINT信號傳給所有由它所啓動的進程,以此告知出現的狀況。

       你可能也注意到了,shell會將這些信號傳給shell腳本程序來處理。而shell腳本的默認行爲 是忽略這些信號。它們可能會不利於腳本的運行。要避免這種情況,你可以腳本中加入識別信 號的代碼,並執行命令來處理信號。

       1.2  生成信號 

            ① 中斷進程

           Ctrl+C組合鍵會生成SIGINT信號,並將其發送給當前在shell中運行的所有進程。可以運行一 條需要很長時間才能完成的命令,然後按下Ctrl+C組合鍵來測試它

           

            Ctrl+C組合鍵會發送SIGINT信號,停止shell中當前運行的進程。sleep命令會使得shell暫停 指定的秒數,命令提示符直到計時器超時纔會返回。在超時前按下Ctrl+C組合鍵,就可以提前終 止sleep命令。

            ②  暫停進程 

            Ctrl+Z組合鍵會生成一個SIGTSTP信號,停止shell中運行的任何進程。停止(stopping)進程跟終止(terminating)進程不同:停止進程會讓程序繼續保留在內存中,並能從上次停止的位置繼續運行

              

           方括號中的數字是shell分配的作業號(job number)。shell將shell中運行的每個進程稱爲作業, 併爲每個作業分配唯一的作業號。它會給第一個作業分配作業號1,第二個作業號2,以此類推。
           如果你的shell會話中有一個已停止的作業,在退出shell時,bash會提醒你

              

          用ps命令來查看已停止的作業      

          在S列中(進程狀態),ps命令將已停止作業的狀態爲顯示爲T。這說明命令要麼被跟蹤,要麼被停止了。

          如果在有已停止作業存在的情況下,你仍舊想退出shell,只要再輸入一遍exit命令就行了。 shell會退出,終止已停止作業。或者,既然你已經知道了已停止作業的PID,就可以用kill命令 來發送一個SIGKILL信號來終止它

           

           在終止作業時,最開始你不會得到任何迴應。但下次如果你做了能夠產生shell提示符的操作 (比如按回車鍵),你就會看到一條消息,顯示作業已經被終止了。每當shell產生一個提示符時, 它就會顯示shell中狀態發生改變的作業的狀態。在你終止一個作業後,下次強制shell生成一個提示符時,shell會顯示一條消息,說明作業在運行時被終止了。

          

         1.3  捕獲信號 

           trap命令允許你來指定shell 腳本要監看並從shell中攔截的Linux信號。如果腳本收到了trap命令中列出的信號,該信號不再由shell處理,而是交由本地處理。 

           trap命令的格式是: 
                  trap commands signals   

          這裏有個簡單例子,展示瞭如何使用trap命令來忽略SIGINT信號,並控制腳本的行爲

               

          本例中用到的trap命令會在每次檢測到SIGINT信號時顯示一行簡單的文本消息。捕獲這些信號會阻止用戶用bash shell組合鍵Ctrl+C來停止程序

            正常運行:

                

           用戶主動使用Ctrl - C 嘗試中斷進程:

               

           此例中,每次使用Ctrl+C組合鍵,腳本都會執行trap命令中指定的echo語句,而不是處理該信號並 允許shell停止該腳本

           1.4 捕獲腳本退出

                除了在shell腳本中捕獲信號,也可以在shell腳本退出時進行捕獲。這是在shell完成任務時 執行命令的一種簡便方法。 要捕獲shell腳本的退出,只要在trap命令後加上EXIT信號就行

               

              

              當腳本運行到正常的退出位置時,捕獲就被觸發了,shell會執行在trap命令行指定的命令。 如果提前退出腳本,同樣能夠捕獲到EXIT

          1.5 修改或移除捕獲

               在腳本中的不同位置進行不同的捕獲處理,只需重新使用帶有新選項的trap命令即可

               

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

              

             移除捕獲:

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

            

           

           ------------------------------------------------------------------------------------------------------------------------------------

            也可以在trap命令後使用單破折號來恢復信號的默認行爲。單破折號和雙破折號都可以正常發揮作用

          --------------------------------------------------------------------------------------------------------------------------------------

          移除信號捕獲後,腳本按照默認行爲來處理SIGINT信號,也就是終止腳本運行。但如果信 號是在捕獲被移除前接收到的,那麼腳本會按照原先trap命令中的設置進行處理       

2、以後臺模式運行腳本

          2.1  後臺運行腳本

               後臺運行腳本 只用在運行命令上加上一個 & 符即可

               (  注意: 放入後臺執行的命令不能與前臺有交互,否則這個命令是不能在後臺執行的 )

              

             當&符放到命令後時,它會將命令和bash shell分離開來,將命令作爲系統中的一個獨立的後 臺進程運行。

             [1] 2884 

             方括號中的數字是shell分配給後臺進程的作業號。下一個數是Linux系統分配給進程的進程 ID(PID)。Linux系統上運行的每個進程都必須有一個唯一的PID。

             一旦系統顯示了這些內容,新的命令行界面提示符就出現了。你可以回到shell,而你所執行 的命令正在以後臺模式安全的運行。這時,你可以在提示符輸入新的命令

             當後臺進程結束時,它會在終端上顯示出一條消息: 
                  [1] +  Done                    sleep  2 

            這表明了作業的作業號以及作業狀態(Done),還有用於啓動作業的命令。

            注意,當後臺進程運行時,它仍然會使用終端顯示器來顯示STDOUT和STDERR消息

           (  即交互式界面仍然會顯示  )

            

           

           你會注意到上面兩個例子中,命令、腳本的輸出與shell提示符混雜在了一起。 

          處理方法: 最好是將STDOUT和STDERR進行重定向,避免這種雜亂的輸出

          

         在終端會話中使用後臺進程時一定要小心。注意,在ps命令的輸出中,每一個後臺進程都和 終端會話(pts/0)終端聯繫在一起。如果終端會話退出,那麼後臺進程也會隨之退出

       2.2  在非控制檯下運行腳本

           用nohup命令來實現,即使退出了終端會話腳本也會一直以後臺模式運行到結束

           原理就是:nohup命令運行了另外一個命令來阻斷所有發送給該進程的SIGHUP信號。這將會在退出終端會話時阻止進程退出

           當你使用nohup命令時,如果關閉該會話,腳本會忽略終端會話發過來的SIGHUP信號。
           由於nohup命令會解除終端與進程的關聯,進程也就不再同STDOUT和STDERR聯繫在一起。 爲了保存該命令產生的輸出,nohup命令會自動將STDOUT和STDERR的消息重定向到一個名爲 nohup.out的文件中         

          

         

          -------------------------------------------------------------------------------------------------------------------------------------------------------

       說明  如果使用nohup運行了另一個命令,該命令的輸出會被追加到已有的nohup.out文件中。當 運行位於同一個目錄中的多個命令時一定要當心,因爲所有的輸出都會被髮送到同一個 nohup.out文件中,結果會讓人摸不清頭腦

          ------------------------------------------------------------------------------------------------------------------------------------------------------- 

         

         

      2.3 作業控制

           在本篇博客的前面部分,你已經得知如何使用組合鍵停止shell中正在運行的作業。在作業停止後, Linux系統會讓你選擇是終止還是重啓。你可以用kill命令終止該進程。要重啓停止的進程需要 向其發送一個SIGCONT信號。 

         啓動、停止、終止以及恢復作業的這些功能統稱爲作業控制。通過作業控制,就能完全控制 shell環境中所有進程的運行方式了。本節將介紹用於查看和控制在shell中運行的作業的命令。 

         2.3.1 查看作業

            作業控制中的關鍵命令是jobs命令。jobs命令允許查看shell當前正在處理的作業。 

        

           腳本使用 $$ 變量來顯示Linux系統分配給該腳本的PID,然後進入循環,每次迭代都休眠10秒。
           可以從命令行中啓動腳本,然後使用Ctrl+Z組合鍵來停止腳本

           

           第二次使用同樣的腳本,利用&將另外一個作業作爲後臺進程啓動。出於簡化的目的,腳本的輸出被重定向到文件中,避免出現在屏幕上。( 此處如果不使用 > 重定向,即使將其放入後臺,仍會與前臺有互動產生輸出 )

           jobs命令可以查看分配給shell的作業。jobs命令會顯示這兩個已停止/運行中的作業,以及它們的作業號和作業中使用的命令。 

          查看作業的PID,可以在jobs命令中加入 -l 選項

       -------------------------------------------------------------------------------------------------------------------------------------------------------

                                          jobs命令參數

                           參  數                                           描  述
                              -l                              列出進程的PID以及作業號

                              -n                             只列出上次shell發出的通知後改變了狀態的作業

                              -p                             只列出作業的PID

                              -r                              只列出運行中的作業

                              -s                              只列出已停止的作業 

        -------------------------------------------------------------------------------------------------------------------------------------------------------

        你可能注意到了jobs命令輸出中的加號和減號。帶加號的作業會被當做默認作業。在使用作業控制命令時,如果未在命令行指定任何作業號,該作業會被當成作業控制命令的操作對象。
        當前的默認作業完成處理後,帶減號的作業成爲下一個默認作業。任何時候都只有一個帶加 號的作業和一個帶減號的作業,不管shell中有多少個正在運行的作業。

        下面例子說明了隊列中的下一個作業在默認作業移除時是如何成爲默認作業的。有3個獨立 的進程在後臺被啓動。jobs命令顯示出了這些進程、進程的PID及其狀態。注意,默認進程(帶 有加號的那個)是最後啓動的那個進程,也就是3號作業。 
        

       調用kill命令向默認進程發送了一個SIGHUP信號,終止了該作業。在接下來的jobs 命令輸出中,先前帶有減號的作業成了現在的默認作業,減號也變成了加號。

     2.3.2  重啓停止的作業

         在bash作業控制中,可以將已停止的作業作爲後臺進程或前臺進程重啓。前臺進程會接管你當前工作的終端( 交互式進程會佔用終端 ),所以在使用該功能時要小心了。

        要以後臺模式重啓一個作業,可用 bg命令加上作業號。

         

         bg命令將作業置於後臺模式。注意,當使用了jobs命令時,它列出了作業及其狀態,即便是默認作業當前並未處於後臺模式   (由上圖可以看出,使用bg命令之後腳本運行是緊接着以上開始,而不是從頭開始運行)

         要以前臺模式重啓作業,可用帶有作業號的 fg 命令。

      2.4  調整謙讓度

         在多任務操作系統中(Linux就是),內核負責將CPU時間分配給系統上運行的每個進程。調 度優先級(scheduling priority)是內核分配給進程的CPU時間(相對於其他進程)。在Linux系統 中,由shell啓動的所有進程的調度優先級默認都是相同的。 調度優先級是個整數值,從-20(最高優先級)到+19(最低優先級)。默認情況下,bash shell 以優先級0來啓動所有進程。

      -------------------------------------------------------------------------------------------------------------------------------------------------------

       竅門 最低值-20是最高優先級,而最高值19是最低優先級,這太容易記混了。只要記住那句俗 語“好人難做”就行了。越是“好”或高的值,獲得CPU時間的機會越低。

       -------------------------------------------------------------------------------------------------------------------------------------------------------

       2.4.1  nice命令 ( 用作升高NI值,即降低優先級 )( 只有一個選項-n )

          nice命令允許設置命令啓動時的調度優先級。要讓命令以更低的優先級運行,只要用nice 的-n命令行來指定新的優先級級別。 

          UID是用戶ID,PID是進程ID,PPID是父進程ID

         

         注意,必須將nice命令和要啓動的命令放在同一行中。ps命令的輸出驗證了謙讓度值(NI 列)已經被調整到了10

         nice命令也可以直接在破折號跟優先級值,例如  nice  -10   ……

       2.5.2  renice命令

           renice允許通過運行進程的PID來改變它的優先級,nice是通過進程名

           

           renice命令會自動更新當前運行進程的調度優先級。

          和nice命令一樣,renice命令也有一 些限制:

                只能對屬於用戶本身的進程執行renice;

                只能通過renice降低進程的優先級;

                root用戶可以通過renice來任意調整進程的優先級。

         如果想完全控制運行進程,必須以root賬戶身份登錄或使用sudo命令。 

       2.6  定時運行作業

         2.6.1  用at 命令來計劃執行作業 ( 只會執行一次 )

              at命令允許指定Linux系統何時運行腳本。at命令會將作業提交到隊列中,指定shell何時運 行該作業。at的守護進程atd會以後臺模式運行,檢查作業隊列來運行作業。大多數Linux發行 版會在啓動時運行此守護進程。

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

             1. at命令的格式

                 at命令的基本格式非常簡單: 
                               at [-f filename] time              

選項:    -m     當計劃任務結束後發送郵件給用戶

              -l        查看用戶計劃任務

               -d  (跟任務編號) 刪除用戶計劃任務

               -c       查看at任務具體內容

            

           

             默認情況下,at命令會將STDIN的輸入放到隊列中。你可以用-f參數來指定用於讀取命令(腳本文件)的文件名。

             time參數指定了Linux系統何時運行該作業。如果你指定的時間已經錯過,at命令會在第二天的那個時間運行指定的作業。

            在如何指定時間這個問題上,非常靈活。at命令能識別多種不同的時間格式。

                  標準的小時和分鐘格式,比如10: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

                            明天10:15 PM

                            10:15+7天

              在你使用at命令時,該作業會被提交到作業隊列(job queue)。作業隊列會保存通過at命令 提交的待處理的作業。針對不同優先級,存在26種不同的作業隊列。作業隊列通常用小寫字母a~z 和大寫字母A~Z來指代。 

           -------------------------------------------------------------------------------------------------------------------------------------------------------

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

          --------------------------------------------------------------------------------------------------------------------------------------------------------

             2. 獲取作業的輸出

                 at命令利用sendmail應用程序來發送郵件。如 果你的系統中沒有安裝sendmail,那就無法獲得任何輸出!因此在使用at命令時,最好在腳本 中對STDOUT和STDERR進行重定向

                -M 可以屏蔽作業產生的輸出信息

             3.列出等待的作業

                 atq命令可以查看系統中有哪些作業在等待( 第一列排序越高優先級越低 )

                 

             4.  刪除作業

                  一旦知道了哪些作業在作業隊列中等待,就能用atrm命令來刪除等待中的作業

                  

          2.7安排需要定期執行的腳本( 週期執行 )

                   Linux系統使用cron程序來安排要定期執行的作業。cron程序會在後臺運行並檢查一個特殊的 表(被稱作cron時間表),以獲知已安排執行的作業。 

          2.7.1 使用cron制定計劃任務之前需要確保crond服務是開啓的,否則計劃任務不會被執行

            

用法:    crontab  [-u 用戶] [-l | -r | -e ]

選項:       -u            指定計劃任務的用戶,默認爲當前用戶

               -l             查看計劃任務

               -r            刪除計劃任務

               -e            編輯計劃任務

               -i             使用-r刪除計劃任務時要求用戶確認刪除

     

           例:(cron文件的編輯器是vim)

                $crontab  -e

                 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

說明

      如何設置一個在每個月的最後一天執行的命令呢?因爲你無法設置 dayofmonth的值來涵蓋所有的月份。這個問題困擾着Linux和Unix程序員,也激發了不少解 決辦法。常用的方法是加一條使用date命令的if-then語句來檢查明天的日期是不是01:
     00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command  

      它會在每天中午12點來檢查是不是當月的最後一天,如果是,cron將會運行該命令。 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

       

            命令列表必須指定要運行的命令或腳本的全路徑名。你可以像在普通的命令行中那樣,添加 任何想要的命令行參數和重定向符號。 
                15 10 * * * /home/rich/test4.sh > test4out

           cron程序會用提交作業的用戶賬戶運行該腳本。因此,你必須有訪問該命令和命令中指定的 輸出文件的權限。

         2.7.2  構建cron時間表 

             每個系統用戶(包括root用戶)都可以用自己的cron時間表來運行安排好的任務。Linux提供 了crontab命令來處理cron時間表。要列出已有的cron時間表,可以用-l選項。 

           默認情況下,用戶的cron時間表文件並不存在。要爲cron時間表添加條目,可以用 -e 選項。 在添加條目時,crontab命令會啓用文本編輯器vim,使用已有的cron時間表作爲文件內容(或者是一個空文件,如果時間表不存在的話)。  

         2.7.3  瀏覽cron目錄

           如果你創建的腳本對精確的執行時間要求不高,用預配置的cron腳本目錄會更方便。有4個基本目錄:hourly、daily、monthly和weekly

             

           因此,如果腳本需要每天運行一次,只要將腳本複製到daily目錄,cron就會每天執行它。 

         2.7.4  anacron程序

              cron程序的唯一問題是它假定Linux系統是7×24小時運行的。除非將Linux當成服務器環境來 運行,否則此假設未必成立。

            如果某個作業在cron時間表中安排運行的時間已到,但這時候Linux系統處於關機狀態,那麼 這個作業就不會被運行。當系統開機時,cron程序不會再去運行那些錯過的作業。要解決這個問 題,許多Linux發行版還包含了anacron程序。

           如果anacron知道某個作業錯過了執行時間,它會盡快運行該作業。這意味着如果Linux系統 關機了幾天,當它再次開機時,原定在關機期間運行的作業會自動運行。

          這個功能常用於進行常規日誌維護的腳本。如果系統在腳本應該運行的時間剛好關機, 日誌文件就不會被整理,可能會變很大。通過anacron,至少可以保證系統每次啓動時整理日誌文件。

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

                  

           anacron程序使用自己的時間表(通常位於/etc/anacrontab)來檢查作業目錄                                                                                

        anacron時間表的基本格式和cron時間表略有不同: 
                         period delay identifier command

               period條目定義了作業多久運行一次,以天爲單位。anacron程序用此條目來檢查作業的時間 戳文件。delay條目會指定系統啓動後anacron程序需要等待多少分鐘再開始運行錯過的腳本。 command條目包含了run-parts程序和一個cron腳本目錄名。run-parts程序負責運行目錄中傳給它的 任何腳本。

             注意,anacron不會運行位於/etc/cron.hourly的腳本。

               這是因爲anacron程序不會處理執行時間 需求小於一天的腳本。

               identifier條目是一種特別的非空字符串,如cron-weekly。它用於唯一標識日誌消息和錯誤 郵件中的作業。 

    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章