iT邦幫忙

2024 iThome 鐵人賽

DAY 19
1
Software Development

從零開始構建能理解語義的 Linebot 架構系列 第 19

執行環境設定: 背景執行與記憶體監控指令

  • 分享至 

  • xImage
  •  

概述

本專案的BotServer和其他外部系統都在同一台EC2上運行,因此記憶體監控顯得格外重要,畢竟經費有限。
而在上一篇的描述中我們可以知道,影響成本最大的除了CPU外,就是記憶體的耗能,
為了確保應用程式順利執行,並能掌握記憶體的使用狀況,在進入後續章節之前,本文將先介紹如何在Linux環境中讓應用程式在背景執行,以及基本的記憶體監控指令。
這些指令將有助於我們確保程式順利運行,並且可以隨時監控記憶體的消耗狀態。

背景執行與記憶體監控指令

為什麼要在背景執行?

  • 當我們透過終端機(Terminal)遠端連線到一台Linux環境的Server,並且下指令執行程式時,一但連線中斷,程式也會跟著停止執行。
    可想而知,我們不可能一直保持跟Server的連線,但又需要讓程式隨時保持待命來服務客戶端的需求。所以需要一個方式,讓這些已經跑起來的程式在我們中斷連線並退出終端機時,不會因此中斷。
    簡單來說,需要讓程式在背景執行,同時避免因為收到SIGHUP訊號導致中斷。
  • 以下將介紹如何在Linux環境中,使用 &nohup讓程式在背景執行,同時避免程式因為 SIGHUP訊號而中止。
  • 與此同時,還需要讓執行程式的相關訊息輸出到外部檔案,我們才能掌握程式運作的狀況。

使用 Ampersand (&) 在背景執行程式

$ 指令 &
  • 在執行程式後加上 &,即可讓程式在背景執行,在背景執行可以讓你不需要透過Ctrl + C中斷程式,也可以進行別的操作。

  • 需要注意的是,當Linux發送SIGHUP訊號時,程式仍然會中止,例如在退出終端機時。

  • SIGHUP:

    • 是一種由Unix系統對程序(Process)發出的訊號,通常的作用是導致Process中斷。
    • 當某個連線退出終端機而中斷時,Unix會對所有由這個連線執行的Process發出SIGHUP。
    • 除了導致中斷以外,有些守護程序(Ex: nginx)在收到SIGHUP不會結束主要程序,而是會觸發重新載入設定檔,使得相關程式不用重新執行,也能套用(重刷)User更新過的設定檔。

使用 nohup 防止 SIGHUP 訊號中止程式

$ nohup 指令 &
  • nohup指令可以無視SIGHUP訊號,避免程式中止。然而,nohup 只負責防止訊號中止,要讓程式在背景執行,仍需加上 &

資料流重定向與輸出處理

Linux的三個標準資料流

在Linux中,定義了三個標準資料流:

  • stdin (0):標準輸入,預設是從鍵盤輸入。
  • stdout (1):標準輸出,通常指一般的程式輸出。
  • stderr (2):錯誤輸出,通常代表程式的Error log。
    其中,stdoutstderr是否有區別,取決於應用程式有沒有對這兩種訊息的輸出做區分。

丟棄輸出

  • /dev/null: 丟棄輸出,有點像把訊息丟到黑洞去
    • /dev/null 是 Linux 中的特殊裝置檔案,用於丟棄不需要的輸出。
    • 當將資料寫入 /dev/null,資料會被丟棄,但系統會回報成功,不會出現錯誤。

常用的資料流重定向符號: >, &

可以使用這些符號,把一般的程式輸出或Error log寫到檔案。>是指定檔案輸出,而代表資料流的符號和前面提到的背景執行一樣,都是Ampersand (&),但用法不太相同。
使用方法如下:

&>檔名

  • 拆解成以下兩個部分:
    • x>檔名
      • 將x資料流輸出到指定名稱的檔案。
    • &
      • &後面加上編號,代表某資料流, Ex: &1代表stdout。
      • &後面沒有加上編號,則代表所有的資料流。
  • 所以把上述內容組合起來,&>檔名代表著 把stdout和stderr全部輸出到指定的檔案

另外一個用法:2>&1

  • 2> 代表將stderr輸出到檔案
  • &1 = stdout
  • 所以2>&1 代表把stderr輸出到stdout輸出的檔案

2>&1&>檔名的差別

  • 基本上只要2>&1有指定stdout的檔案名稱,他們的效用是一樣的,都是把所有輸出寫到同一個檔案。
  • 一個微小的差別在於,&>檔名Bash特有的語法,只在Bash和一些支持此語法的Shell中可用。在其他一些Shell中(sh),這個語法可能無效。
  • 2>&1 是更通用的語法,適用於大多數Unix-like系統的Shell。

資料流重定向與背景執行範例:

1.將標準輸出與錯誤輸出合併,都寫到out.file。

$ 指令 > out.file 2>&1

2.將標準輸出與錯誤輸出合併,都寫到out.file,並且在背景執行且不會因中斷連線而中斷

$ nohup 指令 > out.file 2>&1 &
# 前面的&1指的是資料流,最後的&代表程式要在背景執行,而開頭的nohup則是無視SIGHUP訊號,避免程式中止

3.將輸出丟棄至 /dev/null:

$ nohup 指令 > /dev/null 2>&1 &

效能監控: top

在終端機輸入top就可以看到效能資訊,下面介紹一些top會顯示的資訊內容,以及一些名詞解釋:

顯示系統資源使用情況

top能顯示系統當前的CPU、Memory、Swap的使用率,以及各個Process的資源使用情況。

動態刷新

預設每隔幾秒鐘自動刷新一次,可以隨時查看系統的最新狀態。

Process排序

預設情況下,Process依照CPU使用率排序,但可以根據需要按其他資源(例如記憶體使用量)進行排序。

CPU使用率

  • us(user): User執行的Process使用的CPU時間百分比。
  • sy(system): 系統執行的Process使用的CPU時間百分比。
  • id(idle): CPU閒置時間百分比。
  • wa(wait): 等待I/O操作的時間百分比。

記憶體使用率

  • total: 總記憶體大小。
  • free: 可用記憶體大小。
  • used: 已使用的記憶體大小。
  • buff/cache:用作快取的記憶體大小。
  • Swap: 交換區的使用情況。
  • 按下E時,可以切換Memory的顯示單位,例如Kib / Gib。

Swap

OS會預定一部份的硬碟空間(磁區),當Memory不夠用時,會用個硬碟的空間充當記憶體來暫存資料。

每個Process中的VIRT(Virtual Memory)代表的意義

  • 當Process在執行時,OS會分配給Process一塊虛擬的連續記憶體位址空間(一串連續的記憶體位址, 不是記憶體空間本體)。這些虛體記憶體位址會對應到實體記憶體位置,讓Process可以在這些位址對應的Memory存放資料或程式碼,這個Memory區塊就是Virtual Memory。

為什麼叫虛擬(Virtual)?

  • 因為實際上,這些位址對應的不完全是真正的實體記憶體(Physical Memory)位址,有一部份是從硬碟空間拿來充當記憶體的。所以又稱為Logic Memory

Paging / Page

  • Virtual Memory是由多個同樣大小(通常是4kb, 但根據不同OS會不同)的小區段為單位組成,這些小區段稱為Page
  • 在Linux系統中,x86架構下的Page大小通常是4KB,而在ARM架構下的Page大小通常是16KB或64KB。

為什麼要配置Virtual Memory?

  • 節省Phisical memory空間,有效率的使用Memory
  • 讓每個Process擁有自己獨立的位址空間,這樣它們就可以在自己的位址空間中運作而不會互相干擾,Process可以認為它們是在獨佔整個系統的Memory空間。
  • 哪些Page會被擺在Disk?
    在實際執行程式時,有些程式碼或資料只有在初始階段,或者極少被用到,這些東西就會被OS放到IO速度比較慢的x硬碟裡面。

總結

  • 本文介紹了在Linux環境下,讓程式背景執行的指令,並詮釋top的資訊。這些知識在系統的維運上經常被使用,希望能幫助第一次接觸,或者常被這些資訊混淆的讀者釐清它們所代表的意義。
  • 後續在說明Bot Server時,也會用同樣的方式來執行。

上一篇
執行環境設定: AWS EC2 設定指南
下一篇
使用 Spring Boot 開發 Backend Bot Server: 從 IoC 容器到 DI 實踐
系列文
從零開始構建能理解語義的 Linebot 架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言