asdf คือตัวจัดการเวอร์ชันเครื่องมือพัฒนาซอฟต์แวร์แบบครบวงจรที่ใช้ไฟล์
.tool-versionsเป็นแหล่งกลางในการกำหนดเวอร์ชันต่าง ๆ ต่อโปรเจกต์ แทนที่จะต้องใช้ nvm, pyenv, rbenv แยกกัน asdf รวมทุกอย่างไว้ในเครื่องมือเดียวผ่านระบบ Plugin ที่ขยายได้ไม่จำกัด บทความนี้ครอบคลุมตั้งแต่การติดตั้ง แนวคิด หลักการจัดการ Plugin ไปจนถึงการสร้าง Plugin ของตัวเองและการแก้ไขปัญหาที่พบบ่อย
นักพัฒนาซอฟต์แวร์ในยุคปัจจุบันต้องทำงานกับโปรเจกต์หลายโปรเจกต์พร้อมกัน ซึ่งแต่ละโปรเจกต์มักต้องการเวอร์ชันของเครื่องมือที่แตกต่างกัน ปัญหาที่พบบ่อย ได้แก่:
PATH และ Shell configuration ในรูปแบบที่ขัดแย้งกันตัวอย่างสถานการณ์จริง:
โปรเจกต์ทีม (ก่อนใช้ asdf)
├── project-legacy/ ← Node.js 14, Python 3.8, Ruby 2.7
├── project-current/ ← Node.js 18, Python 3.11, Ruby 3.1
├── project-ai/ ← Python 3.10 (ต้องการ CUDA-specific version)
└── devops-scripts/ ← Terraform 1.3, kubectl 1.25
การสลับโปรเจกต์แต่ละครั้งต้องรัน nvm use 14, pyenv local 3.8 ฯลฯ ด้วยตนเอง ซึ่งนำไปสู่ข้อผิดพลาดที่หลีกเลี่ยงได้ยาก
asdf คือ Extensible Version Manager (ตัวจัดการเวอร์ชันที่ขยายได้) ที่เขียนด้วย Bash โดยมีแนวคิดหลักคือใช้ไฟล์ .tool-versions เดียวในการประกาศเวอร์ชันของเครื่องมือทุกตัวในโปรเจกต์ asdf ทำงานผ่านระบบ Plugin ซึ่งแต่ละ Plugin รับผิดชอบเครื่องมือหนึ่งตัว (เช่น Node.js, Python, Ruby) ทำให้สามารถรองรับเครื่องมือได้ไม่จำกัด
คุณสมบัติหลักของ asdf:
.tool-versions เดียวต่อโปรเจกต์.nvmrc, .python-version, .ruby-version
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#282828', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart LR
subgraph ERA1["🕰️ ยุคก่อน asdf (Before asdf Era) — 2009–2013"]
A1["nvm 0.1\n2010\nNode.js version manager"] --> A2["rbenv 1.0\n2011\nRuby version manager"]
A2 --> A3["pyenv\n2012\nPython version manager"]
end
subgraph ERA2["🚀 กำเนิด asdf (asdf Birth) — 2014–2016"]
B1["HashiCorp releases\nTerraform 0.1\n2014"] --> B2["Metrick Langille\nสร้าง asdf v0.1\n2014"]
B2 --> B3["Plugin system\nเปิดตัวครั้งแรก\n2015"]
B3 --> B4["asdf v0.2\nรองรับ Legacy files\n2016"]
end
subgraph ERA3["🌱 การเติบโต (Growth Era) — 2017–2020"]
C1["Plugin registry\nสาธารณะ\n2017"] --> C2["Fish shell\nsupport\n2018"]
C2 --> C3["asdf v0.7\nปรับปรุง Performance\n2019"]
C3 --> C4["500+ plugins\nในชุมชน\n2020"]
end
subgraph ERA4["⚡ ยุคสมัยใหม่ (Modern Era) — 2021–ปัจจุบัน"]
D1["asdf v0.10\nรองรับ Nushell\n2022"] --> D2["asdf v0.13\nasdf set\nแทน global/local\n2023"]
D2 --> D3["asdf v0.14+\nGo rewrite\nในการพัฒนา\n2024"]
end
ERA1 --> ERA2 --> ERA3 --> ERA4
style ERA1 fill:#3c3836,stroke:#83a598,color:#ebdbb2
style ERA2 fill:#3c3836,stroke:#b8bb26,color:#ebdbb2
style ERA3 fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
style ERA4 fill:#3c3836,stroke:#fb4934,color:#ebdbb2
style A1 fill:#282828,stroke:#83a598,color:#ebdbb2
style A2 fill:#282828,stroke:#83a598,color:#ebdbb2
style A3 fill:#282828,stroke:#83a598,color:#ebdbb2
style B1 fill:#282828,stroke:#b8bb26,color:#ebdbb2
style B2 fill:#282828,stroke:#b8bb26,color:#ebdbb2
style B3 fill:#282828,stroke:#b8bb26,color:#ebdbb2
style B4 fill:#282828,stroke:#b8bb26,color:#ebdbb2
style C1 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style C2 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style C3 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style C4 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style D1 fill:#282828,stroke:#fb4934,color:#ebdbb2
style D2 fill:#282828,stroke:#fb4934,color:#ebdbb2
style D3 fill:#282828,stroke:#fb4934,color:#ebdbb2
จุดเปลี่ยนสำคัญ: ในเวอร์ชัน 0.13 คำสั่ง asdf global และ asdf local ถูกแทนที่ด้วย asdf set ซึ่งมีความยืดหยุ่นกว่า และในเวอร์ชัน 0.14+ โปรเจกต์กำลังเขียนใหม่ด้วย Go เพื่อประสิทธิภาพที่ดีขึ้น
| คุณสมบัติ | asdf | nvm | pyenv | rbenv | mise |
|---|---|---|---|---|---|
| ภาษาที่รองรับ | ทุกภาษา (600+) | Node.js เท่านั้น | Python เท่านั้น | Ruby เท่านั้น | หลายภาษา |
| ไฟล์กำหนดเวอร์ชัน | .tool-versions |
.nvmrc |
.python-version |
.ruby-version |
.mise.toml |
| Legacy file support | ✅ | ✅ | ✅ | ✅ | ✅ |
| Shell รองรับ | Bash/Zsh/Fish/Nu | Bash/Zsh | Bash/Zsh/Fish | Bash/Zsh | Bash/Zsh/Fish/Nu |
| เขียนด้วยภาษา | Bash | Bash | Shell/Python | Shell | Rust |
| ประสิทธิภาพ | ปานกลาง | ดี | ดี | ดี | ดีมาก (Rust) |
| Plugin ecosystem | ใหญ่มาก | ไม่มี | น้อย | น้อย | กำลังเติบโต |
| CI/CD integration | ✅ | ✅ | ✅ | ✅ | ✅ |
| Windows native | ❌ (WSL เท่านั้น) | ❌ | ❌ | ❌ | ✅ |
.tool-versions เดียวประกาศเวอร์ชันของทุกเครื่องมือasdf install, asdf set ฯลฯ)asdf install ครั้งเดียวได้ทุกอย่างPATH เพียงครั้งเดียว ไม่มีการทับซ้อนก่อนติดตั้ง asdf ต้องมีสิ่งต่อไปนี้:
build-essential บน Debian/Ubuntu) สำหรับ Plugin ที่ compile จาก source# ตรวจสอบ prerequisites บน Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y \
curl \
git \
build-essential \
libssl-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev
# ตรวจสอบเวอร์ชัน git
git --version
# ควรได้ผลลัพธ์: git version 2.x.x
วิธีที่ 1: ติดตั้งผ่าน Git (แนะนำ)
# Clone asdf repository ไปยัง ~/.asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
# ตรวจสอบว่าโฟลเดอร์ถูกสร้าง
ls ~/.asdf
# ควรเห็น: asdf.sh bin/ completions/ lib/ shims/ ...
วิธีที่ 2: ติดตั้งผ่าน Package Manager (Pacman บน Arch Linux)
# สำหรับ Arch Linux / Manjaro
yay -S asdf-vm
# หรือใช้ paru
paru -S asdf-vm
วิธีที่ 3: ติดตั้งบน Void Linux (ไม่ใช้ systemd)
# Void Linux ใช้ xbps
sudo xbps-install -S git curl
# จากนั้นติดตั้งผ่าน Git
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
ผ่าน Homebrew (แนะนำสำหรับ macOS):
# ติดตั้งผ่าน Homebrew
brew install asdf
# Homebrew จัดการ PATH ให้อัตโนมัติ
# แต่ต้องตั้งค่า Shell ด้วยตนเองตามข้อ 2.5
ผ่าน Git:
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
# 1. เปิด WSL 2 (Windows Subsystem for Linux)
# ใน PowerShell (Admin): wsl --install
# 2. อัปเดต packages
sudo apt-get update && sudo apt-get upgrade -y
# 3. ติดตั้ง dependencies
sudo apt-get install -y curl git build-essential
# 4. Clone asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
# 5. ตั้งค่า Shell ตามข้อ 2.5
หมายเหตุ: asdf ไม่รองรับ Windows PowerShell หรือ CMD โดยตรง ต้องใช้ผ่าน WSL หรือ Git Bash เท่านั้น
Bash:
# เพิ่มใน ~/.bashrc หรือ ~/.bash_profile
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
echo '. "$HOME/.asdf/completions/asdf.bash"' >> ~/.bashrc
# โหลดการตั้งค่าใหม่
source ~/.bashrc
Zsh:
# เพิ่มใน ~/.zshrc
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.zshrc
# โหลดการตั้งค่าใหม่
source ~/.zshrc
Fish Shell:
# เพิ่มใน ~/.config/fish/config.fish
echo 'source ~/.asdf/asdf.fish' >> ~/.config/fish/config.fish
# ติดตั้ง completions สำหรับ Fish
mkdir -p ~/.config/fish/completions
ln -s ~/.asdf/completions/asdf.fish ~/.config/fish/completions
# โหลดการตั้งค่าใหม่
source ~/.config/fish/config.fish
Nushell:
# เพิ่มใน $nu.config-path (env.nu)
let asdf_path = ($env.HOME | path join ".asdf")
$env.PATH = ($env.PATH | prepend ($asdf_path | path join "shims"))
$env.PATH = ($env.PATH | prepend ($asdf_path | path join "bin"))
# source asdf.nu
source ~/.asdf/asdf.nu
สำหรับผู้ติดตั้งผ่าน Homebrew บน macOS:
# Bash/Zsh ผ่าน Homebrew
echo '. $(brew --prefix asdf)/libexec/asdf.sh' >> ~/.zshrc
# Fish ผ่าน Homebrew
echo 'source (brew --prefix asdf)/libexec/asdf.fish' >> ~/.config/fish/config.fish
# ตรวจสอบเวอร์ชัน asdf
asdf version
# ผลลัพธ์: v0.14.0-xxxx
# ตรวจสอบว่า asdf อยู่ใน PATH
which asdf
# ผลลัพธ์: /home/username/.asdf/bin/asdf
# ดูคำสั่งที่มีทั้งหมด
asdf help
Plugin คือสคริปต์ที่บอก asdf วิธีการติดตั้ง ลบ และสลับเวอร์ชันของเครื่องมือหนึ่งตัว โดยแต่ละ Plugin คือ Git repository ที่มีโครงสร้างตามมาตรฐาน
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
graph TD
USER["👤 ผู้ใช้ (User)"]
ASDF["⚙️ asdf core\n~/.asdf/bin/asdf"]
REGISTRY["📋 Plugin Registry\nGitHub asdf-vm/asdf-plugins"]
subgraph PLUGINS["🧩 Installed Plugins (~/.asdf/plugins/)"]
P1["asdf-nodejs\n(bin/list-all, bin/install...)"]
P2["asdf-python\n(bin/list-all, bin/install...)"]
P3["asdf-ruby\n(bin/list-all, bin/install...)"]
end
subgraph INSTALLS["📦 Installed Versions (~/.asdf/installs/)"]
I1["nodejs/18.20.0/\nnodejs/20.15.0/"]
I2["python/3.11.0/\npython/3.12.0/"]
I3["ruby/3.2.0/"]
end
subgraph SHIMS["🔗 Shims (~/.asdf/shims/)"]
S1["node → shim"]
S2["python → shim"]
S3["ruby → shim"]
S4["npm → shim"]
S5["pip → shim"]
end
USER -->|"asdf plugin add nodejs"| ASDF
ASDF -->|"lookup plugin URL"| REGISTRY
REGISTRY -->|"return git URL"| ASDF
ASDF -->|"git clone"| PLUGINS
ASDF -->|"call bin/install"| INSTALLS
ASDF -->|"create shims"| SHIMS
SHIMS -->|"redirect to correct version"| INSTALLS
style USER fill:#282828,stroke:#b8bb26,color:#ebdbb2
style ASDF fill:#282828,stroke:#83a598,color:#ebdbb2
style REGISTRY fill:#282828,stroke:#d3869b,color:#ebdbb2
style PLUGINS fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
style INSTALLS fill:#3c3836,stroke:#8ec07c,color:#ebdbb2
style SHIMS fill:#3c3836,stroke:#fe8019,color:#ebdbb2
style P1 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style P2 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style P3 fill:#282828,stroke:#fabd2f,color:#ebdbb2
style I1 fill:#282828,stroke:#8ec07c,color:#ebdbb2
style I2 fill:#282828,stroke:#8ec07c,color:#ebdbb2
style I3 fill:#282828,stroke:#8ec07c,color:#ebdbb2
style S1 fill:#282828,stroke:#fe8019,color:#ebdbb2
style S2 fill:#282828,stroke:#fe8019,color:#ebdbb2
style S3 fill:#282828,stroke:#fe8019,color:#ebdbb2
style S4 fill:#282828,stroke:#fe8019,color:#ebdbb2
style S5 fill:#282828,stroke:#fe8019,color:#ebdbb2
ไฟล์ .tool-versions คือไฟล์ plain text ที่ประกาศเวอร์ชันของเครื่องมือในโปรเจกต์นั้น ๆ ไฟล์นี้ควรเพิ่มใน version control (Git) เพื่อให้ทุกคนในทีมใช้เวอร์ชันเดียวกัน
# ตัวอย่างไฟล์ .tool-versions
nodejs 20.15.0
python 3.11.9
ruby 3.2.4
terraform 1.7.0
kubectl 1.29.0
golang 1.22.0
ความสำคัญของไฟล์ .tool-versions:
asdf install ครั้งเดียวได้ทุก dependency
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
graph TB
subgraph PRIORITY["ลำดับความสำคัญ (Priority Order) — สูงสุดไปต่ำสุด"]
S["🔴 SHELL\n$ASDF_NODEJS_VERSION=20.15.0\nสูงสุด — ใช้เฉพาะ Session ปัจจุบัน"]
L["🟡 LOCAL\n~/.../project/.tool-versions\nต่อโปรเจกต์ — commit ลง Git"]
G["🟢 GLOBAL\n~/.tool-versions\nค่าเริ่มต้นทั้งระบบ"]
SYS["⚪ SYSTEM\nVersion ที่ OS ติดตั้งมา\nต่ำสุด — fallback"]
end
S -->|"ถ้าไม่มี Shell override"| L
L -->|"ถ้าไม่มี .tool-versions"| G
G -->|"ถ้าไม่มี Global config"| SYS
style PRIORITY fill:#3c3836,stroke:#83a598,color:#ebdbb2
style S fill:#282828,stroke:#fb4934,color:#ebdbb2
style L fill:#282828,stroke:#fabd2f,color:#ebdbb2
style G fill:#282828,stroke:#b8bb26,color:#ebdbb2
style SYS fill:#282828,stroke:#928374,color:#ebdbb2
| ระดับ | ตำแหน่งไฟล์ | คำสั่ง | ขอบเขต |
|---|---|---|---|
| Shell | Environment variable | asdf shell nodejs 20.15.0 |
เฉพาะ terminal session ปัจจุบัน |
| Local | [project]/.tool-versions |
asdf set nodejs 20.15.0 |
เฉพาะโปรเจกต์นั้น |
| Global | ~/.tool-versions |
asdf set --home nodejs 20.15.0 |
ทั้งระบบ (default) |
| System | ระบบปฏิบัติการ | asdf set nodejs system |
ใช้ version จาก OS |
asdf รองรับไฟล์กำหนดเวอร์ชันของเครื่องมืออื่น ๆ (Legacy version files) เช่น .nvmrc, .python-version, .ruby-version โดยต้องเปิดใช้งานใน ~/.asdfrc
# ~/.asdfrc
legacy_version_file = yes
หลังจากเปิดใช้งาน:
.nvmrc → asdf จะใช้เวอร์ชันนั้นสำหรับ nodejs.python-version → asdf จะใช้เวอร์ชันนั้นสำหรับ python.ruby-version → asdf จะใช้เวอร์ชันนั้นสำหรับ ruby.terraform-version → asdf จะใช้เวอร์ชันนั้นสำหรับ terraformข้อควรทราบ: Legacy file support ขึ้นอยู่กับ Plugin — Plugin ต้องมีสคริปต์
bin/list-legacy-filenamesด้วย
Shim คือ executable script ขนาดเล็กที่อยู่ใน ~/.asdf/shims/ ทำหน้าที่เป็น proxy ระหว่างผู้ใช้กับ binary จริง เมื่อผู้ใช้รันคำสั่งเช่น node, asdf จะ intercept ผ่าน shim และเลือก binary ที่ถูกต้องตามเวอร์ชัน
ขั้นตอนการทำงานของ Shim:
node --versionnode ใน PATH → พบ ~/.asdf/shims/node.tool-versions ในโฟลเดอร์ปัจจุบัน → .tool-versions ในโฟลเดอร์แม่ → ~/.tool-versions~/.asdf/installs/nodejs/[version]/bin/node --version# ดูเนื้อหาของ Shim
cat ~/.asdf/shims/node
# #!/usr/bin/env bash
# # asdf-plugin: nodejs
# exec /home/user/.asdf/bin/asdf exec "nodejs" "node" "$@"
# Shim ถูกสร้างใหม่ได้ด้วย
asdf reshim nodejs
# แสดงรายการ Plugin ทั้งหมดในทะเบียนสาธารณะ
asdf plugin list all
# ค้นหา Plugin เฉพาะ (grep)
asdf plugin list all | grep -i node
# asdf-nodejs https://github.com/asdf-vm/asdf-nodejs.git
# ค้นหาผ่าน Web browser
# https://github.com/asdf-vm/asdf-plugins
# เพิ่ม Plugin จาก Registry สาธารณะ (ระบุชื่ออย่างเดียว)
asdf plugin add nodejs
# เพิ่ม Plugin พร้อมระบุ URL (สำหรับ Plugin นอก registry)
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
# เพิ่ม Plugin หลายตัวพร้อมกัน
asdf plugin add nodejs python ruby golang terraform
Plugin ยอดนิยมที่ควรติดตั้ง:
# ภาษาโปรแกรม
asdf plugin add nodejs
asdf plugin add python
asdf plugin add ruby
asdf plugin add golang
asdf plugin add rust
asdf plugin add java
# DevOps tools
asdf plugin add terraform
asdf plugin add kubectl
asdf plugin add helm
asdf plugin add awscli
# Erlang/Elixir ecosystem
asdf plugin add erlang
asdf plugin add elixir
# อัปเดต Plugin ทีละตัว
asdf plugin update nodejs
# อัปเดต Plugin ทั้งหมดพร้อมกัน
asdf plugin update --all
# ตรวจสอบเวอร์ชัน Plugin (Git commit hash)
asdf plugin list --urls --refs
# ลบ Plugin (และ versions ที่ติดตั้งทั้งหมดจะยังคงอยู่ใน ~/.asdf/installs/)
asdf plugin remove nodejs
# หมายเหตุ: การลบ Plugin ไม่ได้ลบ installed versions
# ต้องลบ versions ก่อนหรือลบโฟลเดอร์ด้วยตนเอง
ls ~/.asdf/installs/nodejs/
rm -rf ~/.asdf/installs/nodejs/ # ลบทั้งหมด (ระวัง!)
# แสดงรายการ Plugin ที่ติดตั้ง
asdf plugin list
# nodejs
# python
# ruby
# terraform
# แสดงพร้อม URL และ Git ref
asdf plugin list --urls
# nodejs https://github.com/asdf-vm/asdf-nodejs.git
asdf plugin list --refs
# nodejs master abc1234
# ใช้ URL ของ Git repository โดยตรง
asdf plugin add my-tool https://github.com/myorg/asdf-my-tool.git
# ใช้ path ท้องถิ่น (สำหรับการพัฒนา Plugin)
asdf plugin add my-tool file:///home/user/dev/asdf-my-tool
# ระบุ branch เฉพาะ (ผ่านการแก้ไข .git/config ใน plugin directory)
# หลังจากเพิ่ม plugin แล้ว
cd ~/.asdf/plugins/my-tool
git checkout feature-branch
# ติดตั้งเวอร์ชันเฉพาะ
asdf install nodejs 20.15.0
# ติดตั้งเวอร์ชัน latest (ถ้า Plugin รองรับ)
asdf install nodejs latest
# ติดตั้ง latest ของ major version
asdf install nodejs latest:18
# ติดตั้งทุกเวอร์ชันที่ระบุใน .tool-versions ในโฟลเดอร์ปัจจุบัน
asdf install
# ตัวอย่าง: ติดตั้ง Java (ต้องระบุ variant)
asdf install java temurin-21.0.3+9
# แสดงเวอร์ชันทั้งหมดที่มี
asdf list all nodejs
# กรองด้วย grep
asdf list all nodejs | grep "^20\."
# 20.0.0
# 20.1.0
# ...
# 20.15.0
# แสดง latest version
asdf latest nodejs
# 22.4.0
# แสดง latest ของ major version
asdf latest nodejs 20
# 20.15.0
# แสดงเวอร์ชันที่ติดตั้งแล้วสำหรับ tool ทั้งหมด
asdf list
# แสดงเฉพาะ tool ที่ระบุ
asdf list nodejs
# 18.20.4
# * 20.15.0 ← * หมายถึงเวอร์ชันที่ใช้งานอยู่ในขณะนี้
# 22.4.0
# แสดงเวอร์ชันที่ใช้งานอยู่ทั้งหมด
asdf current
# nodejs 20.15.0 /home/user/projects/myapp/.tool-versions
# python 3.11.9 /home/user/projects/myapp/.tool-versions
# terraform 1.7.0 /home/user/.tool-versions
คำสั่ง asdf set เป็นคำสั่งหลักสำหรับกำหนดเวอร์ชันใน asdf 0.13+ มีรูปแบบดังนี้:
asdf set [--home] [--parent] <name> <version> [<version>...]
| Flag/Argument | ความหมาย |
|---|---|
| (ไม่มี flag) | เขียนลงไฟล์ .tool-versions ในโฟลเดอร์ปัจจุบัน |
--home |
เขียนลง ~/.tool-versions (global) |
--parent |
เขียนลงไฟล์ .tool-versions ของโฟลเดอร์แม่ที่ใกล้ที่สุด |
<name> |
ชื่อ Tool (เช่น nodejs, python) |
<version> |
เวอร์ชันที่ต้องการ หรือ latest |
# ไปยังโฟลเดอร์โปรเจกต์
cd ~/projects/my-web-app
# กำหนดเวอร์ชัน Node.js สำหรับโปรเจกต์นี้
asdf set nodejs 20.15.0
# ตรวจสอบผล — ไฟล์ .tool-versions ถูกสร้าง/อัปเดต
cat .tool-versions
# nodejs 20.15.0
# กำหนดหลาย tools พร้อมกัน (ต้องรันทีละบรรทัด)
asdf set nodejs 20.15.0
asdf set python 3.11.9
asdf set terraform 1.7.0
# ผลลัพธ์ .tool-versions
cat .tool-versions
# nodejs 20.15.0
# python 3.11.9
# terraform 1.7.0
# กำหนด Node.js เวอร์ชัน Global (ทั้งระบบ)
asdf set --home nodejs 20.15.0
# กำหนด Python เวอร์ชัน Global
asdf set --home python 3.12.0
# ตรวจสอบ ~/.tool-versions
cat ~/.tool-versions
# nodejs 20.15.0
# python 3.12.0
# สมมติโครงสร้าง:
# ~/projects/
# ├── .tool-versions ← ต้องการเขียนที่นี่
# ├── frontend/
# │ └── (อยู่ที่นี่)
# └── backend/
cd ~/projects/frontend
# --parent เขียนลงไฟล์ .tool-versions ของโฟลเดอร์แม่ที่ใกล้ที่สุด
asdf set --parent nodejs 20.15.0
# ผลลัพธ์: ~/projects/.tool-versions ถูกอัปเดต
cat ~/projects/.tool-versions
# nodejs 20.15.0
| คำสั่งเก่า (deprecated) | คำสั่งใหม่ | ความแตกต่าง |
|---|---|---|
asdf global nodejs 18.0.0 |
asdf set --home nodejs 18.0.0 |
เหมือนกัน |
asdf local nodejs 18.0.0 |
asdf set nodejs 18.0.0 |
เหมือนกัน |
| ไม่มี | asdf set --parent nodejs 18.0.0 |
เพิ่มใหม่ใน asdf set |
หมายเหตุ:
asdf globalและasdf localยังใช้งานได้ใน asdf 0.13+ แต่เป็น deprecated aliases — แนะนำให้ใช้asdf setแทน
# กำหนดเวอร์ชันชั่วคราวเฉพาะ terminal นี้
asdf shell nodejs 18.20.4
# ตรวจสอบ
node --version
# v18.20.4
# เปิด terminal ใหม่ → กลับไปใช้เวอร์ชัน local/global
# วิธีทำงานภายใน: ตั้งค่า env variable
echo $ASDF_NODEJS_VERSION
# 18.20.4
# ยกเลิก shell override
unset ASDF_NODEJS_VERSION
# ลบเวอร์ชันเฉพาะ
asdf uninstall nodejs 18.20.4
# ตรวจสอบว่าลบแล้ว
asdf list nodejs
# * 20.15.0
# 22.4.0
# ลบ version ที่ไม่ได้ใช้งานทั้งหมด (ด้วย script)
# asdf ไม่มีคำสั่ง prune ในตัว ต้องทำเอง
for version in $(asdf list nodejs | grep -v '*' | tr -d ' '); do
echo "Removing nodejs $version..."
asdf uninstall nodejs "$version"
done
# ดูเวอร์ชันที่ใช้งานอยู่ทั้งหมด
asdf current
# nodejs 20.15.0 /home/user/project/.tool-versions
# python 3.11.9 /home/user/project/.tool-versions
# terraform 1.7.0 /home/user/.tool-versions
# ดูเฉพาะ tool ที่ระบุ
asdf current nodejs
# nodejs 20.15.0 /home/user/project/.tool-versions
# ดู binary path ที่ใช้งานอยู่จริง
asdf which node
# /home/user/.asdf/installs/nodejs/20.15.0/bin/node
ไฟล์ .tool-versions มีรูปแบบ plain text ง่ายมาก:
# รูปแบบ: <tool-name> <version> [<version2> ...]
# บรรทัดที่เริ่มด้วย # คือ comment
# สามารถระบุหลาย version ต่อ tool (สำหรับ compatibility)
nodejs 20.15.0
python 3.11.9 3.10.14
ruby 3.2.4
terraform 1.7.0
kubectl 1.29.6
helm 3.15.2
golang 1.22.5
กฎของรูปแบบ:
<tool> <version> คั่นด้วยช่องว่าง#)# สร้างไฟล์ด้วย text editor
cd ~/projects/my-project
nano .tool-versions
# หรือสร้างด้วย heredoc
cat > .tool-versions << 'EOF'
nodejs 20.15.0
python 3.11.9
terraform 1.7.0
EOF
# ตรวจสอบไฟล์
cat .tool-versions
# asdf จะอ่านไฟล์นี้อัตโนมัติ
asdf current
# เพิ่ม .tool-versions ใน Git (ควรทำเสมอ)
git add .tool-versions
git commit -m "chore: add .tool-versions for consistent development environment"
# ตัวอย่าง .gitignore — ไม่ควร ignore .tool-versions
# .gitignore ที่ดีสำหรับ Node.js project:
cat >> .gitignore << 'EOF'
node_modules/
dist/
.env
# ไม่ต้อง ignore .tool-versions!
EOF
กระบวนการสำหรับทีม:
.tool-versions และ commitasdf install → ติดตั้งทุกเวอร์ชันที่ระบุasdf ค้นหาไฟล์ .tool-versions จากโฟลเดอร์ปัจจุบันขึ้นไปจนถึง root:
/home/user/
├── .tool-versions ← Global fallback (nodejs 20.x, python 3.12)
└── projects/
├── .tool-versions ← Override (nodejs 18.x)
├── frontend/
│ ├── .tool-versions ← Override (nodejs 20.x)
│ └── src/
│ └── (ไม่มี .tool-versions → สืบทอดจาก frontend/)
└── backend/
└── (ไม่มี .tool-versions → สืบทอดจาก projects/)
# ทดสอบการสืบทอด
cd /home/user/projects/backend
asdf current nodejs
# nodejs 18.20.4 /home/user/projects/.tool-versions
cd /home/user/projects/frontend/src
asdf current nodejs
# nodejs 20.15.0 /home/user/projects/frontend/.tool-versions
# อ่าน .tool-versions และติดตั้งทุก version ที่ยังไม่มี
cd ~/projects/my-project
asdf install
# Installing nodejs 20.15.0...
# Installing python 3.11.9...
# Installing terraform 1.7.0...
# ตรวจสอบหลังติดตั้ง
asdf current
# nodejs 20.15.0 /home/user/projects/my-project/.tool-versions
# python 3.11.9 /home/user/projects/my-project/.tool-versions
# terraform 1.7.0 /home/user/projects/my-project/.tool-versions
# คำสั่ง asdf set = เขียน/แก้ไขไฟล์ .tool-versions โดยอัตโนมัติ
# วิธีที่ 1: ใช้ asdf set
asdf set nodejs 20.15.0
# ผล: เขียน "nodejs 20.15.0" ลงใน .tool-versions
# วิธีที่ 2: แก้ไขไฟล์ตรงๆ
echo "nodejs 20.15.0" >> .tool-versions
# ทั้งสองวิธีให้ผลเหมือนกัน
# แต่ asdf set ดีกว่าเพราะ:
# 1. อัปเดต entry ที่มีอยู่แล้วแทนการเพิ่มซ้ำ
# 2. จัดการ edge cases เช่น trailing whitespace
# 3. สะดวกกว่าในการเขียน script
# ติดตั้ง Plugin
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
# (ต้องการ GPG keys สำหรับ verification)
bash -c '${ASDF_DATA_DIR:=$HOME/.asdf}/plugins/nodejs/bin/import-release-team-keyring'
# ติดตั้ง Node.js
asdf install nodejs 20.15.0
asdf install nodejs lts # ติดตั้ง LTS ล่าสุด
# ตั้งค่า
asdf set --home nodejs 20.15.0
# ทดสอบ
node --version # v20.15.0
npm --version # 10.x.x
# Prerequisites สำหรับ Python (Ubuntu)
sudo apt-get install -y \
libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev \
libncursesw5-dev xz-utils tk-dev \
libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
# ติดตั้ง Plugin
asdf plugin add python https://github.com/danhper/asdf-python.git
# ติดตั้ง Python
asdf install python 3.11.9
asdf install python 3.12.4
# ตั้งค่า global
asdf set --home python 3.12.4
# ทดสอบ
python --version # Python 3.12.4
pip --version # pip 24.x
# ตั้งค่า pip ไม่ให้ require virtual env (optional)
export PIP_REQUIRE_VIRTUALENV=false
# Prerequisites (Ubuntu)
sudo apt-get install -y \
libssl-dev libreadline-dev \
zlib1g-dev libyaml-dev
# ติดตั้ง Plugin
asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git
# ติดตั้ง Ruby
asdf install ruby 3.3.3
# ตั้งค่า
asdf set --home ruby 3.3.3
# ทดสอบ
ruby --version # ruby 3.3.3
gem --version # 3.x.x
# ติดตั้ง Plugin
asdf plugin add golang https://github.com/asdf-community/asdf-golang.git
# ติดตั้ง Go
asdf install golang 1.22.5
# ตั้งค่า GOPATH (เพิ่มใน .bashrc/.zshrc)
export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"
# ตั้งค่า
asdf set --home golang 1.22.5
# ทดสอบ
go version # go version go1.22.5 linux/amd64
# ติดตั้ง Plugin
asdf plugin add java https://github.com/halcyon/asdf-java.git
# ดู distribution ที่มี
asdf list all java | grep temurin | head -20
# ติดตั้ง Adoptium Temurin 21 (LTS)
asdf install java temurin-21.0.3+9
# ตั้งค่า JAVA_HOME (เพิ่มใน .bashrc)
. ~/.asdf/plugins/java/set-java-home.bash # สำหรับ Bash
# . ~/.asdf/plugins/java/set-java-home.zsh # สำหรับ Zsh
# ตั้งค่า
asdf set --home java temurin-21.0.3+9
# ทดสอบ
java --version # openjdk 21.0.3
# ติดตั้ง Plugin
asdf plugin add rust https://github.com/code-lever/asdf-rust.git
# ติดตั้ง Rust stable
asdf install rust stable
asdf install rust 1.79.0
# ตั้งค่า
asdf set --home rust stable
# ทดสอบ
rustc --version # rustc 1.79.0
cargo --version # cargo 1.79.0
# Prerequisites สำหรับ Erlang (Ubuntu)
sudo apt-get install -y \
build-essential autoconf m4 libncurses5-dev \
libwxwidgets-dev libgl1-mesa-dev libglu1-mesa-dev \
libpng-dev libssh-dev unixodbc-dev xsltproc fop \
libxml2-utils libncurses-dev openjdk-11-jdk
# ติดตั้ง Erlang ก่อน (Elixir ต้องการ Erlang)
asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
asdf install erlang 26.2.5
asdf set --home erlang 26.2.5
# ติดตั้ง Elixir
asdf plugin add elixir https://github.com/asdf-vm/asdf-elixir.git
asdf install elixir 1.17.1-otp-26
asdf set --home elixir 1.17.1-otp-26
# ตั้งค่า .tool-versions สำหรับ Elixir project
cat > .tool-versions << 'EOF'
erlang 26.2.5
elixir 1.17.1-otp-26
nodejs 20.15.0
EOF
# ทดสอบ
erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'
# "26"
elixir --version
# Erlang/OTP 26 [erts-14.x]
# Elixir 1.17.1 (compiled with Erlang/OTP 26)
# Terraform
asdf plugin add terraform https://github.com/asdf-community/asdf-hashicorp.git
asdf install terraform 1.9.0
asdf set --home terraform 1.9.0
# kubectl
asdf plugin add kubectl https://github.com/asdf-community/asdf-kubectl.git
asdf install kubectl 1.30.2
asdf set --home kubectl 1.30.2
# Helm
asdf plugin add helm https://github.com/Antiarchitect/asdf-helm.git
asdf install helm 3.15.2
asdf set --home helm 3.15.2
# AWS CLI
asdf plugin add awscli https://github.com/MetricMike/asdf-awscli.git
asdf install awscli 2.17.0
asdf set --home awscli 2.17.0
# ตัวอย่าง .tool-versions สำหรับ DevOps project
cat > .tool-versions << 'EOF'
terraform 1.9.0
kubectl 1.30.2
helm 3.15.2
awscli 2.17.0
EOF
# ติดตั้งทั้งหมดพร้อมกัน
asdf install
direnv เป็นเครื่องมือที่โหลด environment variables จากไฟล์ .envrc อัตโนมัติเมื่อเข้าไดเรกทอรี การใช้ร่วมกับ asdf ช่วยให้ตั้งค่า environment ได้ละเอียดขึ้น
# ติดตั้ง direnv
asdf plugin add direnv https://github.com/asdf-community/asdf-direnv.git
asdf install direnv latest
asdf set --home direnv latest
# ตั้งค่า direnv hook (เพิ่มใน .bashrc)
eval "$(direnv hook bash)"
# ตัวอย่าง .envrc ในโปรเจกต์
cat > .envrc << 'EOF'
# ใช้เวอร์ชันจาก .tool-versions
use asdf
# ตั้งค่า environment variables เพิ่มเติม
export DATABASE_URL="postgres://localhost/myapp_dev"
export NODE_ENV="development"
export RAILS_ENV="development"
EOF
# อนุญาต direnv
direnv allow .
GitHub Actions:
# .github/workflows/ci.yml
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ใช้ .tool-versions เพื่อกำหนดเวอร์ชัน
- name: Install asdf
uses: asdf-vm/actions/setup@v3
- name: Install plugins and versions
uses: asdf-vm/actions/install@v3
# อ่านจาก .tool-versions อัตโนมัติ
- name: Verify versions
run: |
node --version
python --version
- name: Run tests
run: npm test
GitLab CI:
# .gitlab-ci.yml
image: ubuntu:22.04
before_script:
# ติดตั้ง asdf
- apt-get update && apt-get install -y git curl
- git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
- . ~/.asdf/asdf.sh
# ติดตั้ง plugins จาก .tool-versions
- |
while IFS= read -r line; do
tool=$(echo "$line" | awk '{print $1}')
asdf plugin add "$tool" 2>/dev/null || true
done < .tool-versions
- asdf install
test:
script:
- node --version
- npm test
# Dockerfile ที่ใช้ asdf
FROM ubuntu:22.04
# ติดตั้ง dependencies
RUN apt-get update && apt-get install -y \
git curl build-essential \
&& rm -rf /var/lib/apt/lists/*
# ติดตั้ง asdf
RUN git clone https://github.com/asdf-vm/asdf.git /root/.asdf --branch v0.14.0
# ตั้งค่า PATH
ENV PATH="/root/.asdf/shims:/root/.asdf/bin:$PATH"
ENV BASH_ENV="/root/.asdf/asdf.sh"
# copy .tool-versions
COPY .tool-versions /app/.tool-versions
WORKDIR /app
# ติดตั้ง plugins และ versions
RUN bash -c '. /root/.asdf/asdf.sh && \
asdf plugin add nodejs && \
asdf plugin add python && \
asdf install'
# เปิดใช้ asdf ใน shell
SHELL ["/bin/bash", "-c"]
RUN echo '. /root/.asdf/asdf.sh' >> /root/.bashrc
COPY . .
# สร้าง script สำหรับ onboarding
cat > setup-dev-env.sh << 'EOF'
#!/usr/bin/env bash
# setup-dev-env.sh — ตั้งค่า development environment อัตโนมัติ
set -e
echo "🚀 กำลังตั้งค่า development environment..."
# ตรวจสอบว่า asdf ถูกติดตั้งแล้ว
if ! command -v asdf &> /dev/null; then
echo "📦 ติดตั้ง asdf..."
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
source ~/.bashrc
fi
# ติดตั้ง plugins จาก .tool-versions
echo "🔌 ติดตั้ง asdf plugins..."
while IFS= read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
[[ -z "$line" ]] && continue
tool=$(echo "$line" | awk '{print $1}')
if ! asdf plugin list | grep -q "^$tool$"; then
echo " Adding plugin: $tool"
asdf plugin add "$tool" 2>/dev/null || echo " ⚠️ ไม่พบ $tool ใน registry"
fi
done < .tool-versions
# ติดตั้ง versions
echo "📥 ติดตั้ง tool versions..."
asdf install
echo "✅ ตั้งค่าเสร็จสิ้น!"
asdf current
EOF
chmod +x setup-dev-env.sh
VS Code:
// .vscode/settings.json
{
// ชี้ไปที่ binary ที่ asdf จัดการ
"python.defaultInterpreterPath": "${env:HOME}/.asdf/shims/python",
"python.terminal.activateEnvironment": false,
// Node.js path สำหรับ ESLint, Prettier
"eslint.nodePath": "${env:HOME}/.asdf/shims",
// ป้องกัน VS Code override version
"go.goroot": "${env:HOME}/.asdf/installs/golang/1.22.5/go"
}
Neovim (LSP configuration):
-- ~/.config/nvim/lua/lsp.lua
-- ใช้ asdf shims สำหรับ LSP servers
local lspconfig = require('lspconfig')
-- TypeScript/JavaScript LSP
lspconfig.tsserver.setup({
cmd = {
-- ใช้ node จาก asdf
vim.fn.expand("~/.asdf/shims/node"),
vim.fn.expand("~/.asdf/installs/nodejs/20.15.0/lib/node_modules/typescript-language-server/lib/cli.mjs"),
"--stdio"
}
})
-- Python LSP
lspconfig.pyright.setup({
cmd = { vim.fn.expand("~/.asdf/shims/pyright-langserver"), "--stdio" }
})
asdf-my-tool/
├── README.md
├── bin/
│ ├── list-all ← บังคับ: แสดงรายการ versions ที่มี
│ ├── install ← บังคับ: ติดตั้ง version ที่ระบุ
│ ├── list-legacy-filenames ← เสริม: รองรับ legacy files
│ ├── parse-legacy-file ← เสริม: อ่าน legacy file
│ ├── exec-env ← เสริม: ตั้งค่า env ก่อนรัน
│ ├── exec-path ← เสริม: ระบุ path ของ executable
│ ├── uninstall ← เสริม: ลบ version
│ └── latest-stable ← เสริม: บอก version ล่าสุด
└── lib/
└── utils.bash ← helper functions
bin/list-all — แสดงรายการ versions ที่มี:
#!/usr/bin/env bash
# bin/list-all
# แสดงรายการ versions ทั้งหมด คั่นด้วยช่องว่าง
set -euo pipefail
# ดึงรายการ versions จาก GitHub releases
GH_REPO="https://api.github.com/repos/my-org/my-tool/releases"
# ดึงและแสดง tag names (ลบ 'v' prefix)
curl -sL "$GH_REPO" | \
grep '"tag_name":' | \
sed -E 's/.*"([^"]+)".*/\1/' | \
sed 's/^v//' | \
tr '\n' ' '
bin/install — ติดตั้ง version:
#!/usr/bin/env bash
# bin/install
# ตัวแปร environment ที่ asdf ส่งมา:
# ASDF_INSTALL_TYPE — "version" หรือ "ref"
# ASDF_INSTALL_VERSION — version ที่ต้องการติดตั้ง
# ASDF_INSTALL_PATH — path ที่จะติดตั้ง
set -euo pipefail
install_tool() {
local install_type="$ASDF_INSTALL_TYPE"
local version="$ASDF_INSTALL_VERSION"
local install_path="$ASDF_INSTALL_PATH"
# สร้างโฟลเดอร์
mkdir -p "$install_path/bin"
# กำหนด OS และ Architecture
local os arch
os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m)
case "$arch" in
x86_64) arch="amd64" ;;
aarch64|arm64) arch="arm64" ;;
esac
# URL สำหรับดาวน์โหลด
local download_url="https://github.com/my-org/my-tool/releases/download/v${version}/my-tool_${os}_${arch}.tar.gz"
echo "📥 กำลังดาวน์โหลด my-tool v${version}..."
# ดาวน์โหลดและแตกไฟล์
local tmp_dir
tmp_dir=$(mktemp -d)
curl -sL "$download_url" -o "$tmp_dir/my-tool.tar.gz"
tar -xzf "$tmp_dir/my-tool.tar.gz" -C "$tmp_dir"
# คัดลอก binary ไปยัง install path
cp "$tmp_dir/my-tool" "$install_path/bin/my-tool"
chmod +x "$install_path/bin/my-tool"
# ทำความสะอาด
rm -rf "$tmp_dir"
echo "✅ ติดตั้ง my-tool v${version} สำเร็จ"
}
install_tool
bin/list-legacy-filenames:
#!/usr/bin/env bash
# แสดงชื่อ legacy version files ที่รองรับ
# คั่นด้วย space หรือ newline
echo ".my-tool-version"
bin/exec-env:
#!/usr/bin/env bash
# ตั้งค่า environment variables ก่อนรัน executable
# ตัวแปร ASDF_INSTALL_PATH มีค่าแล้วเมื่อถูกเรียก
export MY_TOOL_HOME="$ASDF_INSTALL_PATH"
export PATH="$ASDF_INSTALL_PATH/bin:$PATH"
bin/latest-stable:
#!/usr/bin/env bash
# แสดง version ล่าสุดที่ stable
# รับ argument เป็น version filter (optional)
local filter="${1:-}"
curl -sL "https://api.github.com/repos/my-org/my-tool/releases/latest" | \
grep '"tag_name":' | \
sed -E 's/.*"v([^"]+)".*/\1/'
# ทดสอบ Plugin ในเครื่อง
git clone https://github.com/myuser/asdf-my-tool.git /tmp/asdf-my-tool
# เพิ่ม Plugin จาก local path
asdf plugin add my-tool file:///tmp/asdf-my-tool
# ทดสอบแต่ละฟังก์ชัน
asdf list all my-tool # ทดสอบ bin/list-all
asdf install my-tool 1.0.0 # ทดสอบ bin/install
asdf set my-tool 1.0.0 # ทดสอบการตั้งค่า
my-tool --version # ทดสอบ shim
# ใช้ bats สำหรับ automated testing
# https://github.com/bats-core/bats-core
cat > tests/test_list_all.bats << 'EOF'
#!/usr/bin/env bats
@test "list-all returns versions" {
run bin/list-all
[ "$status" -eq 0 ]
[[ "$output" =~ "1.0.0" ]]
}
EOF
bats tests/
asdf-<tool-name>asdf-plugin และ asdf-<tool-name> ใน GitHub repository# fork และ clone asdf-plugins registry
git clone https://github.com/YOUR-USERNAME/asdf-plugins.git
cd asdf-plugins
# เพิ่ม plugin ในไฟล์ที่เหมาะสม (เรียงตามตัวอักษร)
echo "my-tool = https://github.com/myuser/asdf-my-tool.git" >> plugins/m
# commit และ push
git add plugins/m
git commit -m "Add my-tool plugin"
git push origin main
# เปิด Pull Request บน GitHub
# อัปเดต asdf เป็นเวอร์ชันล่าสุด
asdf update
# หรืออัปเดตผ่าน Git โดยตรง
cd ~/.asdf
git fetch --prune
git checkout "$(git describe --abbrev=0 --tags)"
# ตรวจสอบเวอร์ชันหลังอัปเดต
asdf version
# อัปเดต Plugin ทั้งหมด
asdf plugin update --all
# ตรวจสอบว่ามี version ใหม่หลังอัปเดต plugin
asdf list all nodejs | tail -5 # ดู versions ล่าสุด
# Script อัปเดต asdf และ Plugin ทั้งหมด
cat > update-asdf.sh << 'EOF'
#!/usr/bin/env bash
echo "🔄 อัปเดต asdf..."
asdf update
echo "🔌 อัปเดต plugins ทั้งหมด..."
asdf plugin update --all
echo "✅ อัปเดตเสร็จสิ้น"
asdf version
asdf plugin list
EOF
chmod +x update-asdf.sh
# สำรองการตั้งค่า asdf
backup_asdf() {
local backup_dir="$HOME/asdf-backup-$(date +%Y%m%d)"
mkdir -p "$backup_dir"
# สำรอง global .tool-versions
cp ~/.tool-versions "$backup_dir/tool-versions.bak"
# สำรอง .asdfrc
cp ~/.asdfrc "$backup_dir/asdfrc.bak" 2>/dev/null || true
# บันทึกรายการ plugins
asdf plugin list --urls > "$backup_dir/plugins.txt"
echo "✅ สำรองข้อมูลไปยัง $backup_dir"
}
# กู้คืนการตั้งค่า
restore_asdf() {
local backup_dir="$1"
# ติดตั้ง plugins จาก backup
while IFS=' ' read -r name url; do
asdf plugin add "$name" "$url" 2>/dev/null || true
done < "$backup_dir/plugins.txt"
# กู้คืน .tool-versions
cp "$backup_dir/tool-versions.bak" ~/.tool-versions
# ติดตั้ง versions
asdf install
echo "✅ กู้คืนสำเร็จ"
}
# บนเครื่องเก่า: export การตั้งค่า
export_asdf_config() {
echo "# asdf global versions"
cat ~/.tool-versions
echo ""
echo "# asdf plugins"
asdf plugin list --urls
}
export_asdf_config > ~/asdf-config-export.txt
# บนเครื่องใหม่: import การตั้งค่า
import_asdf_config() {
local config_file="$1"
# ติดตั้ง asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
. ~/.asdf/asdf.sh
# อ่านและติดตั้ง plugins
while IFS= read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
[[ -z "$line" ]] && continue
name=$(echo "$line" | awk '{print $1}')
url=$(echo "$line" | awk '{print $2}')
if [[ -n "$url" ]]; then
asdf plugin add "$name" "$url"
fi
done < "$config_file"
# ติดตั้ง versions
asdf install
}
อาการ: command not found: node แม้ติดตั้งแล้ว
# ตรวจสอบ PATH
echo $PATH
# ควรมี ~/.asdf/shims และ ~/.asdf/bin
# แก้ไข: เพิ่มใน shell config
export PATH="$HOME/.asdf/shims:$HOME/.asdf/bin:$PATH"
source ~/.bashrc
# ตรวจสอบว่า shim มีอยู่
ls ~/.asdf/shims/node
# ถ้าไม่มี → สร้าง shims ใหม่
asdf reshim nodejs
# ตรวจสอบว่า asdf รู้จัก tool
asdf current nodejs
# ตรวจสอบว่าไฟล์ .tool-versions มีอยู่
cat .tool-versions
# ตรวจสอบว่า version ถูกติดตั้งแล้ว
asdf list nodejs
# ถ้าไม่มีในรายการ → ติดตั้งก่อน
asdf install nodejs 20.15.0
# ตรวจสอบ version ที่ใช้งานอยู่จริง
asdf current nodejs
# ตรวจสอบว่า shell override ไม่ขัดขวาง
echo $ASDF_NODEJS_VERSION # ถ้ามีค่า → ลบออก
unset ASDF_NODEJS_VERSION
# ตรวจสอบ binary ที่ใช้งาน
which node
asdf which node
# ปัญหา: Homebrew node ถูกใช้แทน asdf node
# ตรวจสอบ PATH order
echo $PATH
# ~/.asdf/shims ต้องมาก่อน /usr/local/bin (homebrew)
# แก้ไข: จัดลำดับ PATH ในไฟล์ shell config
# เพิ่มที่ด้านบนของ ~/.bashrc หรือ ~/.zshrc:
# export PATH="$HOME/.asdf/shims:$HOME/.asdf/bin:$PATH"
# ตรวจสอบว่าใช้ node ตัวไหน
which node
# ควรได้: /home/user/.asdf/shims/node
# ถ้า homebrew node มาก่อน ให้ unlink
brew unlink node
# ตัวอย่าง: Python build failed
# ดู error message
asdf install python 3.11.9
# ERROR: The Python ssl extension was not compiled...
# แก้ไขบน Ubuntu/Debian
sudo apt-get install -y libssl-dev
# แก้ไขบน macOS
brew install openssl
export LDFLAGS="-L$(brew --prefix openssl)/lib"
export CPPFLAGS="-I$(brew --prefix openssl)/include"
# ลองใหม่
asdf install python 3.11.9
# ดูรายการ dependencies ที่ต้องการ
# (อ่านจาก README ของ Plugin)
asdf plugin info python
# เมื่อ shim ไม่ทำงานหลังติดตั้ง binary ใหม่
# เช่น หลัง npm install -g some-cli
# rebuild shims สำหรับ tool เฉพาะ
asdf reshim nodejs
# rebuild shims ทั้งหมด
asdf reshim
# ตรวจสอบว่า shim ถูกสร้างแล้ว
ls ~/.asdf/shims/ | grep "some-cli"
# ตรวจสอบเนื้อหาของ shim
cat ~/.asdf/shims/some-cli
Fish Shell:
# ปัญหา: asdf ไม่ทำงานใน Fish
# แก้ไข: ตรวจสอบ config.fish
cat ~/.config/fish/config.fish
# ควรมี:
# source ~/.asdf/asdf.fish
# ถ้าไม่มี ให้เพิ่ม
echo 'source ~/.asdf/asdf.fish' >> ~/.config/fish/config.fish
# Reload
source ~/.config/fish/config.fish
# ตรวจสอบ completions
ls ~/.config/fish/completions/ | grep asdf
Zsh:
# ปัญหา: asdf ไม่ทำงานกับ Oh My Zsh
# แก้ไข: ใน .zshrc ต้องโหลด asdf หลัง Oh My Zsh
# .zshrc ที่ถูกต้อง:
# export ZSH="$HOME/.oh-my-zsh"
# source $ZSH/oh-my-zsh.sh
# . "$HOME/.asdf/asdf.sh" ← ต้องอยู่หลัง Oh My Zsh
# ตรวจสอบลำดับความสำคัญ
asdf current nodejs
# nodejs 18.20.4 $ASDF_NODEJS_VERSION ← Shell override กำลัง override อยู่!
# แก้ไข: ลบ Shell override ก่อน
unset ASDF_NODEJS_VERSION
# ตรวจสอบว่าไฟล์ .tool-versions ใดถูกใช้
asdf current nodejs
# nodejs 20.15.0 /home/user/project/.tool-versions ← ถูกต้อง
# ลำดับความสำคัญที่ต้องจำ:
# 1. $ASDF_<TOOL>_VERSION (สูงสุด)
# 2. .tool-versions ในโฟลเดอร์ปัจจุบัน
# 3. .tool-versions ในโฟลเดอร์แม่ (ขึ้นไปเรื่อยๆ)
# 4. ~/.tool-versions (global)
# 5. system (ต่ำสุด)
# เพิ่ม aliases ใน ~/.bashrc หรือ ~/.zshrc
# ดู versions ทั้งหมดที่ใช้งาน
alias av='asdf current'
# ติดตั้ง tool ด้วยเวอร์ชันล่าสุด และตั้งค่า global
asdf-install-latest() {
local tool="$1"
local version
version=$(asdf latest "$tool")
echo "ติดตั้ง $tool $version..."
asdf install "$tool" "$version"
asdf set --home "$tool" "$version"
echo "✅ $tool $version ติดตั้งและตั้งค่าเป็น global แล้ว"
}
# ดู path ของ executable ที่ใช้งานอยู่
alias awhich='asdf which'
# อัปเดต asdf และ plugins ทั้งหมด
alias asdf-update-all='asdf update && asdf plugin update --all'
# Fish shell version (สำหรับ Fish ใช้ function แทน alias)
# functions/asdf-install-latest.fish
function asdf-install-latest
set tool $argv[1]
set version (asdf latest $tool)
echo "ติดตั้ง $tool $version..."
asdf install $tool $version
asdf set --home $tool $version
end
# ASDF_DATA_DIR — เปลี่ยนโฟลเดอร์เก็บข้อมูล (default: ~/.asdf)
export ASDF_DATA_DIR="/opt/asdf-data"
# ASDF_CONFIG_FILE — เปลี่ยน config file (default: ~/.asdfrc)
export ASDF_CONFIG_FILE="$HOME/.config/asdf/asdfrc"
# ASDF_DEFAULT_TOOL_VERSIONS_FILENAME — เปลี่ยนชื่อไฟล์ version
# (default: .tool-versions)
export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=".versions"
# ASDF_<TOOL>_VERSION — Shell-level override สำหรับ tool เฉพาะ
export ASDF_NODEJS_VERSION=18.20.4
export ASDF_PYTHON_VERSION=3.10.14
# ตรวจสอบ
asdf current
# nodejs 18.20.4 $ASDF_NODEJS_VERSION
# python 3.10.14 $ASDF_PYTHON_VERSION
# ตัวอย่าง: Full-stack project ที่ต้องการ Node.js + Python + Ruby + Terraform
cd ~/projects/fullstack-app
# ตั้งค่าทุก runtime พร้อมกัน
asdf set nodejs 20.15.0
asdf set python 3.11.9
asdf set ruby 3.2.4
asdf set terraform 1.7.0
# ไฟล์ .tool-versions
cat .tool-versions
# nodejs 20.15.0
# python 3.11.9
# ruby 3.2.4
# terraform 1.7.0
# ติดตั้งทั้งหมดพร้อมกัน (เหมาะสำหรับ onboarding)
asdf install
# ตรวจสอบ
asdf current
# nodejs 20.15.0 /home/user/projects/fullstack-app/.tool-versions
# python 3.11.9 /home/user/projects/fullstack-app/.tool-versions
# ruby 3.2.4 /home/user/projects/fullstack-app/.tool-versions
# terraform 1.7.0 /home/user/projects/fullstack-app/.tool-versions
#!/usr/bin/env bash
# script สำหรับ audit เวอร์ชันที่ติดตั้งและหาเวอร์ชันใหม่
check_updates() {
echo "🔍 ตรวจสอบ updates สำหรับ global tools..."
echo "================================================"
while IFS=' ' read -r tool current_version; do
[[ "$tool" =~ ^#.*$ ]] && continue
[[ -z "$tool" ]] && continue
latest=$(asdf latest "$tool" 2>/dev/null || echo "unknown")
if [ "$current_version" = "$latest" ]; then
echo "✅ $tool: $current_version (up to date)"
else
echo "⬆️ $tool: $current_version → $latest (update available)"
fi
done < ~/.tool-versions
}
check_updates
# โครงสร้าง dotfiles repository ที่แนะนำ
# ~/dotfiles/
# ├── .tool-versions ← global versions
# ├── .asdfrc ← asdf configuration
# ├── install.sh ← setup script
# └── shells/
# ├── .bashrc
# ├── .zshrc
# └── config.fish
# install.sh
#!/usr/bin/env bash
DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# ติดตั้ง asdf
if [ ! -d "$HOME/.asdf" ]; then
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
fi
# symlink .tool-versions และ .asdfrc
ln -sf "$DOTFILES_DIR/.tool-versions" "$HOME/.tool-versions"
ln -sf "$DOTFILES_DIR/.asdfrc" "$HOME/.asdfrc"
# โหลด asdf
. ~/.asdf/asdf.sh
# ติดตั้ง plugins จาก .tool-versions
while IFS=' ' read -r tool _version; do
[[ "$tool" =~ ^#.*$ ]] && continue
[[ -z "$tool" ]] && continue
asdf plugin add "$tool" 2>/dev/null || true
done < "$HOME/.tool-versions"
# ติดตั้ง versions
asdf install
echo "✅ Dotfiles setup complete!"
# ตัวอย่าง .asdfrc
cat > "$DOTFILES_DIR/.asdfrc" << 'EOF'
# ~/.asdfrc
legacy_version_file = yes
always_keep_download = no
plugin_repository_last_check_duration = 60
EOF
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
mindmap
root((asdf))
จุดแข็ง
เครื่องมือเดียว
600+ plugins
รองรับทุกภาษา
.tool-versions
Single config
ใช้ได้กับทีม
Commit ลง Git
ขยายได้
สร้าง Plugin เอง
Custom repos
การใช้งาน
Local Development
ต่างเวอร์ชันต่อโปรเจกต์
Environment isolation
CI/CD
GitHub Actions
GitLab CI
DevOps
Terraform
kubectl
helm
Shell รองรับ
Bash
Zsh
Fish
Nushell
จุดแข็งหลัก:
.tool-versions เป็น single source of truth.nvmrc, .python-version และไฟล์เก่าอื่น ๆ| กรณี | ควรใช้ asdf | ทางเลือกอื่น |
|---|---|---|
| ทำงานกับหลายภาษาในโปรเจกต์เดียว | ✅ เหมาะมาก | — |
| ทีมขนาดใหญ่ต้องการ environment เดียวกัน | ✅ เหมาะมาก | — |
| DevOps tools (Terraform, kubectl) | ✅ เหมาะมาก | tfenv, mise |
| Elixir/Erlang ecosystem | ✅ เหมาะมาก | kiex, kerl |
| ต้องการประสิทธิภาพสูงสุด | ⚠️ ปานกลาง | mise (Rust-based) |
| Windows ไม่ใช้ WSL | ❌ ไม่รองรับ | scoop, mise |
| ต้องการ UI/GUI | ❌ CLI only | Volta |
| จัดการเฉพาะ Node.js | อาจเกิน | nvm, volta |
การพัฒนาที่กำลังดำเนินอยู่ในปี 2024–2025:
.tool-versions เช่นกัน# .tool-versions — Full-Stack Web Application
# อัปเดตล่าสุด: 2024-07
# Frontend Runtime
nodejs 20.15.0
# Backend Runtime
python 3.11.9
# Database CLI
postgresql 16.3
# Infrastructure
terraform 1.9.0
kubectl 1.30.2
helm 3.15.2
# Code Quality
golang 1.22.5
# ~/.asdfrc — asdf configuration
legacy_version_file = yes
always_keep_download = no
plugin_repository_last_check_duration = 60
#!/usr/bin/env bash
# onboarding.sh — ใช้สำหรับตั้งค่า environment ครั้งแรก
set -euo pipefail
REQUIRED_TOOLS=(nodejs python terraform kubectl)
echo "================================================"
echo " 🚀 Developer Environment Setup"
echo "================================================"
# ตรวจสอบ asdf
if ! command -v asdf &>/dev/null; then
echo "❌ ไม่พบ asdf — กรุณาติดตั้งก่อน"
echo " git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0"
exit 1
fi
echo "✅ asdf $(asdf version) พบแล้ว"
# ติดตั้ง plugins
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! asdf plugin list | grep -q "^$tool$"; then
echo "📦 เพิ่ม plugin: $tool"
asdf plugin add "$tool"
else
echo "✅ plugin $tool มีอยู่แล้ว"
fi
done
# ติดตั้ง versions จาก .tool-versions
echo "📥 ติดตั้ง tool versions..."
asdf install
# แสดงผล
echo ""
echo "================================================"
echo " ✅ ตั้งค่าเสร็จสิ้น!"
echo "================================================"
asdf current