2025年8月25日 星期一

樹莓派 Pi 3A+ 更改虛擬記憶體 swap 大小

上周末將 Pi 3 A+ 重灌 回 32 位元的 Buster, 打算拿來當爬蟲專用主機, 兼測試網站之用, 但安裝 streamlit 與 Pandas 時出現 piwheels 的 hash 不符而無法安裝問題, 詢問 ChatGPT 解決辦法, 它建議關掉 piwheels 讓 pip 直接從 PyPI 下載原始碼, 如果安裝像 Pandas 這樣的大型套件就會自動編譯, 但會比較花時間 (可能 1 小時以上). 

piweels 的設定檔為 /etc/pip.conf :

pi@raspberrypi:~ $ cat /etc/pip.conf  
[global]
extra-index-url=https://www.piwheels.org/simple  

可以用下列指令檢查目前 pip 設定檔是向 piwheels 還是 PyPI 下載 : 

pi@raspberrypi:~ $ python3 -m pip config list  
global.extra-index-url='https://www.piwheels.org/simple'

如果關掉 piwheels 的話則會顯示 global.index-url='https://pypi.org/simple'. 

關掉 piweels 的方法是用 sudo nano 編輯 /etc/pip.conf 檔, 刪除 extra-index-url 整列後存檔即可 :

pi@raspberrypi:~ $ cat /etc/pip.conf  

但我關掉 piwheels 後重新用 pip3 install 指令安裝 Pandas 跑了好久最後因記憶體爆掉 (out of memory, OOM) 而失敗. ChatGPT 說 Pi 3 A+ 的 512MB 記憶體太少了, 編譯原始碼很容易爆掉, 解決辦法是加大硬碟的 swap 空間, 當 RAM 不夠用時就會調用 swap 記憶體以避免 OOM. 

調整 swap 大小要用 sudo nano 編輯 /etc/dphys-swapfile 設定檔 :

pi@raspberrypi:~ $ sudo nano /etc/dphys-swapfile    

將 CONF_SWAPSIZE 參數由預設值 100 (MB) 改為 1024 (MB), 即 1GB :




按 Ctrl+O 存檔再按 Ctrl+X 跳出 nano 後重啟 swap 設定服務 : 

pi@raspberrypi:~ $ sudo systemctl stop dphys-swapfile  
pi@raspberrypi:~ $ sudo systemctl start dphys-swapfile   

檢查記憶體 : 

pi@raspberrypi:~ $ free -h   
              total        used        free      shared  buff/cache   available
Mem:          428Mi       154Mi        61Mi        17Mi       213Mi       207Mi
Swap:         1.0Gi          0B       1.0Gi  

果然已經改成 1GB 了. 

以上更改 swap 動作可以自動化執行, 我請 ChatGPT 幫我寫一個如下可檢視與設定 swap 大小的 shell 程式, 用 nano 編輯  swap_resize.sh : 

pi@raspberrypi:~ $ nano swap_resize.sh   

輸入如下 shell 程式 : 

#!/bin/bash
# 一鍵調整 Raspberry Pi swap 大小
# 用法:
#   sudo ./swap_resize.sh [大小MB]
# 範例:
#   sudo ./swap_resize.sh 1024   # 設定 1GB swap
#   sudo ./swap_resize.sh        # 只檢查目前狀態

CONF_FILE="/etc/dphys-swapfile"

# 如果沒輸入參數,就顯示目前 swap 狀態
if [ -z "$1" ]; then
    echo "ℹ️ 目前的 swap 設定:"
    grep CONF_SWAPSIZE $CONF_FILE
    echo ""
    echo "💻 系統實際使用的記憶體狀態:"
    free -h
    exit 0
fi

SWAPSIZE=$1

echo "👉 設定 swap 大小為 ${SWAPSIZE} MB ..."
sudo sed -i "s/^CONF_SWAPSIZE=.*/CONF_SWAPSIZE=${SWAPSIZE}/" $CONF_FILE

echo "🔄 套用新設定..."
sudo systemctl stop dphys-swapfile
sudo systemctl start dphys-swapfile

echo "✅ 完成!目前的記憶體狀態:"
free -h

按 Ctrl+O 存檔再按 Ctrl+X 跳出 nano 後, 用 chmod 更改權限為可執行 : 

pi@raspberrypi:~ $ chmod +x swap_resize.sh   

執行 shell 程式不傳參數的話預設會顯示目前的 swap 大小 : 

pi@raspberrypi:~ $ ./swap_resize.sh   
ℹ️ 目前的 swap 設定:
CONF_SWAPSIZE=1024   

💻 系統實際使用的記憶體狀態:
              total        used        free      shared  buff/cache   available
Mem:          428Mi       154Mi        60Mi        17Mi       213Mi       206Mi
Swap:         1.0Gi          0B       1.0Gi

調整 swap 大小的指令如下 :
  • 設為 512MB :
    sudo ./swap_resize.sh 512
  • 設為 1GB :
    sudo ./swap_resize.sh 1024
  • 設為 2 GB :
    sudo ./swap_resize.sh 2048
我將 swap 改為 1GB, 將 pip 設定檔改回 piwheels 後安裝 Pandas 花了兩小時才安裝完畢 :

pi@raspberrypi:~ $ python -m pip install pandas    
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pandas
  Downloading https://files.pythonhosted.org/packages/b2/4c/b6f966ac91c5670ba4ef0b0b5613b5379e3c7abdfad4e7b89a87d73bae13/pandas-0.24.2.tar.gz (11.8MB)
    100% |████████████████████████████████| 11.8MB 9.5kB/s 
Requirement already satisfied: numpy>=1.12.0 in /usr/lib/python2.7/dist-packages (from pandas) (1.16.2)
Collecting python-dateutil>=2.5.0 (from pandas)
  Downloading https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229kB)
    100% |████████████████████████████████| 235kB 794kB/s 
Collecting pytz>=2011k (from pandas)
  Downloading https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl (509kB)
    100% |████████████████████████████████| 512kB 476kB/s 
Requirement already satisfied: six>=1.5 in /usr/lib/python2.7/dist-packages (from python-dateutil>=2.5.0->pandas) (1.12.0)
Building wheels for collected packages: pandas
  Running setup.py bdist_wheel for pandas ... done
  Stored in directory: /home/pi/.cache/pip/wheels/47/0a/bf/fd3647f5bc74698ed95dbdbb3d8d120cfe0280969c212cdb6c
Successfully built pandas
Installing collected packages: python-dateutil, pytz, pandas
Successfully installed pandas-0.24.2 python-dateutil-2.9.0.post0 pytz-2025.2

過程中我開第二個終端機用 top 觀察記憶體消長, 發現 swap 大約使用 220MB 左右, 可見預設 100MB 根本不夠用 : 




但即使將 swap 大小擴增, 也只有在 Python2 安裝 Pandas 能成功, 在 Python3 仍然因為 piwheels 的 hash 問題無法安裝 : 

pi@raspberrypi:~ $ python3 -m pip install django
Defaulting to user installation because normal site-packages is not writeable
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting django
  Downloading https://www.piwheels.org/simple/django/Django-3.2.25-py3-none-any.whl (7.9 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━━━━ 5.4/7.9 MB 173.2 kB/s eta 0:00:15
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    django from https://www.piwheels.org/simple/django/Django-3.2.25-py3-none-any.whl#sha256=5559c6d7ffba3c5a9688ec40495b059da6aa6812a2fe17b5a584d6326a05cc69:
        Expected sha256 5559c6d7ffba3c5a9688ec40495b059da6aa6812a2fe17b5a584d6326a05cc69
             Got        d50ab2dd0ca599a4c47b9e15299cf7747f864abffa3371afda6b8ece3d8f47a0

這不是記憶體問題, 而是 piwheels 的問題. 算了, 在 Pi 3 A+ 上就只用 Flask 測試好了, 需要用到 Pandas 就退回去用 Python2. 

沒有留言 :