i3是一款基於X11的視窗管理器(Window Manager),使用效能極佳的C語言開發而成的,介面簡潔、輕巧卻不失實用性,功能強調視窗的佈局和快捷鍵,非常適合用在伺服器上配合其它指令工具或是圖形工具來監看系統狀態和查詢文件。本篇文章將會以無視窗介面的Ubuntu Server作為開端,來介紹i3的安裝與使用方法。
為什麼伺服器需要圖形介面?
伺服器剛安裝完Linux作業系統後,會有許多設定、和軟體部署的工作要處理,如果只單純使用TTY文字介面,處理效率可能不會好到哪裡去。如果把肥大的桌面環境安裝到伺服器上,雖然操作起來比較順暢,但桌面環境同時也會佔用掉不少伺服器的硬碟空間以及記憶體空間。這時其實就可以考慮安裝i3視窗管理器,因為它只專注在視窗的操作和顯示,而非龐大的圖形架構,程式的大小很小(程式專案壓縮之後只有1.2MB),佔用的記憶體也很少(不到30MB),更重要的是它是C語言實作出來的圖形介面,比起大部份使用大量腳本語言(Python、JavaScript等)的桌面環境,i3的效能真的要好太多了!立即啟動、立即關閉,不需要等。
在伺服器架設完成之後,我們可能也會需要監看伺服器的運作狀態,雖然可以直接在TTY下使用top
指令(如下圖),但一個top
就佔滿一個TTY,如果有多樣資訊要同時查看,或是要操作其它的軟體時就會變得很麻煩。
當然,我們也是可以在伺服器上架設SSH服務,利用別台有圖形介面的電腦來連線到這台伺服器上工作啦,只不過這樣的效率還是沒有直接在伺服器上用圖形化介面來操作來得好。
安裝i3視窗管理器
在Ubuntu Server上安裝i3視窗管理器的方式十分容易,只要執行以下指令即可:
安裝完i3之後,Ubuntu Server預設並不會在開機的時候順便啟動i3,您可以在想要使用i3的時候,在任一TTY中執行以下指令:
不出幾秒,i3就開起來了!
第一次使用i3視窗管理器
第一次使用i3視窗管理器時,會出現如上圖所出現的視窗,提示使用者尚未建立i3的設定檔(使用者的i3設定檔路徑為~/.config/i3/config
),這時按下Enter鍵就可以自動建立設定檔。稍候我們會需要編輯這個檔案。
再來會出現一個設定「modifier」按鍵的畫面(如下圖),此時可以用鍵盤或是滑鼠來選擇想要當作「modifier」的按鍵,這個「modifier」按鍵是組合快捷鍵的基本鍵,如果鍵盤有Win鍵的話建議就用Win吧!本篇文章會以Win作為「modifier」為例。選定好之後按下Enter鍵繼續。
接下來就會只剩下「桌面」。畫面最下方那一列,左邊是工作區列,右邊則是狀態列。工作區列這篇文章會在之後會做詳細介紹,而狀態列由左至右分別是:IPv6狀態(ipv6
)、硬碟空間使用量(disk /
)、第一個無線網路介面(wireless _first_
)、第一個有線網路介面(ethernet _first_
)、電池剩餘電量(battery all
)、負載量(load
)、本地端的日期與時間(tztime local
)。預設的狀態列設定檔存放在/etc/i3status.conf
,如果要修改的話,可以複製一份到~/.config/i3status/config
來修改,這篇文章就不再多提狀態列的設定方式了!
然後呢?
i3視窗管理器的使用方法
關閉i3視窗管理器
前面提到在TTY中輸入startx
可以啟動i3視窗管理器,那要如何才能關閉它呢?很簡單,只要在i3視窗管理器中,按下快速鍵Win + Shift + E,畫面上方就會出現是否要關閉i3視窗管理器的確認訊息。
按下Yes, exit i3
之後就可以回到TTY囉!
如果想再啟動i3,再次執行startx
即可。
i3的視窗架構
i3的視窗架構分為4個層級,分別是:顯示器(monitor, output)→工作區(workspace)[→容器(container)[→……→容器(container)]]→視窗(window)。
顯示器和工作區
i3支援多顯示器,一個顯示器可以有擁有多個工作區。在所有顯示器中的工作區之代號均不會重複。
藉由xrandr
指令,我們可以分別替不同的顯示器設定解析度。另外,藉由i3-msg
的move
指令,也可以將某個工作區完整地移動到其它的顯示器中。這個部份,本篇文章稍候會再提到。
當顯示器僅存的工作區消失的同時,又會再立刻創建出新的工作區。
工作區和容器
一個工作區可以擁有多個容器和多個視窗,且必須要擁有至少其中一個,否則它會在i3切換到其它工作區後被消滅,除非該空工作區是該顯示器的唯一一個工作區,此時該空工作區才會被保留下來。
藉由i3預設的快速鍵,我們也可以將某個容器完整移動到不同工作區中,當然,是可以在不同顯示器的工作區間移動的哦!這個部份,本篇文章稍候會再提到。
容器和視窗
一個容器可以擁有多個容器和多個視窗。一個視窗在被建立的時候,會根據當前的排版狀態和視窗或容器焦點來決定要加入至哪個容器中。
每個容器都可以設定一種排版方式(layout),藉由i3預設的快速鍵即可設定。這個部份,本篇文章稍候會再提到。
當一個容器中沒有任何的容器和視窗時,這個容器就會立刻被消滅。
開啟終端機
在i3中,可以按下快速鍵Win + Enter來開啟新的終端機視窗。
關閉視窗或容器
使想要關閉的視窗或容器獲得焦點,之後按下快速鍵Win + Shift + q即可將其關閉。
修改螢幕解析度
若需要修改顯示器的解析度,可以先在終端機下執行以下指令,來查看所有顯示器的名稱和支援的解析度。
如上圖,可以看到目前筆者只有一個Virtual1
顯示器可以使用,
修改螢幕解析度同樣可以使用xrandr
指令來達成,用法如下:
例如要將Virtual1
顯示器的解析度調整為1440x900
,執行以下指令:
執行後,螢幕解析度就調整好了!
這邊要注意的是,直接在終端機下使用xrandr
指令來調整螢幕解析度的話,設定並不會被儲存,重開i3後依然又會回到預設的螢幕解析度。本篇文章之後會說明儲存螢幕解析度設定的方法,現階段先這樣設定就好。
調整視窗大小
在i3中按下快速鍵Win + r,可以進入視窗大小調整模式,在這個模式下,可以直接用滑鼠拉動視窗邊緣來調整視窗的大小,此時所有i3的快速鍵都會失效,在工作區列的旁邊會出現resize
字樣。
若要離開視窗大小調整模式,直接按下ESC
鍵即可。
容器的排版方式
螢幕解析度調整好了之後,可以先按三次Win + Enter,打開三個終端機視窗來練習看看。
預設排版──垂直和水平排列
如果您沒有不小心按到其它的快速鍵,那麼應該會看到如下圖的排版方式。三個視窗垂直或水平排列。
i3預設排版方式屬於完全展開型,它不會對視窗進行收納。如果目前容器不是使用i3的預設排版,按下快速鍵Win + e後可設成i3的預設排版。繼續按快速鍵Win + e的話,則可以切換要水平還是垂直排列。
另外,當視窗不在容器之下的時候,預設排版功能會沒有反應,此時可以先切換成以下其它的排版,再徑行切回,因為其它的排版方式會順便替同層的視窗和容器產生一個新容器。
快速鍵Win + e是去設定目前獲得焦點的視窗或是容器的上層容器的排版方式,所以就算目前是由某個容器獲得焦點,也還是會去設定到其上層的容器。
堆疊排版
如果覺得視窗太多,想要把不重要的收合起來的話,可以使用這個堆疊排版方式。按下快速鍵Win + s後可啟用堆疊排版。
用滑鼠點選被收合的視窗標題,即可將其展開。
同樣地,快速鍵Win + s也是去設定目前獲得焦點的視窗或是容器的上層容器的排版方式,所以就算目前是由某個容器獲得焦點,也還是會去設定到其上層的容器。
分頁排版
如果覺得視窗太多,想要把不重要的收起來的話,也可以使用這個堆疊排版方式。按下快速鍵Win + w後可啟用分頁排版。
用滑鼠點選被收起來的視窗標題,即可將其翻開。
同樣地,快速鍵Win + w也是去設定目前獲得焦點的視窗或是容器的上層容器的排版方式,所以就算目前是由某個容器獲得焦點,也還是會去設定到其上層的容器。
建立新容器並加入新視窗
先前我們提到,可以按三次Win + Enter來打開三個終端機。在沒有使用其它的快速鍵時,這三個終端機在開啟之後,會產生各自的新視窗,並直接加進工作區的層級之下。如果要實現如下兩張圖,在同一個工作區中使用多種不同的排版方式的話,我們需要有別種方式來放置被建立出來的新視窗。
如果要將新建立出來的視窗放置在某個現存的視窗所屬的容器之下,可以先讓該現存視窗得到焦點。
接著按下快速鍵Win + h或是Win + v。如果您夠細心的話,應該會發現該視窗的右邊或是底部的邊框會被加強提示。
按下Win + h後,會使該得到焦點的視窗,在未來取得焦點時,一旦有新建立出來的視窗,i3就會建立出新容器,而得到焦點的視窗和新視窗都會被分配到這新容器之下,且這個新容器的排版方式會被設為預設排版的水平排列。
Win + v與Win + h的功能類似,差別只在Win + v建立出來的新容器的排版方式會被設為預設排版的垂直排列。
在新容器被建立出來之後,Win + h和Win + v的效果就會消失,之後新建視窗就不會再另外建立新容器了。
一旦工作區內有了容器,之後在建立新視窗時,就會根據目前得到焦點的視窗或是容器,來決定新視窗要直接放置在工作區之下,還是要放置在目前得到焦點的容器或是視窗的上層容器之下。
浮動視窗或容器
i3的視窗或容器除了可以嵌在工作區上外,也可以設定為可自由移動的浮動視窗/容器,浮動視窗/容器會直接壓在非浮動視窗/容器的上面。快速鍵Win + Shift + Space可以控制目前獲得焦點的容器或視窗是否為浮動的。
一個工作區中可以有多個浮動視窗/容器。
快速鍵Win + Shift + Space的作用對象是目前獲得焦點的視窗或是容器,而不是其上層的容器。本篇文章接下來會提到移動視窗焦點,以及使上層容器取得焦點的方式。
視窗或容器焦點的移動
最基本、最簡單的視窗焦點移動方式就是移動滑鼠游標,當滑鼠游標從一個視窗移動到另一個視窗時,目前滑鼠所在的視窗就會取得視窗焦點。如果滑鼠所在的視窗因一些原因而失去焦點,只要操控滑鼠游標在同一個視窗內按下滑鼠按鍵即可取回焦點。
i3預設了幾個快速鍵,可以用來移動視窗焦點,如下:
- Win + j:將視窗焦點移動給左邊的視窗。
- Win + k:將視窗焦點移動給下面的視窗。
- Win + l:將視窗焦點移動給上面的視窗。
- Win + ;:將視窗焦點移動給右邊的視窗。
另外,快速鍵Win + a,可以使目前焦點的視窗或是容器的上層容器得到焦點。
而快速鍵Win + space,可以使焦點在浮動視窗/容器和非浮動視窗/容器之間進行切換。
建立與切換工作區
i3預設了幾個快速鍵,可以用來建立或是切換工作區,只要按下Win + 數字鍵,即可建立或是切換到對應數字名稱的工作區。數字鍵0,代表的工作區名稱為「10」,而不是「0」。
如果要建立出名稱為「10」以上的工作區,只能去修改i3的設定檔,因為我們極少有機會用到這麼多的工作區,所以這部份本篇文章就不提了。
視窗或容器本身的移動
i3預設了幾個快速鍵,來移動視窗或容器的位置,如下:
- Win + Shift + j:將目前擁有焦點的視窗或是容器移動到左邊。
- Win + Shift + k:將目前擁有焦點的視窗或是容器移動到下面。
- Win + Shift + l:將目前擁有焦點的視窗或是容器移動到上面。
- Win + Shift + ;:將目前擁有焦點的視窗或是容器移動到右邊。
另外,也可以按下Win + Shift + 數字鍵,將目前擁有焦點的視窗或是容器移動到其它的工作區中。
在終端機外執行程式
i3提供了「dmenu」這個應用程式啟動器,可以按下快速鍵Win + d來進入應用程式的搜尋列(在畫面上方),只要輸入程式名稱再按下Enter鍵即可執行該程式。
終端機的外觀
使用本篇文章提供的方式在Ubuntu Server上安裝i3視窗管理器,預設使用的終端機軟體是GNOME Terminal(gnome-terminal),其外觀可以直接在終端機的選單中找到Preferences
來加以設置。
i3視窗管理器的設定檔
使用者的i3設定檔路徑為~/.config/i3/config
,這個設定檔可以用來控制絕大部分的i3視窗管理器的外觀和快速鍵,以及開啟i3後會自動執行的指令。在這個設定檔中可以看到一些在其他地方沒見過的指令,像是bindsym
、exec
等等。這些是專門給i3看的IPC訊息,如果要透過終端機來送這類訊息給i3視窗管理器的話,可以透過i3-msg
指令來達成。
就拿以下設定檔中的
來說明。
這個bindsym
指令可以替i3添加快速鍵,$mod
是使用set $mod Mod4
指令來設定的,它就是我們第一次開啟i3的時候所設定的「modifier」按鍵,Mod4
就是指Win鍵。此外,Mod1
是指Alt;Mod2
是指Num_Lock;lock
是指Caps_Lock;shift
是指Shift;control
是指Ctrl。
而layout
是用來控制目前焦點的視窗或是容器的上層容器的排版方式所用的指令,這個也是專門給i3看的IPC訊息。
也就是說,如果我們要在終端機中,去控制目前終端機的上層容器的排版方式為分頁排版的話,可以直接在i3圖形介面中的終端機下輸入以下指令:
若要在i3的設定檔中去執行終端機的指令,可以透過exec
這個IPC訊息。例如在i3的設定檔最後加上以下指令,則可以讓i3在啟動之後自動開啟終端機視窗。
i3的exec
指令並不會因需要執行終端機命令而造成阻塞(也就是non-blocking)。exec
指令的--no-startup-id
參數可以避免應用程式在啟動時所造成的滑鼠游標圖示的改變,且也可以使視窗出現在目前的工作區,而不是執行指令的工作區。
若要立刻套用新的設定檔設定,可以在關閉i3之後,在TTY內重新使用startx
指令來開啟。
永久保存螢幕解析度的設定
利用上一個小節學會的i3視窗管理器的設定檔撰寫方法,我們可以在設定檔結尾處加上i3的exec
指令,來使得i3在開啟後自動執行終端機的xrandr
指令,來改變螢幕解析度的設定。
工作區的移動
利用i3的move
指令,可以移動工作區、容器或是視窗。如果要移動目前的整個工作區到其它的顯示器,可以在終端機執行以下指令:
保存與還原工作區
我們辛辛苦苦排好的容器和視窗,可以在終端機上使用i3-save-tree
指令來保存下來。i3-save-tree
指令支援工作區層級和顯示器層級的保存,用法如下:
以上指令可以將目前執行指令的工作區保存成檔案。
以上指令可以將指定的工作區保存成檔案。
以上指令可以將指定的顯示器下的所有工作區保存成檔案。
輸出的檔案內容是稍微類似JSON的格式,因此檔案的副檔名建議使用JSON。
然而,i3的工作區保存功能並不是那麼地好用。它並不會將目前視窗實際所執行的行程資訊記錄下來,而只會保留單純那個視窗的資訊(視窗大小、位置、名稱等資訊)。也就是說,i3的工作區在還原時,會還原先前保存的容器和視窗,但因不知道實際上視窗到底是跑什麼程式,所以會留下「坑」。i3對於這個問題的解決方案是讓這些坑可以自動「吞嚥」(swallow),在當初保留視窗資訊時,i3除了會視窗標題外,也會把一些其它非位置資訊的進階視窗資訊記錄下來,像是視窗class、classname(instance)、window_role等,這些資訊會用來判斷之後開啟的視窗是不是就是原先保存下來的視窗,如果是的話,就會進行「吞嚥」也就是「填坑」的動作,使得程式視窗可以跑到i3認為它應該要在的位置上。筆者在此不得不吐嘈這個設計,它不僅麻煩,也實在是很欠缺實用性。就拿「top」這個指令來說,top是運行在某個終端機程式下的指令,如果我們想要保留很多視窗,分別執行「top」或是其它指令,光靠i3這個雞肋的填坑功能根本做不到,因為終端機程式的視窗資訊都是一模一樣的。
再者,就算i3可以做到完美填坑,我們在重新啟動i3,並載入先前的工作區設定後,居然還得再手動把先前開的程式再一一開來填坑,嗯……總之,先繼續說明把工作區保存成檔案之後還要做的事情吧!
i3-save-tree
指令輸出的檔案必須透過手動編輯才能使用,例如下圖畫面,
產生出來的i3-save-tree
指令輸出的檔案如下圖所示:
沒錯,官方其實也應該知道這「填坑」的機制很難用,所以才在這檔案中把「吞嚥」的欄位給註解掉,想要用這個檔案來還原工作區,使用者必須先編輯好「吞嚥」欄位。
堪用的作法
由於i3工作區保存和還原的機制實在雞肋,令筆者幾度想放棄使用這整個i3視窗編輯器,但後來還是研究出了一個堪用的作法,可以同時實現i3啟動時自動啟動應用程式並正確填坑,以及把現有的視窗填入現有坑中的功能。
首先,在編輯i3-save-tree
指令輸出的檔案時,「吞嚥」的欄位中,我們只設定window_role
的條件,讓它能去匹配數字,從1開始,最多到10,這樣做的目的就是手動把這些坑給編號。
例如要匹配編號2,「吞嚥」欄位可以寫成:
"swallows": [
{
"window_role": "^2$"
}
]
接著,在i3的使用者設定檔中,添加幾個快速鍵:
bindsym $mod+Control+1 exec --no-startup-id xdotool getactivewindow set_window --role 1 windowunmap windowmap
bindsym $mod+Control+2 exec --no-startup-id xdotool getactivewindow set_window --role 2 windowunmap windowmap
bindsym $mod+Control+3 exec --no-startup-id xdotool getactivewindow set_window --role 3 windowunmap windowmap
bindsym $mod+Control+4 exec --no-startup-id xdotool getactivewindow set_window --role 4 windowunmap windowmap
bindsym $mod+Control+5 exec --no-startup-id xdotool getactivewindow set_window --role 5 windowunmap windowmap
bindsym $mod+Control+6 exec --no-startup-id xdotool getactivewindow set_window --role 6 windowunmap windowmap
bindsym $mod+Control+7 exec --no-startup-id xdotool getactivewindow set_window --role 7 windowunmap windowmap
bindsym $mod+Control+8 exec --no-startup-id xdotool getactivewindow set_window --role 8 windowunmap windowmap
bindsym $mod+Control+9 exec --no-startup-id xdotool getactivewindow set_window --role 9 windowunmap windowmap
bindsym $mod+Control+0 exec --no-startup-id xdotool getactivewindow set_window --role 10 windowunmap windowmap
由於會使用到終端機的xdotool
指令,所以需要先在終端機執行以下指令來安裝:
套用快速鍵設定後,就可以用以下指令來還原工作區了。
如上圖,可以看到畫面中出現了3個坑。此時可以使用快速鍵Ctrl + Win + 1、Ctrl + Win + 2、Ctrl + Win + 3來將目前取得焦點的視窗,分別填進編號1、2、3的坑中。
如果要完成啟動i3時自動還原工作區的功能,可以在i3的使用者設定檔中,於底部調整解析度的指令(如果有的話)之下加上:
讓exec
先執行sleep 1
(延遲1秒)的用意是要讓解析度調整能有充份的時間被套用。
接著再加上想要在啟動i3時,也跟著自動開啟的視窗。同樣使用i3的exec
來呼叫就好了。例如剛才提到的──開啟終端機,指令寫法如下:
也可以執行網頁瀏覽器來查看本地端的網站,在此以火狐瀏覽器(Firefox)為例:
也可以執行終端機來跑top
指令:
gnome-terminal
的-e
參數可以設定開啟終端機時要執行的指令,--title
參數則可以設定終端機的視窗標題,如果有多個終端機視窗要填坑,一定要更改為不同的標題。
最後用以下的指令來實現自動填坑:
sleep 2
(延遲2秒)的用意是要讓解析度調整能有充份的時間被套用,且可以把應用程式的視窗建立出來。xdotool
指令的search
子命令,可以依照多個條件來搜尋圖形介面相關的視窗ID。--onlyvisible
參數一定要加上去,可以過濾掉不可顯示的視窗ID。其它常用的篩選條件有--classname
、--class
、--name
這三個,name
是指視窗標題,而classname
和class
可以在終端機執行以下指令後,選擇指定的視窗來查看:
根據顯示出來的WM_CLASS
欄位的值,逗號,
前的部份即為classname
,逗號,
後的部份即為class
。如上圖,可以看出GNOME Terminal這支程式的classname
為gnome-terminal-server
、class
為Gnome-terminal
。
利用xdotool
指令來找出視窗,接著再使用它的set_window
功能,來設定找出來的視窗的window_role
(WM_WINDOW_ROLE)。只要它能與現有的坑想「吞嚥」的window_role
成功匹配,就可以順利地完成填坑。
圖形化檔案瀏覽器
瀏覽檔案時,使用圖形介面通常會比文字介面還要更有效率一點,在i3中,可以使用Thunar這款輕量級的檔案瀏覽器來瀏覽檔案。
直接在終端機執行以下指令就可以安裝了:
然而,在i3中執行Thunar時,可能會發現Thunar的圖示顯示不出來。如下圖:
這個是因為icon-theme沒安裝,或是Thunar不支援現有的icon-theme所引發的問題。可以執行以下指令,來列出軟體源中所有可安裝的icon-theme:
可以到GNOME的icon-theme網頁來尋找預覽圖。
筆者這邊就以tango-icon-theme
為例,使用以下指令可以安裝tango-icon-theme
:
接著用文字編輯器編輯GTK2的設定檔~/gtkrc-2.0
,將gtk-icon-theme-name
改為Tango
。
重新啟動Thunar,就可以看到圖示了。
網頁瀏覽器
如果我們的伺服器是網站伺服器,那麼就會很需要在伺服器上安裝網頁瀏覽器來瀏覽我們架設的網站。
可以參考以下文章來安裝Firefox ESR:
中文字無法顯示的解決方法
在瀏覽網頁或是查看文件的時候,極有可能會遇到中文字無法顯示的情形。
如下圖,火狐瀏覽器在顯示中文字的時候,中文字變成方塊了。
可以參考這篇文章來取得開源的中文字型:
將下載回來的中文字型檔案放置到~/.local/share/fonts
目錄中,如果沒有這個目錄的話就自行建立出來。
接著再到終端機執行以下指令來清除字型快取。
使用以下指令可以顯示出目前系統中安裝的字型:
之後就可以正常顯示中文字啦!