2024-12-28

在用 Docker 架設 MSSQL 時,容器的啟用會警告 [Error response from daemon: Ports are not available...]

在網路上查到的文章大至上得到的說明是,這是因為 windows 可能在某個版本的升級開始會把某些 port 或某個範圍的 port 給「保留」,其中就有包含 mssql 一般慣用的 1433/tcp,而 windows 的一個 HNS 的服務有把一些 port 給「保留」

但也有一說是因為 windows 本身使用了 Hyper-V 把 1433/tcp 給保留了起來

我比較認為是 hyper-v 的問的,因為我目前的 docker 並不是運行在 WSL2 的,還是在比較早期要用 hyper-v 的虛擬機上,所以我比較認為是 hyper-v 引起的

故,如果有跟我遇到一樣問是的,可以先用

netsh interface ipv4 show excludedportrange protocol=tcp

的指定來列出被「保留」下來的 tcp port (注: 上述的指令要用「管理員身份」去執行)

如果上述的指令沒有列出你用到的 port ,那你的問題就比較偏向是你要用的 port 已被你電腦中其他的程序佔用,又或者是其他的程序先加到他自己的「保留」了,那有以下方式你可以試試

  • netstat -ano|findstr "port"
    • 此是先找目前電腦 listen 的 port 是不是有你要用的,如果有出現,此指令也會列出用這個 port 的 process id(PID),你如果確定這個程序你沒有要用或可以改 port 那你就中止這個程序或去改 port
    • 如果沒列出來,那再走以下的建議方式
  • net stop winnat && net start winnat
    • 把 winnat 這服務重啟,這個服務重啟後再去看上述「excludedportrange」的指令,理論上應該就會列出來的項目變少了
    • 此方式理論上應該是可以直接解決問題,但只是麻煩點,有可能要你在啟動 docker 容器時發現「Ports are not available...」時就要把 winnat 服務重啟,但我覺得此方式相對保險
  • 因為認為是 hyper-v 搞的,那來對 hyper-v 處理
    1. dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
      • 先把 hyper-v 這功能停用(注意: 如果你跟我一樣 docker 目前是跑在 hyper-v 上面的,這指令下去你 docker 就會異常,直到重新把 hyper-v 啟用)
    2. netsh interface ipv4 add excludedportrange protocol=tcp startport={port} numberofports=1
      • 把你的 {port} 增加到你自己要保留的設定中,這設定會讓有其他程序要用 {port} 時反而系統會告知該程序這個 {port} 已被保留不能用
    3. dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /ALL
      • 重新啟用 Hyper-v(注意: 如果重新啟用 hyper-v 後 docker 啟動有問題,那建議把 docker 重新安裝)
  • reg add HKLM\SYSTEM\CurrentControlSet\Services\hns\State /v EnableExcludedPortRange /d 0 /f
    • 此項…我認為是上述的方式都不行時再用,因為畢竟要動到regedit,多少有點風險
上述的方式請在做好備份後再使用,以免有一些嚴重的風險
我個人是只有把 winnat 服務重啟的動作後,重新啟動 mssql 容器就正常了

2024-08-17

[Python] pip install 套件時,最後出現`error: Microsoft Visual C++ 14.0 or greater is required`的解決方式

主要是在 windows 的環境使用 python 安裝套件…

有些套件安裝有相依的其他套件時,可能會出現一個訊息

error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

然後,在下載`Build Tools`後,卻往往不知道到底是要選擇安裝什麼…

這裡提供一個以下載的檔案`vs_buildtools.exe`為主的安裝指令

vs_buildtools.exe --norestart --passive --downloadThenInstall --includeRecommended --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools

以此指令就可以完成需求 

2024-06-01

[救援記事] EC2 Ubuntu 20.04 - systemd-journald[xxx]: File /run/log/journal/[...]/system.journal corrupted or uncleanly shut down, renaming and replacing.

前言: 這是公司的一台在未來要做主要的 DB server,幾天前 instance 才創建好,老闆就讓我有空在上面開始佈署相關的軟體跟設定,大至上在前一、兩天就都已經設定好了,因為並沒有急著上線使用,所以就先擺著,然後我也一樣時不時的上去刷系統更新,就前最近,跟前一篇救援記事提到的公司的測試機的狀況一下,系統更新完重開機就連不到了

狀況: 其這一台發生問題的時間比測試機早,這一台是我在上班時間發生的狀況,測試機是同一天的半夜…只不過,aws 的 ebs 只能掛載在同一個「可用區域」的 instance 中,這台 DB instance 的可用區域我老闆建置在別的地方,跟公司原本的可用區域的位置不同,所以一開始我沒辦法把 db 的 ebs 掛到另一個區域的救援機上,所以之前只能先救援測試機

就在凌晨把測試機救援回來就有相對的信心來處理 DB server

救援操作
  1. 啟動 DB instance
    • 雖然已經知道無法正常啟動,但我主要是要看截圖畫面看卡在哪,跟系統日誌
    • 系統日誌大至上和測試機異常時的日誌一樣,但截圖畫面不一樣,測試機卡住的畫面就只有一個游標,但 DB instance 是卡在 `systemd-journald[xxx]: File /run/log/journal/[...]/system.journal corrupted or uncleanly shut down, renaming and replacing.`
  2. 停止 DB instance
  3. detach DB EBS
  4. create Rescue instance
    • mini 的規格就行
    • 要記得可用區域要和 DB instance 同一個
  5. DB EBS attach to Rescue instance
  6. ssh 進入 Rescue instance
  7. sudo mount /dev/xvdf1 /mnt/recovery
    • xvdf1 是我自己編的,請以實際情況下的代號為主
  8. sudo chroot /mnt/recovery
  9. cd /var/log/journal
    • 因為這次的問題,系統並沒有啟動到 syslog 的服務,所以從 syslog 中看不到紀錄
    • 會找 journal 主要是因為 `systemd-journald[xxx]: File /run/log/journal/[...]/system.journal corrupted or uncleanly shut down, renaming and replacing.`
  10. journalctl -p5
    • 直接 cat system.journal 會看不懂,這個檔本身的資料編碼應該是特殊的,所以要透過 journalctl 來看 systemd 的紀錄
    • -p: priority, 列出指定等級的紀錄
      • 0: emerg
      • 1: alert
      • 2: crit
      • 3: err
      • 4: warning
      • 5: notice
      • 6: info
      • 7: debug
  11. 看到紅字的異常 `systemd[xxx]: multipathd.service: Failed to adjust resource limit RLIMIT_NOFILE: Operation not permitted`
    • 我主要是先看紀錄的時間,因為我還記得重新啟動的時間大概是什麼時候,所以以這個時間來看啟動紀錄中有沒有異常的,而紅字比較明顯
  12. 又是熟悉的 RIMIT_NOFILE…
    • /etc/sysctl.conf: 沒發現有設定 `fs.file-max` 和 `fs.nr_open`
    • /etc/sysctl.d/100-custom.conf: 這是新增出來的檔案,有加上 `fs.nr_open = 102400`
    • 我其實本來就有預期應該是和測試機是同一個問題,只是我沒想到的是我在 DB instance 並沒有在 /etc/sysctl.conf 設定 `fs.file-max = 102400`,所以可知這兩次的主因都是 `fs.nr_open`
  13. 將 `fs.nr_open` 先註解掉
  14. 退出 chroot(直接 exit)
  15. umount /mnt/recovery
  16. 退出 Rescue instance
  17. 停止 Rescue instance
  18. (確定已停止) detach DB EBS
  19. attach DB EBS 到 DB instance
  20. 啟動 DB instance
    • 啟動正常
救援 DB server 花的時間就沒有測試機來的久了
呼,好佳在都解決了

[救援記事] EC2 buntu 20.04 - systemd-udev-trigger.service: Failed to adjust resource limit RLIMIT_NOFILE: Operation not permitted

*心得: 好累,以後要切記進行系統更新前保險的做法是做一個快照

前言: 這是公司的一台測試區的環境,Ubuntu 20.04 LTS,這一台從開始就是公司讓我去建置的,所以我大概五至十天就會上來刷更新,但就在最近,有 intel-microcode, libc-bin, libc-dev-bin, libc6, libc6-dev, libtss2-esys0, locales, ubuntu-advantage-tools, ubuntu-pro-client, ubuntu-pro-client-l10n 列出要更新,所以我一如往常的就進行更新,然後因為 intel-microcode 的關係,所以會需要重開機,但我進行重開機之後就再也連不到了

狀況: 重開機後我 ssh 就一直連不到,而且重點是發生在半夜…沒辦法,我只能先向老闆報告,也說明我更新的操作是一直以來就有,但唯獨這次有狀況…我跟老闆借了公司的 aws console 的帳號,登入進去後,在 instance>> 那看到測試的狀況是 "running",但是…在檢查執行狀況那邊是 1/2 的情況,而且這個時候已經不能用 aws console 提供的 web connection 連到主機中

所以先看 aws console 的提供的系統日誌,因為 web 版的系統日誌中帶有一些奇怪的亂碼,但在可讀的資料中已經有發現不少 "failed to start...", "failed to mount..." 訊息,所以想到把測試機的 EBS 給 detach,然後再 attach 到 Rescue 的 instance 中,來檢查一下

救援操作
  1. ssh 進入 Rescue instance
  2. sudo mount /dev/xvdf1 /mnt/recovery
    • xvdf1 是我自己編的,這個請以實際情況下的代號為主
  3. sudo chroot /mnt/recovery
  4. cat /var/log/syslog | more
    • 翻到發生問題的時間,看看當時開機的記錄
  5. 找到第一個出現 Failed 或類似錯誤、啟動失敗的訊息,在我的狀況中,我第一個出現的是 `systemd-udev-trigger.service: Failed to adjust resource limit RLIMIT_NOFILE: Operation not permitted`
  6. 看到 RLIMIT_NOFILE 時,我就想到在這次更新之前,我因為在優化 mysql 的關係,有在以下兩個檔案處加了東西
    • /etc/sysctl.conf: `我在最後加上了 `fs.file-max = 102400`
    • /etc/sysctl.d/100-custom.conf: 這是新增出來的檔案,裡面只有加上 `fs.nr_open = 102400`
  7. 將 `fs.file-max` 和 `fs.nr_open` 先註解掉
  8. 退出 chroot(直接 exit)
  9. umount /mnt/recovery
  10. 退出 Rescue instance
  11. 停止 Rescue instance
  12. (確定已停止) 將本來 attach 給 Rescue instance 的要救援的 EBS 給 detach,然後再 attach 回原本的 測試機 instance
  13. 啟動 測試機 instance
    • 啟動正常
上述的狀況看起來花的時間不多,但實際上…這只是我精簡的操作,因為我本來並沒想到跟 RIMIT_NOFILE 有關,因為在看 syslog 時,一開始的注意力被 amazon-ssm-agent 這服務總是出現 404 的紀錄而感到困惑

然後我在還沒想到是 RIMIT_NOFILE 有關前,我都以為是因為做了系統更新的關係,我還想到要修改 grub,或者是把當時更新的套件都退版回去,在都是無效的情況下,又再一次想到真的逐筆的把 syslog 紀錄給看完後才發現 RIMIT_NOFILE 有關

唉,真是手賤

2024-05-29

[Certbot] ImportError: cannot import name 'appengine' from 'urllib3.contrib' ...

*Certbot 是一個由 Let's Encrypt 的組織維護的一個用來申請加密憑證的工具

之前公司網站的 https 憑證是透過 Certbot 的來輔助申請使用的,公司網站的系統是 Ubuntu 18.04 LTS ,在安裝好 Certbot 後,它會在 /etc/cron.d 中增加一個 certbot 的排程,定期是每天的「0 */12 * * *」會執行 renew 檢測操作

憑證一般申請後的有效期是三個月,但一般應該是可以提前幾天就讓你 renew 展延

而最近我會發現異常是因為在五月初收到來自 Let's Encrypt Expir 寄過來告知還有 xx 天就要過期了,要記得去 renew ,當時我就覺得怪怪的,因為公司這個憑證已經運行有幾年了,我還是第一次收到通知信,不過當時我還有別的事在忙,想說因為有排程會去自動 renew 也就沒有多想

直到前幾天我又收到同一封告知即將要過期的信,我才認真的去檢查

一開始先查看是不是 /etc/cron.d/certbot 是不是被刪或裡面的排程設定被動過了,但檢查後覺得是正常的,再來就是去檢查排程執行時所記錄的 syslog ,在查看「grep -i "certbot" /var/log/syslog」後發現,certbot 的排程執行時有異常,大至的訊息如下

systemd[1]: Starting Certbot
certbot[...]: Traceback (most recent call last):
certbot[...]:  File "/usr/lib/python3/dist-packages/requests_toolbelt/_compat.py"....
...
...
...
certbot[...]: ImportError: cannot import name 'appengine' from 'urllib3.contrib' ...
systemd[1]: certbot.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: certbot.service: Failed with result 'exit-code'.
systemd[1]: Failed to start Certbot

在 google 之後,大部份的建議都是將 python library 中的 urllib3 給移除就可以了,然後執行「sudo pip uninstall urllib3」,再輸入 y 確定要移除
*用 sudo 是因為 certbot 是以 root 身份執行的,所以 urllib3 的套件是安裝在 root 的 python library 之下

然後再手動讓 certbot 跑 renew 就沒有出現上述的異常訊息,而且憑證也更新了
*手動 renew 指定「sudo certbot -q renew」