2025/03/03

Pyinstaller With Tobix Pywine

Python 可以透過 PyInstaller 將執行檔編譯成 Windows 可以使用的 exe,很好用,不同的 python 版本編譯出來的 exe 對目前的 Windows 有不同的支援度:

Python 版本 Windows 7 Windows 8 Windows 10 Windows 11
Python 3.6 ✅ (最後支援)
Python 3.7
Python 3.8
Python 3.9
Python 3.10 ⚠️ (可能有問題) ⚠️ (可能有問題)
Python 3.11 ❌ (不支援) ❌ (不支援)
Python 3.12 ❌ (不支援) ❌ (不支援)

所以編譯的時候要考量 python 的版本,Pyinstaller 只有支援 Windows,在 Linux like 的環境要執行必須透過 Wine 這種指令驅動,如果你要跑 CI/CD 沒那麼方便,後來我選擇了 tobix/pywine - Docker Image | Docker Hub 這個 docker 專案,只要選擇你要的 python 版本,如 tobix/pywine:3.8 ,將外部的 python 檔案 mount 進去 container,執行 docker exec -it builder wine pyinstaller.exe -F xxx.py 便可以編譯了,如果有相關要安裝的套件,也可以事先執行 docker exec -it builder wine python.exe -m pip install -r /tmp/requirements.txt

Docker PHP Extension Installer

我是一位 PHP 開發者,目前許多的 production 專案也會用到 docker 了,所以套件安裝經常會在 Dockerfile 出現,在 php - Official Image | Docker Hub 上你要安裝 extension,他的範例是:

FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
libfreetype-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd

這樣寫蠻醜的也不好維護,後來找到了好用的 mlocati/docker-php-extension-installer: Easily install PHP extensions in Docker containers,安裝方式就變得很乾淨。

FROM php:7.2-cli
RUN curl -sSLf \
-o /usr/local/bin/install-php-extensions \
https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \
chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions gd xdebug

install-php-extensions 一直增加你要的東西就可以,下方還有各 PHP 有哪些支援的 extension 表格對應,可以安裝 composer 版本也很貼心。

# Install the latest version
install-php-extensions @composer
# Install the latest 1.x version
install-php-extensions @composer-1
# Install a specific version
install-php-extensions @composer-2.0.2

Force LF EOL In Git

Windows 以及 MacOS 或 Linux 的換行符號是不太一樣的,Windows 是 CRLF,Linux like 是 LF,在 Windows 使用 git 如果沒有有設定參數,pullcommit 時 git 有可能會幫你自己轉換行符號,這樣會導致 git 在你沒有修改任何內容的情況下判定你有更改檔案,為了避免這樣的狀況最好是設定以下的內容:

$ git config core.eol lf
$ git config core.autocrlf input

Reference

github - Force LF eol in git repo and working copy - Stack Overflow

Scoop Update Command

我在 Windows 上使用 PowerShell 搭配 scoop 來 maintain 我的常用工具已經一陣子了,由於我是更新控,所有的軟體只要出了新版本我都要安裝,scoop 可以用指令來自動偵測更新,以下是我使用的更新命令。

scoop update && scoop update * && scoop cleanup * && scoop cache rm *

指令說明

  • scoop update:更新軟體庫
  • scoop update *:更新所有可以更新的軟體
  • scoop cleanup *:將舊版本刪除
  • scoop cache rm *:將 temp 的安裝檔案清除

2025/02/27

Git Export Modified Files From Commit

我們會遇到某些案子只能用 ftp deploy,會遇到只需要 upload 你修改內容的檔案這件事情,git 有可以做到這件事的指令,git archieve,該指令讓你指定 commit 後匯出從該 commit 到最後 commit 的修改檔案。

git archive -o changes.zip HEAD $(git diff --name-only 91455ec0^ HEAD)

只要將後面的 commit hash 改成你這波修改的開始就可以將修改的內容包含原始目錄結構匯出成 changes.zip,省去每次都要大量覆蓋的問題,如果你是使用 JetBrains 的軟體,並且使用他的 git 管理介面以及 ftp 功能,你可以在一整排你要上傳的使用 Ctrl + Shift + Alt + x 叫出 ftp 上傳介面,他很聰明的就會上傳你選擇的所有 commit 的修改檔案上去,很方便,我真的覺得 JetBrains 可以考慮把他的 git 管理工具獨立成一套軟體,像是 Sourcetree 那樣可以單獨使用,真的很好用。

2025/02/12

Linux Find

之前客戶 server 遇到單一目錄檔案過大問題,使用 rm -f * 或者是砍掉整個目錄都遇到 arguments 過多問題,最終使用 find 指令解決,有在使用 Linux 的人一定知道 find 的強大,在這邊作把常用的案例濃縮筆記一下。

範例

一般

find . -type f -name "lebron*" # 搜尋 lebron 為首的檔案
find . -type f -iname "lebron*" # 搜尋 lebron 為首的檔案(不區分大小寫)
find . -type d -name "lebron*" # 搜尋 lebron 為首的目錄

時間類

參數 說明 單位 範例 說明
atime 檔案最後存取的時間 find /path -atime -7 找出 7 天內被存取過的檔案
ctime 檔案的 inode 最後變更時間 find /path -ctime +30 找出 30 天前 inode 變更的檔案(如權限修改)
mtime 檔案內容的最後修改時間 find /path -mtime 0 找出今天內修改過內容的檔案
amin 檔案最後存取的時間 分鐘 find /path -amin -60 找出 60 分鐘內被存取過的檔案
cmin 檔案的 inode 最後變更時間 分鐘 find /path -cmin +120 找出 120 分鐘前 inode 變更的檔案
mmin 檔案內容的最後修改時間 分鐘 find /path -mmin -30 找出 30 分鐘內修改過內容的檔案

-time

指令 查詢範圍 檔案舉例(假設今天是 2024/02/21)
-mtime +3 4 天前或更早 ✅ 2024/02/17、✅ 2024/02/16
-mtime 3 剛好 3 天前 2024/02/18
-mtime -3 最近 3 天內(包含今天) ✅ 2024/02/21、✅ 2024/02/20、✅ 2024/02/19
-mtime 0 今天(00:00 之後) 2024/02/21(今天)

min

指令 查詢範圍 檔案舉例(假設現在是 12:00 PM)
-mmin +30 31 分鐘前或更早 ✅ 11:29 AM、✅ 11:00 AM
-mmin 30 剛好 30 分鐘前 11:30 AM
-mmin -30 最近 30 分鐘內(含現在) ✅ 12:00 PM、✅ 11:50 AM、✅ 11:45 AM
-mmin 0 最近 1 分鐘內(剛改變) 12:00 PM

空間類

參數 說明 單位 範例 說明
-size 指定檔案大小 512-byte blocks (預設) find /path -size +100M 找出大於 100MB 的檔案
-empty 找出空檔案或空目錄 N/A find /path -empty 找出空檔案或空目錄
-maxdepth 限制搜尋深度 N/A find /path -maxdepth 2 -size +1G 限制搜尋到最多 2 層目錄內,找出大於 1GB 的檔案
-type f 限制搜尋結果為檔案 N/A find /path -type f -size -50k 找出小於 50KB 的檔案
-type d 限制搜尋結果為目錄 N/A find /path -type d -size +10M 找出超過 10MB 的目錄(通常為不常見情況)

-size 常見用法:

  • find /path -size +1G → 找出 大於 1GB 的檔案
  • find /path -size -500k → 找出 小於 500KB 的檔案
  • find /path -size 100M → 找出 剛好 100MB 的檔案
  • find /path -size +100M -size -500M找出大小介於 100MB ~ 500MB 之間的檔案

-size 可用單位:

  • cbytes(例如 -size +1024c 找出大於 1024 bytes 的檔案)
  • kKB(例如 -size -500k 找出小於 500KB 的檔案)
  • MMB(例如 -size +10M 找出大於 10MB 的檔案)
  • GGB(例如 -size +1G 找出大於 1GB 的檔案)

顯示

格式 說明 範例
%p 檔案的完整路徑 ./test.txt
%f 檔案的名稱(不包括路徑) test.txt
%s 檔案的大小(以 byte 為單位) 1024
%M 檔案的權限(如 ls -l 顯示) -rw-r--r--
%u 檔案的擁有者 user1
%g 檔案的群組 group1
%T@ 檔案的最後修改時間,Unix 時間戳 1592390505.000000000
%TY-%Tm-%Td 檔案的修改日期(年-月-日) 2024-02-12
%TH:%TM:%TS 檔案的修改時間(時:分:秒) 14:30:15
%p 檔案的路徑 ./folder/test.txt
%k 檔案的大小(以 1KB 為單位,四捨五入) 1
%l 檔案是符號連結時,顯示其指向的檔案路徑 ./link_to_file.txt
%c 檔案的創建時間(僅支援某些檔案系統) 2024-02-10 12:00:00

顯示檔案名稱與大小(以 KB 為單位)

find . -type f -printf "%s KB\t%p\n"
1024 KB ./file1.txt
2048 KB ./file2.log

顯示檔案的修改日期與名稱

find . -type f -printf "%TY-%Tm-%Td %p\n"
2024-02-12 ./file1.txt
2024-02-12 ./file2.log

顯示檔案權限、擁有者、群組、大小和名稱

find . -type f -printf "%M %u %g %8s %p\n"
-rw-r--r-- user1 group1 1024 ./file1.txt
-rw-r--r-- user2 group2 2048 ./file2.txt

執行類

-printf

指令 說明 範例 解釋
-exec 對符合條件的檔案執行指令 find /path -type f -name "*.log" -exec rm {} \; 刪除所有 .log 檔案
-exec (多個參數) 傳遞多個參數到指令 find /path -type f -name "*.txt" -exec mv {} /backup/ \; 移動 .txt 檔案到 /backup/
-exec (多檔案批次處理) + 來一次傳遞多個檔案 find /path -type f -name "*.jpg" -exec ls -lh {} + 列出 .jpg 檔案詳細資訊(批次傳遞參數)
-execdir 在檔案所在目錄執行指令 find /path -type f -name "*.bak" -execdir rm {} \; 在檔案所在目錄刪除 .bak 檔案

刪除所有 .log 檔案:

find /var/log -type f -name "*.log" -exec rm {} \;

批次刪除 .tmp 檔案(避免多次執行 rm):

find /tmp -type f -name "*.tmp" -exec rm {} +

找出 .sh 檔案並修改權限:

find /scripts -type f -name "*.sh" -exec chmod +x {} \;

計算 .log 檔案總大小:

find /var/log -type f -name "*.log" -exec du -ch {} + | tail -n 1

-delete

指令 說明 範例 解釋
-delete 刪除符合條件的檔案 find /path -type f -name "*.log" -delete 刪除所有 .log 檔案
-delete (空目錄) 刪除空目錄 find /path -type d -empty -delete 刪除所有空目錄
-delete (限制層級) 限制搜尋深度刪除 find /path -maxdepth 1 -type f -name "*.tmp" -delete 只刪除 /path 下的 .tmp 檔案,不影響子目錄

其他

參數 說明 範例 解釋
-user 搜尋指定使用者擁有的檔案 find /path -user username 找出屬於指定使用者的檔案
-group 搜尋指定群組擁有的檔案 find /path -group groupname 找出屬於指定群組的檔案
-perm 根據檔案權限搜尋檔案 find /path -perm 755 找出擁有 755 權限的檔案
-newer 搜尋修改時間在指定檔案之後的檔案 find /path -newer file1.txt 找出在 file1.txt 之後被修改過的檔案
! -newer 搜尋修改時間在指定檔案之前的檔案 find /path ! -newer file1.txt 找出在 file1.txt 之前被修改過的檔案
-maxdepth 限制搜尋的最大目錄層級 find /path -maxdepth 2 只搜尋最多 2 層目錄深度的檔案
-mindepth 限制搜尋的最小目錄層級 find /path -mindepth 2 只搜尋從第 2 層開始的檔案
-print0 輸出檔案名稱並以 null 字元結尾,用於處理空格 find /path -print0 方便與 xargs -0 搭配使用,避免檔名有空格
-0 接受 null 字元分隔的檔案名稱 find /path -print0 | xargs -0 rm 用於 xargs,確保檔名包含空格的情況下也能正確處理
-iname 不區分大小寫的檔案名稱搜尋 find /path -iname "*.jpg" 搜尋所有 .jpg 檔案,不區分大小寫
-empty 搜尋空的檔案或目錄 find /path -empty 找出所有空的檔案或目錄
-exec 執行指定的命令來處理找到的檔案 find /path -name "*.log" -exec ls -lh {} \; 對每個找到的檔案執行 ls -lh
-exec + 批次處理所有符合條件的檔案,提高效率 find /path -name "*.log" -exec ls -lh {} + 批次執行命令,將多個檔案一次傳遞給命令處理
-prune 排除特定目錄,使其不被搜尋 find /path -path "/path/exclude" -prune -o -name "*.txt" -print 排除 /path/exclude 目錄,只搜尋其他 .txt 檔案
-follow 跟隨符號連結 find /path -follow -name "*.txt" 跟隨符號連結,搜尋 .txt 檔案