團隊開發配合SVN HOOKS同步更新在線服務器源碼
最近為了協調整個開發團隊的開發過程,讓團隊協作更加流暢,考慮減少開發人員更新代碼維護代碼的中間環節,於是考慮使用了SVN服務端HOOKS
SVN服務端的 HOOKS 存在於每個 Project 倉庫的hooks目錄,裏面的 *.tmpl 是hooks腳本模板,我使用的是 windows 來做內網源碼版本 服務器系統,所以使用 *.bat 批處理文件來做 Hooks腳本! 但是總所周知 *.bat 批處理文件能執行的任務有限,所以我的批處理只是吧參數引導到PHP腳本上,由PHP腳本來實現我所需要的結果。
一、首先提高 svn 服務程序的權限,修改 "服務" 中 SVN 服務程序的登錄帳戶為超級管理員
二、編寫批處理。因為我只是需要在開發人員提交腳本後執行我的任務,所以只編寫了 post-commit.bat 批處理引導到了PHP腳本 post-commit.php上CODE:
@echo off
setlocal
SET PHP=E:\PHP5\php.exe
%PHP% -f %1\hooks\post-commit.php %*
關於hooks腳本,各位可以看這裏 http://www.subversion.org.cn/svn ... #svn.ref.reposhooks
三、建立 post-commit.php 在每次提交試執行判斷是否需要執行同步操作
我這裏加了 SVN 賬戶判斷,以便只有特定的用戶才有權限向線上服務器同步源碼
還加了[UPTO_RUN_SERVER] 標記,只有特定的用戶在提交時,加入了這個標記才會觸發同步到在線服務器的工作
四、建立一個臨時目錄用於從版本倉庫抽取需要更新的文件,如:E:\svn_tmp\MY_PROJECT_NAME
五、至於如何在團隊協同開發中部署這個應用,或如何更合理有效和安全,各位可以發揮一下想象力
以下是 post-commit.php 代碼的主要部分,有BUG僅供參考
[php]
<?php
//-----------------------------
// 初始化設置
//-----------------------------
//臨時更新目錄,用於svn checkout 得到最新的文件後,上傳到FTP
$TMP_UPDATE_DIR = "E:\\svn_tmp\\MY_PROJECT_NAME";
//獲得當前更新的log
$svnlook_log = "\"C:\\Program Files\\VisualSVN Server\\bin\\svnlook.exe\" log -r {$argv[2]} {$argv[1]}";
//獲得當前更新者帳戶名
$svnlook_author = "\"C:\\Program Files\\VisualSVN Server\\bin\\svnlook.exe\" author -r {$argv[2]} {$argv[1]}";
//更新最新的源碼到臨時更新目錄
$svn_update = "\"C:\\Program Files\\VisualSVN Server\\bin\\svn.exe\" update -r {$argv[2]} {$TMP_UPDATE_DIR}";
//有權限更新到運行服務器的svn帳戶
$upto_run_managers = array('terry39', 'user02', 'user03', 'user04');
//更新狀態記錄文件
$update_status_file = "E:\\svn_tmp\\MY_PROJECT_NAME_update_status.txt";
$output = array();
exec($svnlook_log, $output);
$log = $output;
$output = array();
exec($svnlook_author, $output);
$author = $output;
//-----------------------------
// 函數
//-----------------------------
/**
* 在FTP服務器上創建目錄
*
* @author terry39
*/
function ftp_create_dir($path)
{
global $ftp;
$dir=split("/", $path);
$path="";
$ret = true;
for ($i=0;$i<count($dir);$i++)
{
$path.="/".$dir[$i];
if(!@ftp_chdir($ftp,$path)){
@ftp_chdir($ftp,"/");
if(!@ftp_mkdir($ftp,$path)){
$ret=false;
break;
}
}
}
return $ret;
}
/**
* 刪除 FTP 中指定的目錄
*
* @param resource $ftp_stream The link identifier of the FTP connection
* @param string $directory The directory to delete
*
* @author terry39
*/
function ftp_rmdirr($ftp_stream, $directory)
{
if (!is_resource($ftp_stream) ||
get_resource_type($ftp_stream) !== 'FTP Buffer') {
return false;
}
// Init
$i = 0;
$files = array();
$folders = array();
$statusnext = false;
$currentfolder = $directory;
// Get raw file listing
$list = ftp_rawlist($ftp_stream, $directory, true);
foreach ($list as $current) {
if (empty($current)) {
$statusnext = true;
continue;
}
if ($statusnext === true) {
$currentfolder = substr($current, 0, -1);
$statusnext = false;
continue;
}
$split = preg_split('[ ]', $current, 9, PREG_SPLIT_NO_EMPTY);
$entry = $split[8];
$isdir = ($split[0]{0} === 'd') ? true : false;
// Skip pointers
if ($entry === '.' || $entry === '..') {
continue;
}
if ($isdir === true) {
$folders[] = $currentfolder . '/' . $entry;
} else {
$files[] = $currentfolder . '/' . $entry;
}
}
foreach ($files as $file) {
ftp_delete($ftp_stream, $file);
}
rsort($folders);
foreach ($folders as $folder) {
ftp_rmdir($ftp_stream, $folder);
}
return ftp_rmdir($ftp_stream, $directory);
}
/**
* 把更新到的文件列表上傳到服務器上
*
* 更新的同時記錄更新日志,如過有一個文件或者目錄更新失敗,則返回錯誤
*
* @param array $update_list
* @return bool
*
* @author terry39
*/
function update_to_ftp($update_list)
{
global $argv, $ftp, $author_name, $TMP_UPDATE_DIR;
$ftp_update_logfile='E:\svn_tmp\ftp_MY_PROJECT_NAME_upload.log'; //執行更新的日志文件
$ftp_root_dir = '/'; //服務器上的地址源碼對應的起始目錄
$log = "";
$log .= date('Y-m-d H:i:s') . " BEGIN UPDATE TO FTP\n";
$log .= date('Y-m-d H:i:s') . " Reversion: {$argv[2]}\n";
$log .= date('Y-m-d H:i:s') . " Author: {$author_name}\n";
$ftp = ftp_connect('FTP服務器地址');
$ftp_login = ftp_login($ftp, 'FTP賬戶', 'FTP密碼');
if($ftp && $ftp_login){
$log .= date('Y-m-d H:i:s') . " Connected to FTP Server Success\n";
}else{
$log .= date('Y-m-d H:i:s') . " Connected to FTP Server False\n";
$log .= date('Y-m-d H:i:s') . " UPDATE FALSE\n";
$log .= date('Y-m-d H:i:s') . " QUIT UPDATE\n\n";
return false;
}
$result = true;
foreach($update_list as $file_cmd){
if(substr($file_cmd, 0, 6) == 'Update') continue; //這裏有最後一行的 Update Reversion NNN 要忽略
$file_cmd = trim($file_cmd);
$cmd = substr($file_cmd, 0, 1);
$file = trim(substr($file_cmd, 1));
$from = $file;
$file = substr($file, strlen($TMP_UPDATE_DIR) + 1); //去掉路徑中的開頭 $TMP_UPDATE_DIR 路徑
$filename = is_dir($from) ? null : array_pop(explode('/', $file));
$to = $ftp_root_dir . str_replace("\\", "/", $file);
//計算出路徑並創建FTP目錄 (如果不存在的話)
$dir = is_dir($from) ? $to : dirname($to);
if(!@ftp_chdir($ftp,$dir)){
$log .= date('Y-m-d H:i:s') . " FTP_MKD\t{$dir}\n";
ftp_create_dir($dir); //創建目錄
}
if(is_dir($from)) continue;
//更新或創建文件
if($cmd == "U" || $cmd == "A"){
$result = $result && ftp_put($ftp, $to, $from, FTP_BINARY);
//記錄日志
$log .= date('Y-m-d H:i:s') . " FTP_PUT\t{$from}\t{$to}" . ($result ? "\tSUCCESS\n" : "\tFALSE\n");
//刪除文件或目錄
}else if($cmd == "D"){
//-------------------------------
// 這裏要判斷目標是目錄還是文件
//-------------------------------
if(@ftp_chdir($ftp,$to)){
$r = ftp_rmdirr($ftp, $to);
$log .= date('Y-m-d H:i:s') . " FTP_RMD\t{$to}" . ($r ? "\tSUCCESS\n" : "\tFALSE\n");
}else{
$result = $result && ftp_delete($ftp, $to);
//記錄日志
$log .= date('Y-m-d H:i:s') . " FTP_DEL\t{$to}" . ($result ? "\tSUCCESS\n" : "\tFALSE\n");
}
}else{
$log .= date('Y-m-d H:i:s') . " UNKNOWN CMD\t{$cmd}\n";
continue;
}
}
//記錄最後一次更新成功的版本
if($result){
$log .= date('Y-m-d H:i:s') . " UPDATE SUCCESS\n";
}else{
$log .= date('Y-m-d H:i:s') . " UPDATE FALSE\n";
}
$log .= date('Y-m-d H:i:s') . " END UPDATE\n\n";
file_put_contents($ftp_update_logfile, $log, FILE_APPEND);
return $result;
}
//-----------------------------
// 判斷並執行同步更新
//-----------------------------
//取得當前更新者帳戶名,判斷是否有權限更新到運行服務器
$author_name = $author[count($author) -1];
if(in_array($author_name, $upto_run_managers)){
//查看log中是否包含 [UPTO_RUN_SERVER] 指令標記
if(strpos(implode("\n", $log), '[UPTO_RUN_SERVER]') !== false){
//-------------------------------------------
// 准備開始同步更新在線服務器上的文件
//-------------------------------------------
$new_rev = $argv[2];
if(!file_exists($update_status_file)){
file_put_contents($update_status_file, '1|1');
}
$update_status = explode('|', file_get_contents($update_status_file));
//當記錄的更新狀態為更新成功的版本號{$update_status[0]} 比最後一次更新的版本號 {$update_status[1]} 小時
//還原臨時更新目錄到最後一次更新成功的版本 {$update_status[0]},然後再 update 獲得更新文件列表
//然後提交到在線服務器
if($update_status[0] < $update_status[1]){
$svn_update_r = "\"C:\\Program Files\\VisualSVN Server\\bin\\svn.exe\" update -r {$update_status[0]} {$TMP_UPDATE_DIR}";
exec($svn_update_r);
}
$output = array();
exec($svn_update, $output);
$update = $output;
//這裏根據update列表更新服務器上的文件
$update_success = true;
$update_success = update_to_ftp($update);
//記錄更新後的更新狀態到到文件
if($update_success){
file_put_contents($update_status_file, "{$new_rev}|{$new_rev}");
}else{
file_put_contents($update_status_file, "{$update_status[0]}|{$new_rev}");
}
}
}
?>
[/php]
- 9月 04 週六 201015:47
團隊開發配合SVN HOOKS同步更新在線服務器源碼
- 1月 02 週六 201014:56
Centos5.X 小筆記
#時間的設置
yum -y install ntp
ntpdate 210.72.145.44 && clock -w
- 更新套件
yum update
- 安裝套件
yum install
- 升級套件
yum upgrade
- 移除套件
yum remove
- 清除暫存套件 /var/cache/yum
yum clean
- 列出所有套件
yum list
- 列出可更新套件
yum list updates
- 列出已安裝套件
yum list installed
- 檢查可更新套件名稱
yum check-update
- 列出所有套件資訊
yum info
- 列出可更新套件資訊
yum info updates
- 列出已安裝套件
yum info installed
- 列出已安裝但不在 Yum Repository 套件資訊
yum info extras
- 列出套件提供檔案清單
yum provides
群组安装功能:
yum grouplist
yum groupinstall "Web Server"幾個查看 Linux 系統資訊或 Kernel 版本的方法:(轉載 http://jinnsblog.blogspot.com/2008/10/check-linux-kernel-version.html)
- uname -a
可用man uname查尋其相關參數的用法,-a是列出所有系統相關的資訊,或者可到鳥哥的私房菜去朝聖。- uname -r -r是列出精簡敘述
- cat /proc/version
- cat /etc/issue
下圖是各指令的結果範例:
cat /etc/redhat-release
查看 linux版本(以CentOS為例)
#/root$ cat /etc/redhat-release
CentOS release 5.2 (Final)
- 1月 02 週六 201014:46
Centos5.2升级到Centos5.3
Centos5.2升级到Centos5.3
當由 cnetos 5.2 升級至 5.3 時,rpm 可能會出現問題:”rpmdb: unable to lock mutex: Invalid argument”。為避免以上問題,請先將 glibc 升級,然後更新整個安裝.
yum clean all
yum update glibc*
yum update yum* rpm* python*
yum clean all
yum update kernel*
yum update
shutdown -r now使用 ssh 進行遙距升級時,請考慮採用主機升級來減低中途斷線的影響.
- 12月 08 週一 200812:04
Linux 開機,關機,登入,登出 細項說明
Linux 開機,關機,登入,登出
【::開機::】
‧GRUB - GRand Unified Bootloader (開機管理程式)
‧GRUB設定檔 /boot/grub/menu.lst (或 /boot/grub/grub.conf)
‧GRUB預設將Windows系統設為Other。
‧進入單人模式:在GRUB選單中按 a 鍵,並在命令後加入 s 即可,命令列如下:
grub append> ro root=LABEL=1 rhgb quiet s
menu.lst 檔內容:
=========================
default=0 (預設開機的作業系統)
timeout=5 (開機選單在timeout指定秒數結束時仍沒選擇時,自動進入default的作業系統)
splashimage=(hd0,1) /boot/grub/splash.xpm.gz (開機選單的背景圖片)
#hiddenmenu (將開機選單隱單,在timeout結束時自動進入default作業系統,加#預設關閉)
(以下會根據安裝的作業系統而不同)
title Fedora Core (2.6.9-1.667) (選單名稱)
root(hd0,1) (存放系統核心的分割區)
kernel /boot/vmlinuz-2.6.9-1.667 ro root=LABEL/12 rhgb quiet (指定要載入的核心及掛載系統的根目錄)
initrd /boot/initrd-2.6.9-1.667.img
title Other (Windows分割區)
rootnoverify (hd0,0) (指定開機磁碟)
chainloader +1 (啟動該分割區中第一個磁區的開機程式)
makeactive (設為Active)
=========================
改變開機進入的執行模式:開啟 /etc/inittab ,修改「 id:5:initdefault: 」的 runlevel
runlevels共七種模式:
0 - halt (關機,不能設定這個選項,不然一開機就關機了^^")
1 - single user mode (單人模式)
2 - Multiuser, without NFS (和模式3同為多人多工模式,但不提供網路連線)
3 - Full multiuser mode (文字全多工)
4 - unused (保留)
5 - X11 (X Window 圖形模式)
6 - reboot (重開機,一樣不能設定這個選項,否則一開機就重開)
‧在文字模式時,可直接執行 init 1~6 來立即執行runlevel。
‧在文字模式要進入圖形模式:startx (或以root執行gdm或kdm)。
‧若要啟動第二個 X Window:startx --:1 (第三個 startx --:2 依此類推)
【::登入-登出::】
‧命令提示字元 # 表示此帳號為「系統管理員」;$ 表示「一般使用者」。
#login:登入系統。(若在 /etc 底下含有名稱為 nologin 的檔案時,系統只允許root登入。)
#logout:登出系統。
#exit:退出shell,當退出所有shell時,相當於logout。
【::關機::】
#halt [-dfinpw]:關閉系統。
-d 不要在wtmp(登入記錄檔)中記錄。
-f 強制關閉系統。
-i 先關閉全部的網路介面,再關閉系統。
-n 不執行sync(將記憶體中的資料寫入硬碟)。
-p 關閉系統後,關閉電源。
-w 僅在wtmp中記錄,而不結束系統。
#reboot [-dfinw]:重新開機。
-d 重開時不把資料寫入記錄檔 /var/tmp/wtmp 。
-f 強制重開。
-i 在重開前,先關閉網路介面。
-n 在重開前,不檢查是否有未結束的程序。
-w 測試,只把重開機的資料寫入 /var/log/wtmp 記錄檔。
#shutdown [-cfFhknr] [-t 秒數] [時間] [警告訊息]:系統關機(功能較多)。
-c 取消在背景執行的shutdown指令(取消前景shutdown可用ctrl + c)。
-f 重新啟動時不執行 fsck。
-F 重新啟動時執行 fsck。
-h 關機。
-k 僅送出訊息,不關機。
-n 不呼叫init程序進行關機。(一般關機程序是由shutdown呼叫init來關機,不建議)
-r 重開機。
-t 秒數 送出警告訊息和結束程序間要隔多少秒。
時間 設定多久後執行shutdown,時間參數有 hh:mm 或 +m (now 表示立即執行)。
警告訊息 送出警告訊息給使用者。
‧Ctrl + Alt + Del 也可重新開機,若要取消,須編輯 /etc/inittab
ca::ctrlaltdel:/sbin/shutdown -t3 -r now (將此行註解掉 #)
- 10月 03 週五 200823:40
RedHat/Centos - 關機流程 詳細步驟
一. 關機流程
Linux 運作時, 不可以直接將電源關閉, 否則, 可能會損毀檔案系統.
因此, 必須按照正常的程式關機:
觀察系統使用情形(也許當時, 正有使用者做著重要的工作呢!)
通知線上使用者, 本機即將關閉. (如果, 使用者眾多, 應該給予多一點的緩時間)
使用正確的 shutdown 指令.
關機使用的指令是 shutdown.
shutdown 以一種安全的方式關閉主機系統.
它會通知所有已登入的user, 主機即將關閉, 並且會將登入(login)的活動予以凍結.
shutdown 允許你:
選擇關機、重新開機或進入單人操成模式
設定關機時間: 可以設定成現在立刻關機, 也可以設定某一個特定的時間,
可以自訂關機之前, 傳送給線上 user 的警告訊息
可以只送警訊息, 作勢嚇嚇user, 但卻不是真的要關機. 因為, 有時, 你可能想要做一些試驗, 不想有其他 user 擾.
可以選擇是否要 fsck 檢查檔案系統
當 shutdown 開始執行後, 系統會以 SIGTERM 訊號通知所有的行程(processes), 主機即將關閉.
這麽做是必要的, 因為, 如此一來, 一些在執行中的程式, 才能即時存檔、清除暫存檔或將仍在記憶體中的資料趕快寫入硬碟中(flush).
shutdown 以訊號通知 init, 要求 init 要切換 runlevel, 來達成上述目的.
如果是關機(halt), 則切換到 runlevel 0; 若是重新開機(reboot), 則切換到 runlevel 6; 若是單人模式(single), 則切換到 runlevel 1.
然後就交給相關 runlevel 中的 script檔, 完成最後的關機事項.
若欲知各 runlevel 的定義情形, 可參考 /etc/inittab.
二. 關機指令.
/sbin/shutdown [-t 秒數] [-rkhncfF] 時間 [警告訊息]
-t 秒數 : 設定在切換至不同的runlevel之前, 警告和刪除二訊號之間的延遲時間(秒).
-k : 僅送出警告訊息文字, 但不是真的要 shutdown.
-r : shutdown 之後重新開機.
-h : shutdown 之後關機.
-n : 不經過 init , 由 shutdown 指令本身來做關機動作.(不建議你用)
-f : 重新開機時, 跳過 fsck 指令, 不檢查檔案系統.
-F : 重新開機時, 強迫做 fsck 檢查.
-c : 將已經正在 shutdown 的動作取消.
例子:
shutdown -r now 立刻重新開機
shutdown -h now 立刻關機
shutdown -k now 'Hey! Go away! now....' 發出警告訊息, 但沒有真的關機
shutdown -t3 -r now 立刻重新開機, 但在警告和刪除processes 之間, 延遲3秒鐘.
shutdown -h 10:42 'Hey! Go away!' 10:42 分關機
shutdown -r 10 'Hey! Go away!' 10 分鐘後關機
shutdown -c 將剛才下的 shutdown 指令取消,必須切換至其他tty, 登入之後, 才能下此一指令.
shutdown now 切換至單人操作模式(不加任何選項時)
注意事項:
時間參數務必要加: 不是用 now, 便是用 hh:mm 或 mm
now 其實就是 0 的意思.
不加任何選項的話, 會進入 runlevel 1, 即單人操作模式.
--------------------------------------------------------------------------------
關機命令如下,第一種是將關機作為一種任務,每天自動執行;第二種是若干小時後關機。樓主您自己選擇一種吧:
第一種方法:
用 crontab命令就可以了,下面看一下它的詳細用法。名稱 : crontab 使用權限 : 所有使用者 使用方式 : crontab [ -u user ] file crontab [ -u user ] { -l | -r | -e } 說明 : crontab 是用來讓使用者在固定時間或固定間隔執行程式之用,換句話說,也就是類似使用者的時程表。-u user 是指設定指定 user 的時程表,這個前提是你必須要有其許可權(比如說是 root)才能夠指定他人的時程表。如果不使用 -u user 的話,就是表示設定自己的時程表。餐數 : -e : 執行文字編輯器來設定時程表,內定的文字編輯器是 VI,如果你想用別的文字編輯器,則請先設定 VISUAL 環境變數來指定使用那個文字編輯器(比如說 setenv VISUAL joe) -r : 刪除目前的時程表 -l : 列出目前的時程表時程表的格式如下 : f1 f2 f3 f4 f5 program 其中 f1 是表示分鐘,f2 表示小時,f3 表示一個月份中的第幾日,f4 表示月份,f5 表示一個星期中的第幾天。program 表示要執行的程式。 當 f1 為 * 時表示每分鐘都要執行 program,f2 為 * 時表示每小時都要執行程式,其餘類推 當 f1 為 a-b 時表示從第 a 分鐘到第 b 分鐘這段時間內要執行,f2 為 a-b 時表示從第 a 到第 b 小時都要執行,其餘類推 當 f1 為 */n 時表示每 n 分鐘個時間間隔執行一次,f2 為 */n 表示每 n 小時個時間間隔執行一次,其餘類推 當 f1 為 a, b, c,... 時表示第 a, b, c,... 分鐘要執行,f2 為 a, b, c,... 時表示第 a, b, c...個小時要執行,其餘類推 使用者也可以將所有的設定先存放在檔案 file 中,用 crontab file 的方式來設定時程表。 例子 : 每月每天每小時的第 0 分鐘執行一次 /bin/ls : 0 7 * * * /bin/ls 在 12 月內, 每天的早上 6 點到 12 點中,每隔 20 分鐘執行一次 /usr/bin/backup : 0 6-12/3 * 12 * /usr/bin/backup 週一到週五每天下午 5:00 寄一封信給 alex@domain.name : 0 17 * * 1-5 mail -s "hi" alex@domain.name < /tmp/maildata 每月每天的午夜 0 點 20 分, 2 點 20 分, 4 點 20 分....執行 echo "haha" 20 0-23/2 * * * echo "haha" 注意 : 當程式在你所指定的時間執行後,系統會寄一封信給你,顯示該程式執行的內容,若是你不希望收到這樣的信,請在每一行空一格之後加上 > /dev/null 2>&1 即可
第二種方法:
使用shutdown定時關機的問題
shutdown: invalid option -- -
Usage: shutdown [-akrhfnc] [-t secs] time [warning message]
-a: use /etc/shutdown.allow
-k: don't really shutdown, only warn.
-r: reboot after shutdown.
-h: halt after shutdown.
-f: do a 'fast' reboot (skip fsck).
-F: Force fsck on reboot.
-n: do not go through "init" but go down real fast.
-c: cancel a running shutdown.
-t secs: delay between warning and kill signal.
** the "time" argument is mandatory! (try "now") **
PS:我是這樣的shutdown -t 54000 就是運行15小時後自動關機
- 10月 03 週五 200823:38
RedHat/Centos shutdown 用法
快速使用說明..
shutdown -h now 立即關機
shutdown -r now 立即重啟
Linux命令:shutdown
功能說明:系統關機指令。
語 法:shutdown [-efFhknr][-t 秒數][時間][警告資訊]
補充說明:shutdown指令可以關閉所有程式,並依用戶的需要,進行重新開機或關機的動作。
參 數:
-c 當執行"shutdown -h 11:50"指令時,只要按+鍵就可以中斷關機的指令。
-f 重新啟動時不執行fsck(磁片維護)。
-F 重新啟動時執行fsck。
-h 將系統關機。
-k 只是送出資訊給所有用戶,但不會實際關機。
-n 不調用init程式進行關機,而由shutdown自己進行。
-r shutdown之後重新啟動。
-t<秒數> 送出警告資訊和刪除資訊之間要延遲多少秒。
[時間] 設置多久時間後執行shutdown指令。
[警告資訊] 要傳送給所有登入用戶的資訊。
reboot 快速重啟(跳過sync過程,即同步化)
啟動級別(0~6),位於/etc/inittab:
對各個運行級的詳細解釋:
0 為停機,機器關閉。(千萬不要設置到此級別)
1 為單用戶模式,就像Win9x下的安全模式類似。
2 為多用戶模式,但是沒有NFS支援。
3 為完整的多用戶模式,是標準的運行級。
4 一般不用,在一些特殊情況下可以用它來做一些事情。例如在筆記本電腦的電池用盡時,可以切換到這個模式來做一些設置。
5 就是X11,進到X Window系統了。
6 為重啟,運行init 6機器就會重啟。(千萬不要設置到此級別)
shutdown、Halt、init、reboot的區別:
shutdown調用時,會發送信號(signal)給init程式,要求它改變runlevel,具體會根據參數決定(關閉或重起)。
halt和reboot都是shutdown的某個命令的鏈結,halt相當於shutdown -h now,也就是關閉;reboot相當於shutdown -r now,作用是重啟系統。
Init作為Linux系統的首發程式,有多個運行級(runlevel),比如0-關閉 1-單用戶模式 3-字元介面 5-圖形介面 6-重啟,因此使用Init來進行關機或重啟操作和shutdown差不多,且比shutdown更直接(不需要發送信號了的說)。

