Linux前後台作業切換及離線管理 Linux bash shell單一終端介面下,我們經常需要管理或同時完成多個作業,如一邊執行編譯,一邊實現資料備份,以及執行SQL查詢等其他的任務。所有的上述的這些工作我們可以在一個bash內實現,也就是說在同一個終端視窗完成。下面主要描述了Linux下前後台作業切換與管理以及作業在離線的情形下如何管理。 1、前後台作業的定義 前後台作業實際上對應的也就是前後台進程,因此也就有對應的pid。在這裡我們統稱為作業。 無論是前台作業還是後台作業,兩者都來自當前的shell,是當前shell的子程式。 下面是兩者的定義。 前台作業:可以由使用者參與互動及控制的作業我們稱之為前台作業。 後台作業:在記憶體可以自啟動並執行作業,使用者無法參與互動以及使用[ctrl]+c來終止,只能通過bg或fg來調用該作業。 2、幾個常用的作業命令 a、command & 直接讓作業進入後台運行 b、[ctrl]+z 將當前作業切換到後台 c、jobs 查看後台作業狀態 d、fg %n 讓後台啟動並執行作業n切換到前台來 d、bg %n 讓指定的作業n在後台運行 e、kill %n 移除指定的作業n "n" 為jobs命令查看到的job編號,不是進程id。 每一個job會有一個對應的job編號,編號在當前的終端從1開始分配。 job 編號的使用樣式為[n],後面可能會跟有 "+" 號或者 "-" 號,或者什麼也不跟。 "+" 號表示最近的一個job,"-" 號表示倒數第二個被執行的Job。注,"+" 號與 "-" 號會隨著作業的完成或添加而動態發生變化。 通過jobs方式來管理作業,當前終端的作業在其他終端不可見。 3、示範後台作業命令[python] a、直接將作業放入到後台(附加 & 符號) robin@SZDB:/tmp> tar -czvf temp.tar.gz tempSYBO2SZ.dbf & [1] 12500 robin@SZDB:/tmp> tempSYBO2SZ.dbf robin@SZDB:/tmp> #此時可進行其它操作,作業一旦完成,會彈出如下的提示 [1]+ Done tar -czvf temp.tar.gz tempSYBO2SZ.dbf robin@SZDB:/tmp> ls -hltr temp* -rwxr-xr-x 1 robin oinstall 490M 2013-05-02 17:48 tempSYBO2SZ.dbf -rw-r--r-- 1 robin oinstall 174M 2013-05-02 17:50 temp.tar.gz b、已經開始執行,但需要放入後台(使用[ctrl]+z) robin@SZDB:/tmp> tar -czvf temp2.tar.gz tempSYBO2SZ.dbf tempSYBO2SZ.dbf [1]+ Stopped tar -czvf temp2.tar.gz tempSYBO2SZ.dbf robin@SZDB:/tmp> jobs [1]+ Stopped tar -czvf temp2.tar.gz tempSYBO2SZ.dbf #下面同時發布兩個作業,並且在中途按下[ctrl]+z以便將當前作業提交到後台 robin@SZDB:/tmp> find /u02 -type f -size +100000k robin@SZDB:/tmp> find / -type f -size +100000k #再次查看當前的jobs時,jobs管理器裡出現了3個處於stopp狀態的job robin@SZDB:/tmp> jobs [1] Stopped tar -czvf temp2.tar.gz tempSYBO2SZ.dbf [2]- Stopped find / -type f -size +100000k [3]+ Stopped find /u02 -type f -size +100000k robin@SZDB:/tmp> jobs -l #使用-l參數查看當前shell下所有的作業以及對應的job number,進程pid [1] 32682 Stopped tar -czvf temp2.tar.gz tempSYBO2SZ.dbf [2]- 32687 Stopped find /u02 -type f -size +100000k [3]+ 32707 Stopped find / -type f -size +100000k #下面通過pid可以查看到對應的進程資訊 robin@SZDB:/tmp> ps -ef | grep 32707 | grep -v grep robin 32707 32095 0 09:48 pts/1 00:00:00 find / -type f -size +100000 robin@SZDB:/tmp> tty #當前終端的資訊為pts/1 /dev/pts/1 #開啟另外一個終端 robin@SZDB:~> tty /dev/pts/3 robin@SZDB:~> jobs #此時可以看到jobs命令無任何返回 robin@SZDB:~> ps -ef | grep 32707 | grep -v grep #僅僅根據進程id可以找到對應的作業 robin 32707 32095 0 09:48 pts/1 00:00:00 find / -type f -size +100000 #由上可知,對於當前shell下的jobs,僅當前shell(終端)可見 c、將後台作業切換到前台(fg命令) robin@SZDB:/tmp> fg #省略Job number的情形,則將預設的job切換到前台 find / -type f -size +100000k /u02/database/old/CNMMBOBK/undo/undotbsCNMMBOBK.dbf ...... [ctrl]+z robin@SZDB:/tmp> fg %1 tar -czvf temp2.tar.gz tempSYBO2SZ.dbf robin@SZDB:/tmp> jobs [2]- Stopped find /u02 -type f -size +100000k [3]+ Stopped find / -type f -size +100000k d、運行後台中暫停作業(bg命令) #前面有2個job處於stopped狀態,現在我們讓其在後台運行,直接輸入bg命令則預設的job繼續運行,否則輸入job編號,運行指定的job robin@SZDB:/tmp> bg 2 #輸入bg 2之後,可以看到原來的命令後被追加了& [2]- find /u02 -type f -size +100000k & robin@SZDB:/tmp> jobs [2]- Running find /u02 -type f -size +100000k & [3]+ Stopped find / -type f -size +100000k e、移除指定的作業n(kill) robin@SZDB:/tmp> jobs [3]+ Stopped find / -type f -size +100000k robin@SZDB:/tmp> kill -9 %3 #強制終止job 3,注意,此處的%不可省略 robin@SZDB:/tmp> jobs [3]+ Killed find / -type f -size +100000k robin@SZDB:/tmp> jobs #kill -9 表明強制終止指定的Job,-15則表明是正常終止指定的job。 kill -l 則列出kill能夠使用的所有訊號 #對於上述命令的詳細協助,使用 man command來擷取協助資訊 f、帶參shell指令碼的幕後處理 #下面是一個測試用的shell指令碼 robin@SZDB:~/dba_scripts/custom/bin> more echo_time.sh #!/bin/bash SID=$1 sqlplus -S scott/tiger@$1 <<EOF select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') today from dual; begin dbms_lock.sleep(300); end; / select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') today from dual; exit; EOF exit #直接執行帶參的shell指令碼 robin@SZDB:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO TODAY ------------------- 2013-05-03 11:07:48 [1]+ Stopped ./echo_time.sh CNMMBO #按下[ctrl]+z將其切換到後台 robin@SZDB:~/dba_scripts/custom/bin> jobs [1]+ Stopped ./echo_time.sh CNMMBO robin@SZDB:~/dba_scripts/custom/bin> kill -9 %1 #強制終止該job [1]+ Stopped ./echo_time.sh CNMMBO robin@SZDB:~/dba_scripts/custom/bin> jobs #此時該job已經被標記為killed [1]+ Killed ./echo_time.sh CNMMBO robin@SZDB:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO & #將shell指令碼參數之後跟 &符號即將job放入到後台 [1] 2233 robin@SZDB:~/dba_scripts/custom/bin> #此時依舊可以看到有輸出,但可以繼續後續操作 TODAY ------------------- 2013-05-03 11:08:25 robin@SZDB:~/dba_scripts/custom/bin> jobs [1]+ Running ./echo_time.sh CNMMBO & robin@SZDB:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO >temp.log 2>&1 & #最佳的辦法是直接將其輸出到記錄檔 [2] 2256 robin@SZDB:~/dba_scripts/custom/bin> jobs [1]- Running ./echo_time.sh CNMMBO & [2]+ Running ./echo_time.sh CNMMBO >temp.log 2>&1 & #下面來查看日誌,日誌中的兩次查詢正好相差5分鐘 robin@SZDB:~/dba_scripts/custom/bin> more temp.log TODAY ------------------- 2013-05-03 11:09:24 PL/SQL procedure successfully completed. TODAY ------------------- 2013-05-03 11:14:24 4、作業離線管理[python] 將作業(進程)切換到後台可以避免由於誤操作如[ctrl]+c等導致的job被異常中斷的情形,而離線管理主要是針對終端異常斷開的情形。 通常使用nohup命令來使得離線或登出之後,Job依舊可以繼續運行。也就是說nohup忽略所有掛斷(SIGHUP)訊號。 如果該方式命令之後未指定&符號,則job位於前台,指定&符號,則job位於後台。 #下面是使用nohup的樣本,可以省略日誌的輸出,因為原job的輸出會自動被nohup重新導向到預設的nohup.out記錄檔 robin@SZDB:~/dba_scripts/custom/bin> nohup ./echo_time.sh CNMMBO nohup: appending output to `nohup.out' #直接斷開終端,並重新串連一個新的終端視窗 robin@SZDB:~/dba_scripts/custom/bin> jobs #由於是一個新的終端,所以jobs無法看到任何作業 robin@SZDB:~/dba_scripts/custom/bin> ps -ef | grep echo_time.sh robin 2623 1 0 11:26 ? 00:00:00 /bin/bash ./echo_time.sh CNMMBO robin@SZDB:~/dba_scripts/custom/bin> more nohup.out #其輸出的日誌可以看到job被成功完成 TODAY ------------------- 2013-05-03 11:26:32 PL/SQL procedure successfully completed. TODAY ------------------- 2013-05-03 11:31:32 #下面使用nohup方式且將Job放入幕後處理,同時指定了記錄檔,則nohup使用指定的記錄檔,而不會輸出到預設的nohup.out robin@SZDB:~/dba_scripts/custom/bin> nohup ./echo_time.sh CNMMBO >temp2.log 2>&1 & [1] 3019 robin@SZDB:~/dba_scripts/custom/bin> jobs [1]+ Running nohup ./echo_time.sh CNMMBO >temp2.log 2>&1 &