shell不允许输入空字符_shell脚本编程之控制脚本
點藍色字關注“CurryCoder的程序人生”
微信公眾號:CurryCoder的程序人生
歡迎關注我,一起學習,一起進步!
1.引言
目前為止,運行腳本的唯一方式是以實時模式在命令行界面上直接運行。但是,這并不是Linux上運行腳本的唯一方式。2.處理信號量Linux利用信號與運行在系統中的進程進行通信。不同的Linux信號以及Linux如何用這些信號來停止、啟動、終止進程。可以通過對腳本進行編程,使其在收到特定信號時執行某些命令,從而控制shell腳本的操作。
2.1 重溫Linux信號Linux系統和應用程序可以生成超過30個信號,下面列出了Linux編程時遇到的最常見Linux系統信號。
1信號??????????????????????值??????????????????????????描述默認情況下,bash shell會忽略收到的任何SIGQUIT(3)和SIGTERM(15)信號(正因為如此,交互式shell才不會意外停止)。但是,bash shell會處理收到的SIGHUP(1)和SIGINT(2)信號。a.如果bash shell收到了SIGHUP信號,比如你要離開一個交互式shell,它就會退出。但是在退出之前,它會將SIGHUP信號傳遞給所有由該shell所啟動的進程。
b.通過SIGINT信息,可以中斷shell。Linux內核會停止為shell分配CPU處理時間。這種情況發生時,shell會將SIGINT信號傳遞給所有由它所啟動的進程。
2.2 生成信號bash shell允許使用鍵盤上的組合鍵生成兩種基本的Linux信號,這個特性在需要停止或暫停失控程序時非常方便。
中斷進程:Ctrl+C組合鍵可以生成SIGINT信號,并將該信號發送給當前在shell中運行的所有進程,停止shell中當前運行的進程。如下例所示:
1暫停進程:可以在進程運行期間暫停進程,無需終止它。它可以在不終止進程的情況下,使你能夠深入腳本內部仔細觀察。Ctrl+Z組合鍵會生成一個SIGTSTP信號,暫停shell中運行的任何進程。暫停進程與中斷進程不同:暫停進程會讓程序繼續保留在內存中,并能從上次暫停的位置繼續運行。如下例所示:
1[njust@njust?~]$?sleep?10上述示例中,方括號中的數字是shell分配的作業號,shell將shell中運行的每個進程稱為作業,并為每個作業分配唯一的作業號。它會給第一個作業分配作業號1,第二個作業分配作業號2,依次類推。
如果你的shell會話中有一個已暫停的作業,在退出shell時,只要再輸入一遍exit命令bash會提醒你。如下所示:
1[njust@njust?~]$?sleep?10可以還有ps命令查看已經暫停的作業,如下所示:
1[njust@njust?~]$?sleep?10在S列(進程狀態)中,ps命令將已暫停作業的狀態顯示為T,可以通過已暫停作業的PID,就可以用kill命令來發送一個SIGKILL信號來終止它。如下所示:
1[njust@njust?~]$?kill?-9?36422.3 捕捉信號trap命令允許你來指定shell腳本要監控并從shell中攔截的Linux信號,如果腳本收到了trap命令中列出的信號,該信號不再由shell處理,而是交由本地處理。trap命令的格式如下:
1trap??commands?signals從上面trap命令的格式來看,在trap命令行上,只要列出想要shell執行的命令,以及一組用空格分開的待捕獲的信號即可。如下例所示:使用trap命令來忽略SIGINT信號,并控制腳本的行為。
1上面的示例程序使用trap命令在每次檢測到SIGINT信號時,會顯示一行簡單的文本消息。捕獲這些信號會阻止用戶用bash shell組合鍵來Ctrl+C來停止程序運行。2.4?捕獲腳本退出除了在shell腳本中捕獲信號,也可以在shell腳本退出的時候進行捕獲。要想捕獲shell腳本的退出,只要在trap命令后加上EXIT信號即可。如下例所示:
1上述示例程序中,當腳本運行到正常的退出位置時,捕獲就被觸發,shell會執行trap命令。如果提前退出腳本,同樣能捕獲到EXIT信號。
2.5?修改或移除捕獲
如果一個信號在捕獲被修改前接收到的,那么腳本仍然會根據最初的trap命令進行處理。如下例所示: 1可以刪除已經設置好的捕獲:只要在trap命令與希望恢復默認行為的信號列表之間加上兩個破折號即可,但如果信號是在捕獲被移除前接收到的,那么腳本會按照原先trap命令中的設置進行處理,如下例所示: 13.以后臺模式運行腳本一些腳本可能要執行很長時間,而我們又不希望在命令行界面一直等待腳本執行結束。于是,可以采用后臺運行的模式。在后臺模式中,進行運行時不會和終端會話上的STDIN、STDOUT、STDERR關聯。3.1 后臺運行腳本以后臺模式運行腳本只需要在命令后加一個&即可。如下例所示: 1當&符號放到命令后時,它會將命令和bash shell分離開,將命令作為系統中的一個獨立的后臺進行運行,結果中顯示的第一行解釋:[1]:shell分配給后臺進程的作業號;4280:Linux系統分配給進程的進程ID(PID),Linux系統上運行的每個進程都必須有一個唯一的PID;當后臺進程結束時,它會在終端上顯示出下面的一條信息,該消息表示作業的作業號及作業狀態Done,還有用于啟動作用的命令。1[1]+??完成??????????????????./bg1.sh注意:當后臺進程運行時,它仍然會使用終端顯示器來顯示STDOUT和STDERR消息,如下例所示: 13.2 運行多個后臺作業可以在命令行中同時啟動多個后臺作業,每次啟動新作業時,Linux系統都會為其分配一個新的作業號和PID。通過ps命令,可以看出所有腳本的狀態。如下例所示: 1[njust@njust?tutorials]$?./bg2.sh?&??./bg3.sh?&?./bg4.sh?&?ps在ps命令的輸出中,每一個后臺進程都和終端會話聯系在一起。如果終端會話退出,那么后臺進程也會隨之退出。如果希望運行在后臺模式的腳本在登出控制臺后能夠繼續運行,需要借助別的手段。4.在非控制臺下運行腳本有時候,你會想在終端會話中啟動shell腳本,然后讓腳本一直以后臺模式運行到結束,即使你已經退出了終端。可以使用nohup命令來實現。nohup命令運行了另外一個命令來阻斷所有發送給該進程的SIGHUP信號。這會在退出終端會話時,阻止進程退出。如下例所示:
1[njust@njust?tutorials]$?nohup?./bg2.sh?&當使用nohup命令時,如果關閉該會話,腳本會忽略終端會話發送過來的SIGHUP信號。由于nohup命令會解除終端與進程的關聯,進程也就不再同STDOUT和STDERR聯系在一起。為了保存該命令產生的輸出,nohup命令會自動將STDOUT和STDERR的消息重定向到一個名為nohup.out的文件中。nohup.out文件包含了通常會發送到終端顯示器上的所有輸出。如下所示: 1[njust@njust?tutorials]$?cat?nohup.out?5.作業控制作業控制:啟動、停止、終止及恢復作業的功能。通過作業控制,就能完全控制shell環境中所有進程的運行方式了。5.1 查看作業作業控制中的關鍵命令是jobs命令,jobs命令允許查看shell當前正在處理的作業。如下例所示: 1$$變量:顯示Linux系統分配給該腳本的PID。可以從命令行啟動該腳本,使用Ctrl-Z鍵來暫停腳本。利用&將另一個作業作為后臺進程啟動,然后將腳本的結果重定向到文件中。如下例所示:1[njust@njust?tutorials]$?./work1.sh?>?work1.out?&jobs命令可以查看分配給shell的作業,jobs命令會顯示上面兩個已停止/運行中的作業,以及它們的作業號和作業中使用的命令。如下所示:1[njust@njust?tutorials]$?jobs要想查看作業的PID,可以在jobs命令中加入-l選項。如下所示:1[njust@njust?tutorials]$?jobs?-ljobs命令參數如下所示:1參數????????????????????描述jobs命令輸出中的加號和減號,帶加號的作業會被當做默認作業。在使用作業控制命令時,如果未在命令行中指定任何作業號,該作業會被當成作業控制命令的操作對象。當前的默認作業完成處理后,帶減號的作業成為下一個默認作業。任何時候都只有一個帶加號的作業和一個帶減號的作業,不管shell中有多少個正在運行的作業。下例表示了下一個作業在默認作業移除時是如何成為默認作業的。如下例所示: 1[njust@njust?tutorials]$?./work1.sh?>?work1.out?&5.2 重啟停止的作業在bash作業控制中,可以將已停止的作業作為后臺進程或前臺進程重啟。前臺進程會接管你當前工作的終端,所以在使用該功能時要小心。要以后臺模式重啟一個作業,可以使用bg命令加上作業號。如下例所示:1[njust@njust?tutorials]$?./work1.sh?注意:當作業被轉入后臺模式時,并不會列出其PID。如果有多個作業,需要在bg命令后加上作業號。如下所示: 1[njust@njust?tutorials]$?./work1.sh?注意:當使用jobs命令時,它列出了作業及其狀態,即使是默認作業當前并沒有處于后臺模式。要以前臺模式重啟已暫停作業,可使用帶有作用號的fg命令。由于作業是以前臺模式運行的,直到該作業完成后,命令行界面才會出現提示符。如下所示: 1[njust@njust?tutorials]$?./work1.sh?6.調整謙讓度在多任務操作系統中,內核負責將CPU時間分配給系統上運行的每個進程。調度優先級是內核分配給進程的CPU時間。在Linux系統中,由shell啟動的所有進程的調度優先級默認都是相同的。調度優先級是一個整數值,從-20(最高優先級)~+19(最低優先級)。默認情況下,bash shell以優先級0來啟動所有進程。越低的值即優先級越高,獲得CPU時間的機會就越高。6.1 nice命令nice命令允許你設置命令啟動時的調度優先級,要讓命令以更低的優先級允許,只要用nice -n命令來指定新的優先級級別。如下例所示:1[njust@njust?tutorials]$?nice?-n?10?./work1.sh?>?work1.out?&注意:必須將nice命令和要啟動的命令放在同一行中。上例中,ps命令的輸出驗證了謙讓度值(NI列)已經被調整為10。但是,如果想要提高某個命令的優先級,nice命令會阻止普通用戶來提高命令的優先級。因為nice命令的-n選項并不是必須的,只需要在破折號后面跟上優先級即可。如下例所示:6.2 renice命令有時候需要改變系統上已運行命令的優先級,通過renice命令即可實現。它允許你指定運行進程的PID來改變它的優先級。如下例所示:
1[root@njust?tutorials]#?./work1.sh?&renice命令會自動更新當前運行進程的調度優先級,必須以root賬戶登錄后才能使用!renice也有一些限制:a.只能對屬于你的進程執行renice;b.只能通過renice降低進程的優先級;c.root用戶可以通過renice來任意調整進程的優先級;7.定時任務有時候,我們需要在某個預先設定的時間開始運行腳本,Linux系統提供了多個在預選時間運行腳本的方法:at命令和cron表。7.1 用at命令來計劃執行作業at命令允許指定Linux系統何時運行腳本,at命令會將作業提交到隊列中,指定shell何時運行該作業。at的守護進程atd會以后臺模式運行,檢查作業隊列來運行作業。atd守護進程會檢查系統上的一個特殊目錄/var/spool/at來獲取用at命令提交的作業。默認情況下,atd守護進程會每60s檢查一下該目錄。1.at命令的格式1at?[-f?filename]?time默認情況下,at命令會將STDIN的輸入放到隊列中。可以使用-f選項來指定用于讀取命令(腳本文件)的文件名。time參數指定了Linux系統何時運行該作業。如果你指定的時間已經錯過,at命令會在第二天的那個時刻運行指定的作業。如何指定時間?at命令能夠識別多種不同的時間格式。如下所示:a.標準的小時和分鐘格式,如21:00;
b.AM/PM指示符,如21:00 PM;c.特定可命令時間,如now noon midnight等;d.標準日期格式,如MMDDYY MM/DD/YY DD.MM.YYe.文本日期,如Jul 4或Dec 25;f.指定時間增量:當前時間+25 min、明天10:15 PM、10:15+7天在使用at命令時,該作業會被提交到作業隊列中。作業隊列會保存通過at命令提交的待處理的作業。針對不同的優先級,存在26種不同的作業隊列,作業隊列通過用小寫字母a~z和大寫字母A~Z來表示。作業隊列的字母排序越高,作業運行的優先級就越低(更高的nice值)。默認情況下,at的作業會被提交到a作業隊列。如果想以更高的優先級運行作業,可以用-q參數指定不同的隊列字母。2.獲取作業的輸出當作業在Linux系統上運行時,顯示器并不會關聯到該作業。取而代之的是,Linux系統會將提交該作業的用戶的電子郵箱地址作為STDOUT和STDERR。任何發到STDOUT或STDERR的輸出都會通過郵件發送給該用戶。如下例所示: 1使用e-mail作為at命令的輸出很不方便,因此在使用at命令時,最好在腳本中對STDOUT和STDERR進行重定向。如果不想在at命令中使用郵件或重定向,最好加上-M選項來屏蔽作業產生的輸出信息。如下所示: 13.列出等待的任務atq命令可以查看系統中有哪些作業在等待。如下所示: 1[njust@njust?tutorials]$?at?-M?-f?at1.sh?teatime4.刪除作業一旦知道哪些作業在作業隊列中等待,就能使用atrm命令來刪除等待中的命令。如下所示:
1[njust@njust?tutorials]$?atq7.2 設置需要定期執行的腳本使用at命令預設時間安排腳本執行很方便,但是如果想每天的同一時間都執行該腳本,就不再使用at命令不斷提交作業了。Linux系統使用cron程序來安排要定期執行的作業。cron程序會在后臺運行并檢查一個特殊的表(cron時間表),以獲得已安排執行的作業。1.cron時間表cron時間表采用一種特別的格式來指定作業何時運行,格式如下所示:
1min?hour?day?month?week?具體的命令cron時間表允許你使用特定值、取值范圍(如1~5)或者通配符(*)來指定條目。如下所示:
115?10?*?*?*?command??#?每天的10:15執行一次命令可以用三字符的文本值(mon、tue、wed、thu、fri、sat、sun)或數值(0為周日,6為周六)來指定week的值。如何設置一個在每個月的最后一天執行的命令?常用的方法是加一條使用date命令的if-then語句來檢查明天的日期是否為01。如下所示:100?12?*?*?*?if?[?`date?+%d?-d?tomorrow`?=?01?];?then?;?command具體的命令中必須指定要運行的命令或腳本的全路徑名,如下例所示:115?10?*?*?*?/home/njust/tutotials/test.sh?>?test.out2.構建cron時間表每個系統用戶都可以用自己的cron時間表來運行安排好的任務,Linux提供了crontab命令來處理cron時間表。要列出已有的cron時間表,可以用-l選項。如下所示:1[njust@njust?tutorials]$?crontab?-l默認情況下,用戶cron時間表文件并不存在。要為cron時間表添加條目,可以用-e選項。在添加條目時,crontab命令會啟動一個文本編輯器,使用已有的cron時間表作為文件內容。3.瀏覽cron目錄如果你創建的腳本對精確的執行時間要求不高,用預配置的cron腳本目錄會更方便。有4個基本目錄:hourly、daily、monthly、weekly。如果腳本需要每天執行一次,只要將腳本復制到daily目錄,cron就會每天執行它。如下所示: 1[njust@njust?~]$?ls?/etc/cron.*ly4.anacron程序cron程序的唯一問題是:它假設Linux是7*24小時運行的,除非將Linux系統當成服務器環境來運行,否則假設不會成立。如果某個作業在cron時間表中安排運行的時間已到,但這時Linux系統處于關機狀態,那么這個作業就不會執行。當系統開機時,cron程序不會再去運行那些錯過的作業。要解決這個問題,許多Linux發行版包含了anacron程序。如果anacron知道某個作業錯過了執行時間,它會盡快運行該作業。這個功能常用于日志維護的腳本。anacron程序只會處理位于cron目錄的程序,如/etc/cron.monthly。它使用時間戳來決定作業是否在正確的計劃間隔內運行。每個cron目錄都有一個時間戳文件,該文件位于/var/spool/anacron。如下所示:1[root@njust?njust]#?cat?/var/spool/anacron/cron.monthlyanacron程序使用自己的時間表(通常位于/etc/anacrontab)來檢查作業目錄。如下所示: 1[root@njust?njust]#?cat?/etc/anacrontabanacron時間表的基本格式如下所示:period:定義了作業多久運行一次,以天為單位。anacron程序用此來檢查作業的時間戳文件;
delay:指定系統啟動后anacron程序需要等待多少分鐘再開始運行錯過的腳本;
command:包含了run-parts程序(負責運行目錄中傳給它的任何腳本)和一個cron腳本目錄名;
identifier:一種特別的非空字符串,用于唯一標識日志消息和錯誤郵件中的作業;
1period?delay?identifier?command注意:anacron程序不會運行位于 /etc/cron.hourly的腳本。因為anacron程序不會處理執行時間需求小于一天的腳本。7.3 使用新shell啟動腳本如果每次運行腳本的時候都能夠啟動一個新的bash shell,將會非常方便。當用戶登錄bash shell時需要運行相關的啟動文件,基本上不同發行版的Linux系統按照下列順序所找到的第一個文件會被運行,其余的文件將會被忽略:
? ? a. $HOME/.bash_profile
? ? b.?$HOME/.bash_login
? ? c. ?$HOME/.profile
因此,需要將在登錄時運行的腳本放在上面的第一個文件中。每次啟動一個新的shell時,bash shell都會運行.bashrc文件。可以如下例所示進行驗證:
1.bashrc文件通常也是通過某個bash啟動文件來運行的。因為.bashrc文件會運行兩次:一次是當你登入bash shell時,另一次是當你啟動一個bash shell時。如果你需要一個腳本在兩個時刻都得以運行,可以把這個腳本放進該文件中。
8.資料下載[1]https://github.com/cdlwhm1217096231/Linux/tree/master/Shell%E8%84%9A%E6%9C%AC%E7%BC%96%E7%A8%8B覺得好看,請點這里↓↓↓
總結
以上是生活随笔為你收集整理的shell不允许输入空字符_shell脚本编程之控制脚本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: thinkPHP6.0 控制器请求方法延
- 下一篇: java class _Java Cla