創建Linux服務,輕鬆管理(自啟動,恢復)進程
- 2020 年 1 月 23 日
- 筆記
有這樣一個場景,在一台伺服器上,我們想要啟動一個簡單的網路文件伺服器,用來提供給內網的用戶下載。
這裡,我們使用ruby啟動一個服務
- 使用
ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000
啟動文件伺服器 - 使用
ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000 &
將該進程設置為後台執行 - 為了防止掛起,我們還需要使用nohup處理。像這樣
nohup ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000 &
如上面設置一番,基本上可以工作了。
但是還有一些問題,比如
- 進程意外停止了,無法自動啟動
- 伺服器重啟,該進程也不會自動啟動
那麼我們有沒有什麼好的辦法解決呢,答案是有的。就是下面介紹的使用systemd創建Linux 服務的方式解決。
創建服務Unit文件
創建一個服務文件,比如這裡叫做vim /etc/systemd/system/apk_server.service
(可以將apk_server替換為你希望的名稱)
內容如下
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=APK Server Service StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root ExecStart=/usr/bin/env ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000 [Install] WantedBy=multi-user.target |
---|
重點可能需要替換的有
- Description 該服務的描述資訊
- User 填寫真實的用戶名稱,也可以填寫root不修改。
- ExecStart 必須替換為你需要執行的命令。
基本搞定了
啟動服務
1 |
systemctl start apk_server.service |
---|
停止服務
1 |
systemctl stop apk_server.service |
---|
重新啟動服務
1 |
systemctl restart apk_server.service |
---|
設置開啟自啟動
1 2 3 |
systemctl enable apk_server.service //執行結果 Created symlink /etc/systemd/system/multi-user.target.wants/apk_server.service → /etc/systemd/system/apk_server.service. |
---|
其他欄位解釋
- StartLimitIntervalSec 啟動頻率限制,設置為0
- Restart=always 當進程退出後自動重啟
- RestartSec 重啟延遲時間,單位為毫秒
- WantedBy 自動啟動相關參數
查看服務狀態
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
systemctl status apk_server.service ● apk_server.service – APK Server Service Loaded: loaded (/etc/systemd/system/apk_server.service; disabled; vendor preset: disabled) Active: active (running) since Fri 2019-12-xx 22:06:40 CST; 9s ago Main PID: 17802 (ruby) Tasks: 2 (limit: 26213) Memory: 15.8M CGroup: /system.slice/apk_server.service └─17802 ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000 localhost.localdomain systemd[1]: Started APK Server Service. localhost.localdomain env[17802]: [2019-12-xx 22:06:40] INFO WEBrick 1.4.2 localhost.localdomain env[17802]: [2019-12-xx 22:06:40] INFO ruby 2.5.3 (2018-10-18) [x86_64-linux] localhost.localdomain env[17802]: [2019-12-xx 22:06:40] INFO WEBrick::HTTPServer#start: pid=17802 port=8000 |
---|
配置更新
當我們修改了之前的service文件後,會得到的提示
Warning: The unit file, source configuration file or drop-ins of apk_server.service changed on disk. Run 『systemctl daemon-reload』 to reload units.
所以,當我們每次修改後,都需要執行systemctl daemon-reload
確保配置生效。
排查錯誤
查找錯誤資訊
可以使用使用兩種方法
- 第一種是
systemctl status
,上面介紹的 - 第二種是
journalctl
journalctl
journalctl相對提供的日誌會更多一些,使用方法也很簡單
1 |
journalctl -u coo_code_review.service –no-pager –reverse |
---|
對應的日誌就能看到了
1 2 3 4 5 |
localhost.localdomain systemd[1]: coo_code_review.service: Failed with result 'exit-code'. localhost.localdomain systemd[1]: coo_code_review.service: Service RestartSec=1s expired, scheduling restart. localhost.localdomain systemd[1]: coo_code_review.service: Scheduled restart job, restart counter is at 52. localhost.localdomain systemd[1]: Stopped Coo Code Review Service. localhost.localdomain systemd[1]: Started Coo Code Review Service. |
---|
code=exited, status=217/USER
1 2 3 4 5 |
apk_server.service – APK Server Service Loaded: loaded (/etc/systemd/system/apk_server.service; disabled; vendor preset: disabled) Active: activating (auto-restart) (Result: exit-code) since Fri 2019-12-20 14:03:12 CST; 409ms ago Process: 17535 ExecStart=/usr/bin/env bash /root/startApkServer.sh (code=exited, status=217/USER) Main PID: 17535 (code=exited, status=217/USER) |
---|
通常的錯誤原因是上面配置中的User設置的用戶名不對。更新正確即可
設置工作目錄
很多是否我們的命令會是這樣
- 進入一個目錄
- 然後執行命令
但是當我們這樣設置ExecStart=/usr/bin/env cd your_dir && ruby -run -ehttpd easy_file_server/ -p8000
是有問題的。好在可以這樣設置工作目錄
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[Unit] Description=APK Server Service StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root WorkingDirectory=/root/your_dir ExecStart=/usr/bin/env ruby -run -ehttpd /home/webbuild/easy_file_server/ -p8000 [Install] WantedBy=multi-user.target |
---|
通過增加WorkingDirectory=/root/your_dir
可以解決問題。
設置環境變數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[Unit] Description=xxxxx Service StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root Environment="ANDROID_HOME=/opt/android-sdk-linux" WorkingDirectory=/root/automan/xxx ExecStart=/usr/bin/env bash /root/automan/xxx/gradlew run [Install] WantedBy=multi-user.target |
---|
使用上面的程式碼,我們就增加了ANDROID_HOME=/opt/android-sdk-linux
這個環境變數。
如果是多個環境變數,設置多行Environment="ANDROID_HOME=/opt/android-sdk-linux"
就行
203/EXEC 錯誤
1 2 3 |
localhost.localdomain systemd[1]: Started Coo Code Review Service. localhost.localdomain systemd[1]: coo_code_review.service: Main process exited, code=exited, status=203/EXEC localhost.localdomain systemd[1]: coo_code_review.service: Failed with result 'exit-code'. |
---|
解決方法,增加/usr/bin/env
1 |
ExecStart=/usr/bin/env bash /root/automan/xxxxx/gradlew run |
---|