利用systemd部署golang專案的實現方法
簡介
- CentOS 7 繼承了 RHEL 7 的新的特性,例如強大的 systemd, 而 systemd 的使用也使得以往系統服務的 /etc/init.d 的啟動指令碼的方式就此改變, 也大幅提高了系統服務的執行效率。但服務的配置和以往也發生了極大的不同,同時變的簡單而易用了許多。
- CentOS 7 的服務 systemctl 指令碼存放在:/usr/lib/systemd/,有系統 system 和使用者 user 之分, 即:/usr/lib/systemd/system 和 /usr/lib/systemd/user
配置檔案
- 這裡我們先要說明一下 unit 的檔案位置,一般主要有三個目錄:
/lib/systemd/system /run/systemd/system /etc/systemd/system
- 這三個目錄的配置檔案優先順序依次從低到高,如果同一選項三個地方都配置了,優先順序高的會覆蓋優先順序低的。 系統安裝時,預設會將 unit 檔案放在 /lib/systemd/system 目錄。如果我們想要修改系統預設的配置,比如 nginx.service,一般有兩種方法:
- 在 /etc/systemd/system 目錄下建立 nginx.service 檔案,裡面寫上我們自己的配置。
- 在 /etc/systemd/system 下面建立 nginx.service.d 目錄,在這個目錄裡面新建任何以.conf 結尾的檔案,然後寫入我們自己的配置。推薦這種做法。
- /run/systemd/system 這個目錄一般是程序在執行時動態建立 unit 檔案的目錄,一般很少修改,除非是修改程式執行時的一些引數時,即 Session 級別的,才在這裡做修改。
服務配置
- 每一個服務以.service 結尾,一般會分為 3 部分:[Unit]、[Service] 和 [Install],就以 nginx 為例吧,具體內容如下:
[Unit] Description=nginx - high performance web server Documentation=http://nginx.org/en/docs/ After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
配置項說明
- 下面分別解釋下著三部分的含義
[Unit]
- Description : 服務的簡單描述
- Documentation : 服務文件
- After= : 依賴,僅當依賴的服務啟動之後再啟動自定義的服務單元
[Service]
- Type : 啟動型別 simple、forking、oneshot、notify、dbus
- - Type=simple(預設值):systemd 認為該服務將立即啟動,服務程序不會 fork。如果該服務要啟動其他服務,不要使用此型別啟動,除非該服務是 socket 啟用型
- - Type=forking:systemd 認為當該服務程序 fork,且父程序退出後服務啟動成功。對於常規的守護程序(daemon),除非你確定此啟動方式無法滿足需求, 使用此型別啟動即可。使用此啟動型別應同時指定 PIDFile=,以便 systemd 能夠跟蹤服務的主程序。
- - Type=oneshot:這一選項適用於只執行一項任務、隨後立即退出的服務。可能需要同時設定 RemainAfterExit=yes 使得 systemd 在服務程序退出之後仍然認為服務處於啟用狀態。
- - Type=notify:與 Type=simple 相同,但約定服務會在就緒後向 systemd 傳送一個訊號,這一通知的實現由 libsystemd-daemon.so 提供
- - Type=dbus:若以此方式啟動,當指定的 BusName 出現在 DBus 系統總線上時,systemd 認為服務就緒。
- PIDFile : pid 檔案路徑
- Environment : 環境變數(可以新增多個)eg :Environment=REPO_REF=dev
- ExecStartPre :啟動前要做什麼,上文中是測試配置檔案 -t
- ExecStart:啟動
- ExecReload:過載
- ExecStop:停止
- PrivateTmp:True 表示給服務分配獨立的臨時空間
[Install]
- WantedBy:服務安裝的使用者模式,從字面上看,就是想要使用這個服務的有是誰?上文中使用的是:multi-user.target ,就是指想要使用這個服務的目錄是多使用者。
操作示例
- 每一個.target 實際上是連結到我們單位檔案的集合,當我們執行
systemctl enable nginx.service
- 就會在 /etc/systemd/system/multi-user.target.wants/ 目錄下新建一個 /usr/lib/systemd/system/nginx.service 檔案的連結。
常用的 service 操作
# 自啟動 systemctl enable nginx.service # 禁止自啟動 systemctl disable nginx.service # 啟動服務 systemctl start nginx.service # 停止服務 systemctl stop nginx.service # 重啟服務 systemctl restart nginx.service # 檢視Unit定義檔案 systemctl cat nginx.service # 編輯Unit定義檔案 systemctl edit nginx.service # 重新載入Unit定義檔案 systemctl reload nginx.service # 列出已啟動的所有unit,就是已經被載入到記憶體中 systemctl list-units # 列出系統已經安裝的所有unit,包括那些沒有被載入到記憶體中的unit systemctl list-unit-files # 檢視服務的日誌 journalctl -u nginx.service # 還可以配合`-b`一起使用,只檢視自本次系統啟動以來的日誌 # 檢視所有target下的unit systemctl list-unit-files --type=target # 檢視預設target,即預設的執行級別。對應於舊的`runlevel`命令 systemctl get-default # 設定預設的target systemctl set-default multi-user.target # 檢視某一target下的unit systemctl list-dependencies multi-user.target # 切換target,不屬於新target的unit都會被停止 systemctl isolate multi-user.target systemctl poweroff # 關機 systemctl reboot # 重啟 systemctl rescue # 進入rescue模式
Systemd + Golang Demo
- 下面例子通過 Systemd 部署一個最簡單的 Golang Web Server
package main import ( "flag" "fmt" "log" "net/http" ) func main() { var address string flag.StringVar(&address,"address","5353","listen address") flag.Parse() http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request) { fmt.Fprintf(w,"Hello,This is a test for systemd !\n") }) // 設定訪問路由 log.Printf("Starting server on %s\n",address) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s",address),nil)) }
- 編譯程式碼,並將可執行檔案同步到遠端伺服器上
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o systemd-test main.go rsync -zP ./systemd-test root@gp-aliyun:/usr/local/bin/
- 在遠端伺服器上編寫服務配置,放在 /etc/systemd/system/ 中
[Unit] Description=Systemd Test After=network.target [Service] User=nobody # Execute `systemctl daemon-reload` after ExecStart= is changed. ExecStart=/usr/local/bin/systemd-test -address "6060" [Install] WantedBy=multi-user.target
- 通過 systemctl 啟動服務
# 每一次修改ExecStart都需執行 systemctl daemon-reload # 啟動 systemctl start systemd-test.service # 檢視狀態 systemctl status systemd-test.service
- 狀態如下
- 可以通過 curl 進行測試:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。