因為這是Wiki的一個條目,可以在任何時間內被任何人編輯,因此建議你不要完全使用這個腳本,而是將其當作編寫腳本的指導手冊看待。
該教學向你大概描述什麼是虛擬硬碟,怎樣和 Minecraft 使用,以及如何設定一個虛擬硬碟伺服器。
虛擬硬碟描述[]
傳統上,檔案和資料夾儲存在硬碟驅動器,但以今天的標準來看,普通資料的傳輸速度(80MB/秒 到 200MB/秒之間)的提升空間還很大。虛擬硬碟是一個虛擬的檔案系統(不像硬碟那樣是硬體),會把檔案資料完全實時儲存在計算機記憶體條裡。它們的普通資料傳輸速度(3000MB/秒 到 15000MB/秒之間)非常高,但會失去穩定性(重啟電腦資料就會丟失)以及空間(受系統安裝記憶體條的數量限制,包括交換空間)。然而,有許多實用工具可以每隔一段時間備份虛擬硬碟裡面的資料,以及在關機前備份,然後在系統啟動時載入上次儲存的資料。
優點和缺點[]
優點[]
- 非常高的傳輸速度(從資料到應用)
- 非常低的尋道時間(在檔案之間搜尋)
缺點[]
- 在系統重啟時會清除虛擬硬碟的資料
- 如果世界尺寸大於記憶體條可用空間則很難實現
為什麼它對 Minecraft 伺服器有意義[]
在一個 Minecraft 伺服器,最大的一個瓶頸是相關的磁碟 I/O 操作(如區塊管理)。透過向記憶體行動資料,存取時間會被大大縮減,資料傳輸速度也會大大提高,讓區塊載入和儲存區塊操作變得更快。因為一個 Minecraft 世界包含了許多區塊檔案,尋道時間沒多大變化,因為重要的是整體速度。
基礎 Minecraft 和虛擬硬碟安裝[]
確保在開始前備份了你的檔案!
GNU/Linux(簡單方法)[]
2011年3月12日,在 Aimless Bits 的網誌裡,發布了把一個 Minecraft 伺服器載入到虛擬硬碟的簡單方法。它包含了修改過的 Wiki 腳本,以及一些小變更。本指南充實了這一過程,並在 Aimless Bits 的腳本裡做了一些小變更。
這個快速指南假設你已為載入 Minecraft 設定了一個使用者、Minecraft 目錄和執行中的伺服器。你最好熟悉 /etc/init.d/minecraft 啟動腳本。
- 第一步,在根目錄裡為虛擬硬碟建立一個目錄。如「/home/username/minecraft_ramdisk」。
- 要將其掛載為一個虛擬硬碟,只需要簡單編輯你的 /etc/fstab/ 檔案:
sudo nano /etc/fstab
然後加入這行,確保路徑(使用者名稱、目錄名稱等)是正確的。
tmpfs /home/username/minecraft_ramdisk tmpfs defaults,size=512m 0 0
虛擬硬碟的尺寸必須比 Minecraft 的世界目錄還要大。確保你已經預留多了一些空間。
- 重啟你的計算機。虛擬硬碟現在會在你重啟時載入,如果你希望立刻載入,輸入
mount -t tmpfs none /home/username/minecraft_ramdisk -o size=512m
現在要做的就是執行簡單修改過的腳本,該腳本會載入硬碟上的檔案到伺服器裡,將它們複製幾次作為副本,以防止資料丟失。再次提醒,這個腳本是 Aimless Bits 腳本的修改版本。
如果你已經寫好了 /etc/init.d/minecraft 腳本,刪除它或者將其覆蓋到這個腳本裡。如果沒有,新建一個文字文件,命名為「minecraft」,然後向它複製下列腳本內容。
#!/bin/bash # /etc/init.d/minecraft # version 0.6 2012-02-25 (YYYY-MM-DD) ### BEGIN INIT INFO # Provides: minecraft # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Minecraft server # Description: Starts the minecraft server ### END INIT INFO #Settings JARFILE='craftbukkit-beta_1.4.6-R0.3.jar' USERNAME="minecraft" MCSTORE="/home/$USERNAME/minecraft" MCPATH="/home/$USERNAME/minecraft_ramdisk" CPU_COUNT=1 INVOCATION="java -Xmx2048M -Xms2048M -server -jar $JARFILE -o false" BACKUPPATH="/home/$USERNAME/minecraft_backups/" WORLD=Asgarde as_user() { if [ "`whoami`" == "$USERNAME" ] ; then bash -c "$1" else su - $USERNAME -c "$1" fi } mc_status() { ps aux |grep -F -v grep|grep -F -v SCREEN|grep -F --quiet $JARFILE return $? } mc_start() { if mc_status; then echo "Tried to start but $JARFILE was already running!" else echo "$JARFILE was not running... starting." if [ -d $MCSTORE/$WORLD.bak ]; then echo "last $WORLD.bak still exist, crashed warning! manual check required!!!" exit 1 fi cd $MCPATH if [ ! -f "$MCPATH/$JARFILE" ]; then echo "Ram drive empty... prepping." as_user "cp -R $MCSTORE/* $MCPATH/" fi as_user "cd $MCPATH && screen -dmS minecraft $INVOCATION" sleep 7 if mc_status; then echo "$JARFILE is now running." else echo "Could not start $JARFILE." fi fi } mc_saveoff() { if mc_status; then echo "$JARFILE is running... suspending saves" TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user "$TO_SCREEN \"say SERVER BACKUP STARTING. Server going readonly...\"\015'" as_user "$TO_SCREEN \"save-off\"\015'" as_user "$TO_SCREEN \"save-all\"\015'" sync sleep 10 else echo "$JARFILE was not running. Not suspending saves." fi } mc_saveon() { if mc_status; then echo "$JARFILE is running... re-enabling saves" TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user "$TO_SCREEN \"save-on\"\015'" as_user "$TO_SCREEN \"say SERVER BACKUP ENDED. Server going read-write...\"\015'" else echo "$JARFILE was not running. Not resuming saves." fi } mc_stop() { if mc_status; then echo "$JARFILE is running... stopping." TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user "$TO_SCREEN \"say SERVER SHUTTING DOWN IN 5 SECONDS. Saving map...\"\015'" as_user "$TO_SCREEN \"save-all\"\015'" sleep 5 as_user "$TO_SCREEN \"stop\"\015'" sleep 5 else echo "$JARFILE was not running." fi if mc_status; then echo "$JARFILE could not be shut down... still running." else echo "$JARFILE is shut down." fi } mc_update() { if mc_status; then echo "$JARFILE is running! Will not start update." else MC_SERVER_URL=https://minecraft.net/`wget -q -O - http://www.minecraft.net/download.jsp | grep minecraft_server.jar\</a\> | cut -d \" -f 2` as_user "cd $MCPATH && wget -q -O $MCPATH/minecraft_server.jar.update $MC_SERVER_URL" if [ -f $MCPATH/minecraft_server.jar.update ]; then if `diff $MCPATH/$JARFILE $MCPATH/minecraft_server.jar.update >/dev/null` then echo "You are already running the latest version of $JARFILE." else as_user "mv $MCPATH/minecraft_server.jar.update $MCPATH/$JARFILE" echo "Minecraft successfully updated." fi else echo "Minecraft update could not be downloaded." fi fi } mc_backup() { echo "Backing up minecraft files" as_user "tar zcf $BACKUPPATH/MCBKUP_`date "+%Y.%m.%d-%H"`.tar.gz $MCSTORE" echo "Backup complete" } mc_disksaverun() { if mc_status; then echo "Saving ramdrive to disk." if [ ! -f $MCPATH/$JARFILE ]; then echo "Error.. Minecraft not in ram" else if [ -d $MCSTORE/$WORLD.bak ]; then echo "last $WORLD.bak still exist, crashed warning! manual check required!!!" exit 1 fi if [ -d $MCSTORE/$WORLD ]; then as_user "mv $MCSTORE/$WORLD $MCSTORE/$WORLD.bak" fi TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user "$TO_SCREEN \"save-off\"\015'" as_user "$TO_SCREEN \"save-all\"\015'" as_user "cp -R $MCPATH/* $MCSTORE/" as_user "$TO_SCREEN \"save-on\"\015'" if [ -d $MCSTORE/$WORLD.bak ]; then as_user "rm -r $MCSTORE/$WORLD.bak" fi fi else echo "Service is not running" fi } mc_disksavehalt() { echo "Saving ramdrive to disk." if [ ! -f $MCPATH/$JARFILE ]; then echo "Error.. Minecraft not in ram" else if [ -d $MCSTORE/$WORLD.bak ]; then echo "last $WORLD.bak still exist, crashed warning! manual check required!!!" exit 1 fi if [ -d $MCSTORE/$WORLD ]; then as_user "mv $MCSTORE/$WORLD $MCSTORE/$WORLD.bak" fi echo "Saving, screen session closed" as_user "cp -R $MCPATH/* $MCSTORE/" if [ -d $MCSTORE/$WORLD.bak ]; then as_user "rm -r $MCSTORE/$WORLD.bak" fi fi } #Start-Stop here case "$1" in start) mc_start ;; stop) mc_stop mc_disksavehalt ;; restart) mc_stop mc_disksavehalt mc_start ;; update) mc_stop mc_backup mc_update mc_start ;; backup) mc_disksaverun mc_saveoff mc_backup mc_saveon ;; disksavehalt) mc_disksavehalt ;; disksaverun) mc_disksaverun ;; status) if mc_status; then echo "$JARFILE is running." else echo "$JARFILE is not running." fi ;; *) echo "Usage: /etc/init.d/minecraft {start|stop|update|backup|status|restart|disksaverun}" exit 1 ;; esac
- 把該腳本移動到你的 /etc/init.d/ directory,然後設定它為可執行:
mv /directory/wherefileis/filename /etc/init.d/minecraft chmod a+x /etc/init.d/minecraft
註: 該腳本沒有寫上在該網站的其他 minecraft 初始化腳本的命令列選項! 因此重寫了該腳本,加入了一些指令代碼,因此虛擬硬碟伺服器也可以使用指令之類去同步而不用使用其他外掛來進行計劃:http://pastebin.com/4ynwL2js 。如果需要命令列選項,可以使用這個。
你就快完成了!這個腳本表現的和原始的啟動腳本差不多,只有一點不同的就是它把資料載入到虛擬硬碟裡。你也可以修改腳本來使用 rsync 而不是 cp,如果你想做其他東西,例如遠程複製,但這對效能沒什麼影響,除非你的世界很大。
"rsync -r -t $MCSTORE/ $MCPATH/"
- 請勿跳過這個步驟!你需要加入一個 crontab 條目來儲存你的世界。因為某些原因,你要接著往下看,但是如果你不完成這個步驟,那麼你在虛擬硬碟裡的資料就會丟失。該腳本有2個磁碟儲存函數,disksavehalt 和 disksaverun。 Disksavehalt 假定 screen 會話正在關閉或正在備份,不會關閉地圖儲存。不要在 crontab 裡調用這個函數,而是使用 disksaverun。
欲自動備份,這樣做:
sudo crontab -e
然後加入下面2行:
*/5 * * * * /etc/init.d/minecraft disksaverun 20 */6 * * * /etc/init.d/minecraft backup
數字代表每隔多少分鐘就儲存世界,如果你有高容錯的設定、備用電源等等,可以不那麼頻繁。否則堅持至少每五分鐘備份一次!
第二行讓 Minecraft 每隔6小時備份一次(執行backup函數),並且固定在:20時進行備份。不要跳過備份!這是最後一次警告!
但願這能夠對管理員有幫助,祝你好運!
GNU/Linux(備選方法)[]
在多數的 GNU/Linux 發行版,虛擬硬碟已經設定好了(通常掛載在 /dev/shm (shared memory(共享的記憶體))),預設最多使用已安裝記憶體的一半) 如果未設定,網際網路上有許多資源教你如何設定。
可以把任何東西移到虛擬硬碟,但本教學只專注於把地圖移動到虛擬硬碟裡,並將伺服器檔案留在傳統驅動器上。
在使用者根目錄裡的「minecraft_server/」伺服器目錄裡分成下面幾個基本檔案,含有世界「world」和其他所需要的檔案。
~/minecraft_server/ |
---|
world/ |
minecraft_server.jar |
server.log |
server.properties |
... |
接下來的目標是把「world/」移動到共享記憶體裡。由於虛擬硬碟的不穩定性,我們要建立一個新資料夾,在裡面放上一個自動備份的腳本,透過複製目前目錄到一個新名稱目錄來定期儲存目前世界的名為(例如)「world_storage」的快照。
$ cd ~/minecraft_server/ $ cp -r world/ world_storage/
現在舊世界在一個安全位置裡,我們現在可以進行下一步並將世界移動到虛擬硬碟。
$ mkdir /dev/shm/minecraft $ mv world/ /dev/shm/minecraft
現在,世界以及載入到記憶體裡,但是 Minecraft 伺服器還是沒有在它的目錄裡看見這個世界,導致在啟動時會重新生成它。為了阻止伺服器生成它,我們要在虛擬硬碟裡創造一個符號連結到那個世界。執行下列指令:
$ ln -s /dev/shm/minecraft/world/
這將會建立一個名為「world/」的連結,其連結到伺服器目錄「/dev/shm/minecraft/world/」,伺服器會把它當作實際的世界資料夾使用,但是這個資料夾在記憶體裡。
現在我們需要注意虛擬硬碟的不穩定性,要定期儲存記憶體「world_storage/」裡面的世界。下面將使用 cron 進行計劃任務和 rsync 進行同步。
首先,建立一個叫作 cron 的腳本(它不能是一個腳本,因為你可以直接從 cron 命令列直接調用 rsync,但這樣允許在晚些時候更容易的進行自訂)
#!/bin/sh VOLATILE="/home/$USER/minecraft_server/world/" PERMANENT="/home/$USER/minecraft_server/world_storage/" #TODO: Check if both directories actually exist, skipped here for clearness rsync -r -t -v "$VOLATILE" "$PERMANENT"
然後每隔幾分鐘執行該腳本(這裡將會隔5分鐘,你可以測試一下隔多長時間對你是最合適的)
$ crontab -e
你將會被帶到一個編輯器(更精確的說:你的「EDITOR」環境變數編輯器)來編輯你的使用者 cron 表。加入下列行:
*/5 * * * * bash /home/<your_username>/minecraft_server/save_world.sh &>/dev/null
現在你的伺服器將會重啟,你將會在晚些時候在共享記憶體裡(/dev/shm/minecraft/world)重新建立世界資料夾(/dev/shm/minecraft),因為重啟後 /dev/shm/ 是空的。你可以寫一個簡單的可執行腳本來做到這點。
因此製作一個簡單的可執行腳本:
exec 1>/tmp/backup_world.log 2>&1 #sends the output to this file #!/bin/sh #remake the paths mkdir /dev/shm/minecraft mkdir /dev/shm/minecraft/world VOLATILE="/home/$USER/minecraft_server/world/" PERMANENT="/home/$USER/minecraft_server/world_storage/" #TODO: Check if both directories actually exist, skipped here for clearness #reversed the order rsync -r -t -v "$PERMANENT" "$VOLATILE"
每次你重啟時,你都要執行這個腳本來重新掛載虛擬硬碟。不要把這個加入到 crontab 裡。如果你知道如何做,那麼你可以把這個加入到啟動腳本中。
GNU/Linux (快而不精)[]
這是上述備選方案的一個快速卻粗糙(效果完全相同)的版本。這個技巧在架設於Fedora的伺服器上效果良好。
首先定位至伺服器工作路徑並備份現存世界。
cp -r world/ world_storage/
- 以防意外發生,你可能還希望多建立一個備份。
要使用這個方法,我們需要目錄名為「world」,因此從工作路徑中刪除world/
rm world/ -rf
現在,我們需要將伺服器的世界目錄重新導向至共享記憶體中。在crontab中輸入一行指令即可。
*/5 * * * * rsync -r -t -v /dev/shm/world/ /path_to_minecraft/world_storage/
現在我們需要將世界「掛載」至共享記憶體中。新建 start.sh 檔案,輸入以下兩行:
cp /path_to_minecraft/world_storage/ /dev/shm/world/ -r rsync -r -t -v /dev/shm/world/ /path_to_minecraft/world_storage/
每次重啟伺服器時,都可以使用 start.sh 將世界掛載至共享記憶體,其後你就可以正常啟動伺服器(方便起見也可以直接在 start.sh 中加上一行指令)。如果你希望在執行 start.sh 啟動伺服器並且使用screen
指令,請一定用screen
指令執行 start.sh。不要在腳本中使用screen
指令,否則伺服器將在後台執行而你將不能執行控制台指令。
Windows[]
使用一個像 Dataram RAMDisk(下載免費的版本)之類的虛擬硬碟實用工具來在記憶體中建立一個磁碟,並將伺服器檔案放進裡面。 Dataram RAMDisk 提供了在其關閉的時候或隔幾分鐘自動儲存圖像的選項。
開始之前:
- 至少要4G記憶體
- 開啟「關機時儲存磁碟映像」,在關機時停止虛擬硬碟的執行會對 Windows 關機時間造成影響,同時也會對開機時間造成影響,因為要「在啟動時載入磁碟映像」。如果你僅在需要時手動啟動或停止伺服器,那麼這就不成問題了。
- 在網路上進行搜尋儲存虛擬硬碟資料的方法,以防你的虛擬硬碟不能工作時丟失資料。
- FAT16 格式的虛擬硬碟通常比 FAT32 的要快,然而 FAT16 格式不允許單個磁碟容量超過 2048 MB。
- 記住:經常備份!如果你的電腦崩掉了,任何未儲存的虛擬硬碟資料都會丟失!
- 確保你為虛擬硬碟分配了足夠的空間,可以裝得下「Minecraft Server」資料夾 - 記得 Minecraft 世界資料可以增加很多!
- ...最後,確保剩餘的記憶體空間足夠讓 Windows 和伺服器本身執行
設定你的虛擬硬碟(簡單用法)
- 下載並安裝 Dataram RAMDisk
- 設定硬碟尺寸(不推薦設定到最大)
- 如果硬碟尺寸少於等於 2048 MB,選擇「FAT16 Partition」否則就選「FAT32 Partition」(高級使用者可能會選擇「unformatted」並手動格式化硬碟)
- 前往 Load/Save 頁籤,並選擇所有3種虛擬硬碟儲存方法(「AutoSave」、「Save Disk Image on Shutdown」和「Load Disk Image on Startup」)
- 要啟動你的虛擬硬碟 - 點擊「Start RAMDisk」
- 現在前往「計算機」(Win XP 為我的電腦、Win 7、Win 10 為計算機、Win 8 為此計算機),你應該會看見新的硬碟
- 打開它並複製所有的 Minecraft 伺服器到這個硬碟裡。
- 像平常一樣啟動你的伺服器,只不過現在是從剛剛建立的虛擬硬碟啟動 - 你現在就能啟動和執行了!
你的虛擬硬碟現在會在關機時自動儲存,並在開機時自動載入。你會注意到開機/關機的時間更長了,而增加的時間取決於你設定的尺寸。
同時,你可能希望調整 AutoSave (自動儲存)間隔。
如果你沒有選擇「Save Disk Image on Shutdown」,繼續看下去!
你需要在'每次'關閉計算機時完成下列步驟,否則資料就會丟失!
- 手動停止虛擬硬碟(在關閉計算機之前)
- 如果你的 Minecraft 伺服器正在執行,停止它
- 打開 Dataram RAMDisk configuration Utility(再次)
- 在 Load/save 頁籤開啟「Load Disk Image on Startup」
- 點擊「Save disk image now」
- 點擊「Stop RAMDisk」
- (如果你希望再次啟動伺服器,按照你第一次啟動伺服器的操作去做。如果你勾選了「Load Disk Image at Startup」才能做這個)
- 備選方法:
- 停止你的伺服器
- 複製虛擬硬碟裡的所有檔案到硬碟驅動器的一個備份資料夾
- 在 Dataram RAMDisk configuration Utility 點擊「Stop RAMDisk」
- (要再次啟動它,按照你第一次啟動虛擬硬碟的操作去做,然後把所有檔案複製到虛擬硬碟裡,然後啟動你的伺服器。)
Mac OS X[]
在 Mac OS 裡鍵入下列指令來建立你的虛擬硬碟:
diskutil erasevolume HFS+ "ramdisk" `hdiutil attach -nomount ram://1165430`
這隻有一條命令列,而且還很快,很有效果。 :)
如果你跟隨這些操作去做了,你的虛擬硬碟將會出現在 /Volumes/ramdisk。在此之後,按照你在 Linux 那樣做,使用 Terminal 和你喜愛的文字編輯器。
|
語言