
บทนี้มุ่งปูพื้นฐานการใช้งาน บรรทัดคำสั่ง (Command Line Interface, CLI) บนระบบปฏิบัติการ Linux อย่างเป็นระบบ ตั้งแต่แนวคิดของ Shell, การเคลื่อนที่ในระบบไฟล์, การจัดการไฟล์และโพรเซส ไปจนถึงการประมวลผลข้อความด้วย Pipeline เพื่อให้ผู้เรียนสามารถทำงานบนเซิร์ฟเวอร์ที่ไม่มี GUI ได้อย่างมั่นใจและมีประสิทธิภาพ
Shell คือโปรแกรมตัวแปลคำสั่ง (Command Interpreter) ที่ทำหน้าที่รับคำสั่งจากผู้ใช้ แล้วแปลและส่งต่อให้ Kernel ประมวลผล ส่วน Terminal คือหน้าต่างหรืออุปกรณ์ที่ใช้ป้อนคำสั่งและแสดงผล การเข้าใจความแตกต่างและความสัมพันธ์ของสิ่งเหล่านี้เป็นรากฐานสำคัญก่อนจะลงมือใช้งานคำสั่งใด ๆ
สี่คำนี้มักถูกใช้สลับกันในภาษาพูด แต่แท้จริงหมายถึงสิ่งที่แตกต่างกัน:
tty (เช่น /dev/pts/0 หรือ /dev/tty1)ลำดับชั้นการทำงาน:
flowchart LR
U[User / ผู้ใช้] -->|keystroke| TE[Terminal Emulator
เช่น Alacritty, Kitty]
TE -->|pty| TTY[TTY Device
/dev/pts/0]
TTY -->|stdin| SH[Shell
bash / zsh / fish]
SH -->|fork exec| K[Kernel
Linux Kernel]
K -->|stdout| TTY
TTY -->|pixel| TE
TE --> U
style U fill:#458588,stroke:#83a598,color:#fbf1c7
style TE fill:#689d6a,stroke:#8ec07c,color:#fbf1c7
style TTY fill:#d79921,stroke:#fabd2f,color:#282828
style SH fill:#b16286,stroke:#d3869b,color:#fbf1c7
style K fill:#cc241d,stroke:#fb4934,color:#fbf1c7
Shell แต่ละชนิดมีปรัชญาและความสามารถต่างกัน ผู้ใช้ Linux ควรรู้จักทางเลือกเพื่อเลือกใช้ให้เหมาะสม:
| Shell | ปีที่ออก | จุดเด่น | จุดด้อย |
|---|---|---|---|
| sh (Bourne Shell) | 1977 | ต้นแบบ POSIX Shell, เล็ก, พกพาได้ | ฟีเจอร์น้อยมาก |
| bash | 1989 | มาตรฐานของ Linux ส่วนใหญ่, เข้ากันได้กับ sh | Scripting ช้ากว่าบางตัว |
| zsh | 1990 | Auto-completion ทรงพลัง, Plugin (Oh My Zsh, Prezto) | กำหนดค่าซับซ้อน |
| fish | 2005 | User-friendly, Syntax highlight ในตัว, Auto-suggestion | ไม่เข้ากับ POSIX 100% |
| dash | 2002 | เล็กและเร็ว, ใช้รัน /bin/sh บน Debian/Ubuntu |
ไม่มี interactive features |
| ksh (Korn Shell) | 1983 | ต้นแบบของ bash หลายฟีเจอร์, นิยมบน AIX/Solaris | ใน Linux ไม่ค่อยใช้ |
ตรวจสอบ Shell ที่ใช้อยู่และรายการ Shell ที่ระบบอนุญาต:
# ดู Shell ปัจจุบันของผู้ใช้
echo $SHELL # แสดงค่า environment variable
echo $0 # แสดงชื่อของ shell ที่รันอยู่จริง
# ดูรายการ shell ที่ระบบอนุญาตให้ใช้เป็น login shell
cat /etc/shells
# เปลี่ยน default shell ของผู้ใช้ปัจจุบันเป็น zsh
chsh -s /usr/bin/zsh # ต้องใส่รหัสผ่าน, effect เมื่อ login ใหม่
# ตัวอย่างผลลัพธ์จาก cat /etc/shells:
# /bin/sh
# /bin/bash
# /usr/bin/zsh
# /usr/bin/fish
Prompt คือข้อความที่ Shell แสดงเพื่อรอรับคำสั่ง ค่านี้ควบคุมผ่านตัวแปร PS1 (Primary Prompt) และ PS2 (Secondary Prompt สำหรับคำสั่งหลายบรรทัด)
ตัวอย่างการปรับแต่ง Prompt ใน bash:
# ดูค่า PS1 ปัจจุบัน
echo "$PS1"
# เปลี่ยน PS1 ให้แสดง user@host:path$ แบบมีสี
# \u = username, \h = hostname, \w = current working directory, \$ = # หรือ $
# \[\e[32m\] = เริ่มสีเขียว, \[\e[0m\] = คืนสีเดิม
export PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\$ '
# PS2 ใช้เมื่อคำสั่งยังไม่จบ (เช่น เปิด quote ค้าง)
export PS2='→ '
# ทดสอบ PS2 โดยพิมพ์ quote ค้าง:
echo "hello
# จะเห็นสัญลักษณ์ → รอให้พิมพ์ต่อ
world"
หากต้องการให้ค่าคงอยู่ถาวร ให้ใส่บรรทัด export PS1='...' ลงในไฟล์ ~/.bashrc (สำหรับ bash) หรือ ~/.zshrc (สำหรับ zsh)
Shell บันทึกคำสั่งทั้งหมดที่พิมพ์ไว้ในไฟล์ ~/.bash_history (bash) หรือ ~/.zsh_history (zsh) เพื่อให้เรียกใช้ซ้ำได้
# ดูประวัติคำสั่งทั้งหมด (มีเลขลำดับกำกับ)
history
# ดู 10 คำสั่งล่าสุด
history 10
# รันคำสั่งล่าสุดซ้ำ
!!
# รันคำสั่งลำดับที่ 125 จากประวัติ
!125
# รันคำสั่งล่าสุดที่ขึ้นต้นด้วย "git"
!git
# รันคำสั่งล่าสุดที่มีคำว่า "docker" อยู่ตรงไหนก็ได้
!?docker
# แทนที่ข้อความในคำสั่งก่อนหน้า: ถ้าเพิ่งพิมพ์ "ls /etc" แล้วพิมพ์:
^etc^home # จะรัน "ls /home" ทันที
# ค้นหาย้อนหลังแบบ Incremental Search
# กด Ctrl+R แล้วพิมพ์คำบางส่วน เช่น "dock" → จะโผล่คำสั่ง docker ที่เคยใช้
# กด Ctrl+R ซ้ำ เพื่อหาอันที่เก่ากว่า
# กด Enter เพื่อรัน หรือ Esc/ลูกศรเพื่อแก้ไขก่อนรัน
# ล้างประวัติทั้งหมด (ใช้เมื่อเผลอพิมพ์รหัสผ่านลงไป)
history -c && history -w
# ป้องกันไม่ให้คำสั่งที่ขึ้นต้นด้วยช่องว่างถูกบันทึก (ใช้ใน ~/.bashrc)
export HISTCONTROL=ignorespace:ignoredups
export HISTSIZE=10000
export HISTFILESIZE=20000
การกด Tab ให้ Shell เดาและเติมคำให้อัตโนมัติ เป็นฟีเจอร์ที่ประหยัดเวลาที่สุดของ Command Line
ตัวอย่าง:
# พิมพ์แค่ "cd /etc/net" แล้วกด Tab → จะกลายเป็น "cd /etc/network/" (ถ้ามี)
cd /etc/net<TAB>
# พิมพ์ "sudo apt install fire" แล้วกด Tab 2 ครั้ง
# จะแสดง: firefox, firefox-esr, firejail, firewalld
# bash-completion ช่วยให้เติมได้ลึกขึ้น เช่น
git che<TAB> # → git checkout
git checkout <TAB><TAB> # → แสดง branch ทั้งหมดในโปรเจกต์
systemctl status ng<TAB> # → nginx.service
การติดตั้ง bash-completion (บน Ubuntu/Debian):
sudo apt install bash-completion
# เพิ่มใน ~/.bashrc (ถ้ายังไม่มี)
# [ -f /etc/bash_completion ] && . /etc/bash_completion
คีย์ลัดของ Shell (โดยเฉพาะ Readline ที่ bash ใช้) ช่วยให้การพิมพ์คำสั่งเร็วขึ้นมาก:
| Shortcut | หน้าที่ |
|---|---|
| Ctrl+C | ส่ง SIGINT ยกเลิกคำสั่งที่กำลังรัน |
| Ctrl+Z | ส่ง SIGTSTP หยุด (suspend) คำสั่งไว้ชั่วคราว |
| Ctrl+D | ส่ง EOF ปิด stdin / logout จาก shell |
| Ctrl+L | ล้างหน้าจอ (เท่ากับคำสั่ง clear) |
| Ctrl+A | เลื่อน cursor ไปหัวบรรทัด |
| Ctrl+E | เลื่อน cursor ไปท้ายบรรทัด |
| Ctrl+U | ลบข้อความจาก cursor ย้อนไปหัวบรรทัด |
| Ctrl+K | ลบข้อความจาก cursor ไปจนท้ายบรรทัด |
| Ctrl+W | ลบคำที่อยู่ก่อน cursor |
| Ctrl+Y | วางข้อความที่ลบล่าสุด (Yank) |
| Ctrl+R | ค้นหาประวัติคำสั่งย้อนหลัง |
| Alt+B / Alt+F | ย้าย cursor ทีละคำ (ย้อน/ไปข้างหน้า) |
| Alt+. | แทรกอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า |
ระบบไฟล์ของ Linux เป็นโครงสร้างต้นไม้ (Tree) ที่มีรากเดียวคือ / ทุกอุปกรณ์และทุกพาร์ทิชันจะถูก "mount" เข้ามาเป็นสาขาของต้นไม้นี้ การเคลื่อนที่ให้คล่องเป็นทักษะพื้นฐานที่ต้องทำให้เป็นอัตโนมัติ
# แสดงตำแหน่งปัจจุบัน (Print Working Directory)
pwd
# ตัวอย่างผลลัพธ์: /home/moo/projects
# เข้าไปในไดเรกทอรี
cd /var/log
# กลับไปที่ home ของผู้ใช้ (สามเท่ากัน)
cd
cd ~
cd $HOME
# กลับไปที่ไดเรกทอรี "ก่อนหน้า" ที่เพิ่งอยู่ (เหมือนปุ่ม Back)
cd -
# ขึ้นหนึ่งชั้น / สองชั้น
cd ..
cd ../..
# เข้า home ของผู้ใช้อื่น
cd ~moo # เท่ากับ /home/moo
cd ~root # เท่ากับ /root
# ตัวอย่างการสลับไปมาระหว่าง 2 โฟลเดอร์
cd /etc/nginx
cd /var/log/nginx
cd - # กลับ /etc/nginx
cd - # กลับ /var/log/nginx
คำสั่ง ls มี option มากมาย แต่ที่ใช้บ่อยคือ:
ls # แสดงรายชื่อพื้นฐาน
ls -l # แสดงแบบ long listing (สิทธิ์, เจ้าของ, ขนาด, วันที่)
ls -a # แสดงไฟล์ที่ขึ้นต้นด้วย . ด้วย (hidden file)
ls -h # แสดงขนาดในหน่วย human-readable (K, M, G)
ls -R # แสดงแบบ recursive (เข้าลึกทุกโฟลเดอร์)
ls -t # เรียงตามเวลา modify (ล่าสุดก่อน)
ls -S # เรียงตามขนาด (ใหญ่ก่อน)
ls -r # กลับลำดับการเรียง (reverse)
# รวม option ยอดนิยม
ls -lah # รายละเอียดเต็ม + hidden + human-readable size
ls -lhtr # เรียงจากเก่าไปใหม่ (ล่าสุดอยู่ล่างสุด - เห็นง่ายบน terminal)
ls -lhS /var/log # ดูไฟล์ log เรียงตามขนาด
# ใช้ alias ทำให้พิมพ์สั้น (ใส่ใน ~/.bashrc)
alias ll='ls -lah'
alias la='ls -A'
alias l='ls -CF'
ตัวอย่างผลลัพธ์ ls -lah และความหมาย:
drwxr-xr-x 3 moo moo 4.0K Oct 15 14:32 projects/
-rw-r--r-- 1 moo moo 1.2K Oct 14 09:10 notes.md
-rwxr-xr-x 1 root root 15K Sep 1 2024 backup.sh
แต่ละคอลัมน์:
คำสั่ง tree แสดงโครงสร้างไดเรกทอรีแบบต้นไม้ที่อ่านง่ายมาก ต้องติดตั้งเพิ่ม:
# ติดตั้ง
sudo apt install tree # Debian/Ubuntu
sudo pacman -S tree # Arch
sudo dnf install tree # Fedora/RHEL
# แสดงโครงสร้างทั้งหมดของโฟลเดอร์ปัจจุบัน
tree
# จำกัดความลึก 2 ชั้น
tree -L 2
# แสดงเฉพาะไดเรกทอรี (ไม่แสดงไฟล์)
tree -d
# แสดง hidden file ด้วย
tree -a
# รวมออปชันที่ใช้บ่อยสุด: ลึก 3 ชั้น + ขนาด human-readable
tree -L 3 -h /etc/nginx
# ตัวอย่าง output:
# .
# ├── app.py
# ├── requirements.txt
# └── tests
# ├── test_api.py
# └── test_db.py
/ เสมอ เช่น /home/moo/file.txt ใช้ได้จากทุกที่./file.txt, ../docs/readme.mdสัญลักษณ์สำคัญ:
. หมายถึงไดเรกทอรีปัจจุบัน.. หมายถึงไดเรกทอรีแม่ (ขึ้นหนึ่งชั้น)~ หมายถึง home directory ของผู้ใช้ปัจจุบัน~user หมายถึง home directory ของผู้ใช้ชื่อ user- (ในคำสั่ง cd) หมายถึงไดเรกทอรีก่อนหน้า# ถ้าอยู่ที่ /home/moo/projects/ai-course
pwd # → /home/moo/projects/ai-course
cat ./lecture01.md # = /home/moo/projects/ai-course/lecture01.md
cat ../ml-course/syllabus.md # = /home/moo/projects/ml-course/syllabus.md
cat ~/notes.md # = /home/moo/notes.md
cat /etc/hostname # absolute, ใช้ได้จากทุกที่
Globbing คือการให้ Shell ขยาย (expand) สัญลักษณ์พิเศษให้เป็นรายชื่อไฟล์จริงก่อนส่งให้คำสั่ง
| Pattern | ความหมาย | ตัวอย่าง |
|---|---|---|
* |
ตัวอักษรใด ๆ กี่ตัวก็ได้ (รวมว่าง) | *.txt → ไฟล์ .txt ทั้งหมด |
? |
ตัวอักษรใด ๆ หนึ่งตัว | file?.log → file1.log, fileA.log |
[abc] |
ตัวใดตัวหนึ่งใน set | [aeiou]*.md → ไฟล์ .md ที่ขึ้นต้นด้วยสระ |
[a-z] |
ช่วงตัวอักษร | img[0-9].png |
[!abc] |
ไม่ใช่ตัวใน set (negate) | [!._]* → ไม่ขึ้นต้นด้วย . หรือ _ |
{a,b,c} |
Brace Expansion | file.{jpg,png,gif} |
# ลบไฟล์ .log ทั้งหมด
rm *.log
# คัดลอกไฟล์ที่ขึ้นต้นด้วย "report" ตามด้วยเลข 3 หลัก
cp report???.pdf /backup/
# ย้ายไฟล์ภาพทุกประเภทไปโฟลเดอร์ images
mv *.{jpg,jpeg,png,gif,webp} ./images/
# เปิดใช้ globstar เพื่อให้ ** หมายถึง recursive (bash 4+)
shopt -s globstar
ls **/*.py # ไฟล์ .py ทุกไฟล์ในทุกชั้นย่อย
Brace Expansion ไม่ใช่ glob แท้ (ไม่ต้องมีไฟล์จริงอยู่) แต่เป็นการสร้างสตริงหลายชุดพร้อมกัน:
# สร้างโฟลเดอร์หลายอันพร้อมกัน
mkdir -p project/{src,tests,docs,config}
# ได้: project/src, project/tests, project/docs, project/config
# สร้างโครงสร้างซ้อนกัน
mkdir -p course/{ai,ml,netsec}/{lectures,labs,quizzes}
# ได้ 9 โฟลเดอร์ย่อย
# ใช้ช่วงตัวเลข
echo {1..5} # → 1 2 3 4 5
echo {01..10} # → 01 02 03 04 05 06 07 08 09 10 (zero-padded)
echo {a..e} # → a b c d e
echo {10..1..2} # → 10 8 6 4 2 (step -2)
# สร้างไฟล์เปล่า 100 ไฟล์
touch log_{001..100}.txt
# ใช้คู่กับคำสั่งจริง
cp config.yml{,.bak} # สำเนาเป็น config.yml.bak (trick ยอดฮิต)
mv document.{txt,md} # เปลี่ยนชื่อนามสกุล
# สร้างไฟล์เปล่า หรือปรับ timestamp ของไฟล์ที่มีอยู่แล้ว
touch newfile.txt
touch -t 202501011200 file.txt # ตั้ง timestamp เอง (YYYYMMDDhhmm)
touch -r ref.txt target.txt # ให้ timestamp เท่ากับ ref.txt
# สร้างไดเรกทอรี
mkdir logs
# -p (parents) สร้างโฟลเดอร์พ่อแม่ให้ด้วยถ้ายังไม่มี (ไม่ error หากมีอยู่แล้ว)
mkdir -p /var/www/app/public/assets/images
# รวมหลายโฟลเดอร์พร้อม brace expansion
mkdir -p lab-{01..10}/{code,data,report}
# ลบไดเรกทอรี (ต้องว่างเท่านั้น)
rmdir empty_folder
rmdir -p a/b/c # ลบ c, b, a ถ้าทั้งหมดว่าง
# ---------- cp (copy) ----------
cp source.txt dest.txt # คัดลอกไฟล์
cp file.txt /tmp/ # คัดลอกไปโฟลเดอร์
cp -r src/ backup/ # -r = recursive (สำหรับไดเรกทอรี)
cp -i file.txt dest.txt # -i = interactive ถามก่อนเขียนทับ
cp -p file.txt dest.txt # -p = preserve permissions/timestamps
cp -v *.md docs/ # -v = verbose แสดงว่ากำลังทำอะไร
cp -rpv src/ /backup/$(date +%Y-%m-%d)/ # backup แบบครบทุก option
# ---------- mv (move / rename) ----------
mv old.txt new.txt # เปลี่ยนชื่อ
mv file.txt ../ # ย้ายขึ้นไปชั้นบน
mv -n source.txt dest.txt # -n = no-clobber ไม่เขียนทับ
mv *.log archive/ # ย้ายหลายไฟล์
# ---------- rm (remove) ----------
rm file.txt # ลบไฟล์
rm -r folder/ # -r = recursive ลบโฟลเดอร์และเนื้อใน
rm -i *.bak # -i = ถามก่อนลบทุกไฟล์
rm -f file.txt # -f = force ไม่ถาม ไม่ error ถ้าไม่มีไฟล์
rm -rf node_modules/ # ลบทั้งต้น (ใช้ด้วยความระวังสูงสุด!)
# CAUTION: rm -rf / หรือ rm -rf $UNSET_VAR/* อาจลบทั้งระบบ!
# ป้องกันด้วย alias:
alias rm='rm -i'
# หรือใช้ trash-cli แทน:
sudo apt install trash-cli
trash-put file.txt # ลบลงถังขยะ กู้คืนได้
trash-list
trash-restore
# Hard Link: ชี้ไปที่ inode เดียวกัน ลบไฟล์ต้นฉบับข้อมูลยังอยู่ตราบใดที่ยังมี link
ln original.txt hardlink.txt
# Symbolic Link (Symlink): เป็น "ทางลัด" ชี้ไปที่ path ลบต้นฉบับ link ก็พัง
ln -s /var/log/nginx/access.log nginx-log # -s = symbolic
# ตรวจสอบ link
ls -l nginx-log
# lrwxrwxrwx 1 moo moo 23 Oct 15 nginx-log -> /var/log/nginx/access.log
# อ่านเป้าหมายของ symlink
readlink nginx-log
readlink -f nginx-log # ตามไปจนถึงไฟล์จริง
# ลบ symlink (ไม่ใช่ไฟล์ต้นทาง!)
rm nginx-log # หรือ unlink nginx-log
ความแตกต่าง:
flowchart LR
subgraph HL[Hard Link]
HA[file.txt] --> I1[inode #1234
ข้อมูลจริง]
HB[backup.txt] --> I1
end
subgraph SL[Symbolic Link]
SA[link.txt] -->|path string| SB[original.txt]
SB --> I2[inode #5678
ข้อมูลจริง]
end
HL ~~~ SL
style HA fill:#98971a,stroke:#b8bb26,color:#282828
style HB fill:#98971a,stroke:#b8bb26,color:#282828
style I1 fill:#d79921,stroke:#fabd2f,color:#282828
style SA fill:#458588,stroke:#83a598,color:#fbf1c7
style SB fill:#b16286,stroke:#d3869b,color:#fbf1c7
style I2 fill:#d79921,stroke:#fabd2f,color:#282828
# stat แสดงข้อมูล metadata ละเอียดของไฟล์
stat /etc/passwd
# แสดง inode, blocks, IO block, สิทธิ์, access/modify/change time, birth time
# file ตรวจสอบชนิดไฟล์จริง (ไม่ใช่จากนามสกุล)
file script.sh # → Bourne-Again shell script, ASCII text executable
file image.jpg # → JPEG image data, JFIF standard 1.01
file /usr/bin/ls # → ELF 64-bit LSB executable, x86-64
# basename และ dirname ใช้ใน script บ่อยมาก
FILE="/home/moo/docs/report.pdf"
basename "$FILE" # → report.pdf
basename "$FILE" .pdf # → report (ตัดนามสกุล)
dirname "$FILE" # → /home/moo/docs
# ใช้ใน for loop
for f in /var/log/*.log; do
name=$(basename "$f" .log)
echo "Processing $name"
done
ไฟล์หรือโฟลเดอร์ที่ชื่อขึ้นต้นด้วย . จะไม่แสดงใน ls ปกติ (ต้องใช้ ls -a) ใช้เก็บไฟล์ค่าปรับแต่ง (dotfiles) เช่น .bashrc, .gitconfig, .ssh/, .config/
# ดูเฉพาะ hidden file
ls -d .* # หลีก ., .. ด้วย:
ls -A # -A คล้าย -a แต่ไม่แสดง . และ ..
# Dotfiles ที่สำคัญใน ~/
# .bashrc / .bash_profile → bash configuration
# .zshrc → zsh configuration
# .profile → login shell env
# .gitconfig → git user settings
# .ssh/ → ssh keys & config
# .config/ → XDG-standard config directory
# .cache/ → cached data (เคลียร์ได้)
# .local/share/ → application data
# cat = concatenate แสดงเนื้อไฟล์ (หรือรวมหลายไฟล์)
cat file.txt
cat file1.txt file2.txt > combined.txt # รวมสองไฟล์
# -n แสดงเลขบรรทัด, -b แสดงเฉพาะบรรทัดที่ไม่ว่าง
cat -n script.sh
cat -b notes.md
# tac = cat กลับด้าน แสดงจากบรรทัดสุดท้าย
tac /var/log/syslog | head # ดู log ล่าสุดก่อน
# nl เพิ่มเลขบรรทัดแบบยืดหยุ่น
nl -ba poem.txt # นับทุกบรรทัด
nl -bt report.md # นับเฉพาะบรรทัดที่ไม่ว่าง (default)
ข้อควรระวัง: cat ไฟล์ binary อาจทำให้ terminal พัง แก้ด้วย reset หรือ stty sane
less คือ pager ที่ทรงพลัง สามารถเลื่อนขึ้นลงได้อิสระ (more ทำได้แค่เลื่อนลง)
less /var/log/syslog
# คีย์ที่ใช้ในหน้าต่าง less:
# SPACE / f → หน้าถัดไป
# b → หน้าก่อนหน้า
# j / ↓ → บรรทัดลง
# k / ↑ → บรรทัดขึ้น
# g → ไปต้นไฟล์
# G → ไปท้ายไฟล์
# /pattern → ค้นหาไปข้างหน้า
# ?pattern → ค้นหาย้อนหลัง
# n / N → ผลถัดไป / ย้อนกลับ
# &pattern → กรองเฉพาะบรรทัดที่ match
# :n / :p → ไฟล์ถัดไป / ก่อนหน้า (ถ้าเปิดหลายไฟล์)
# F → follow mode (เหมือน tail -f)
# q → ออก
# option ยอดนิยม
less -N file.txt # แสดงเลขบรรทัด
less -R colored.log # ตีความ ANSI color
less +F /var/log/auth.log # เปิดใน follow mode ทันที
head file.txt # แสดง 10 บรรทัดแรก (default)
head -n 20 file.txt # 20 บรรทัดแรก
head -c 100 file.txt # 100 byte แรก
tail file.txt # 10 บรรทัดสุดท้าย
tail -n 50 /var/log/syslog # 50 บรรทัดสุดท้าย
tail -n +100 file.txt # ตั้งแต่บรรทัดที่ 100 ถึงท้าย
# -f (follow) ดู log แบบ real-time - คำสั่งที่ sysadmin ใช้บ่อยที่สุด
tail -f /var/log/nginx/access.log
# -F เหมือน -f แต่ติดตามแม้ไฟล์ถูก rotate
tail -F /var/log/syslog
# follow หลายไฟล์พร้อมกัน
tail -f /var/log/nginx/{access,error}.log
# multitail (ติดตั้งเพิ่ม) สำหรับดู log หลายไฟล์แบบ split screen
sudo apt install multitail
multitail /var/log/syslog /var/log/auth.log
wc file.txt
# 125 1823 10456 file.txt
# ↑ ↑ ↑
# lines words bytes
wc -l file.txt # นับเฉพาะจำนวนบรรทัด
wc -w file.txt # นับคำ
wc -c file.txt # นับ byte
wc -m file.txt # นับ character (สำคัญกับไฟล์ UTF-8 ที่มีภาษาไทย)
# ตัวอย่างการใช้จริง
ls /etc | wc -l # นับจำนวนไฟล์ใน /etc
cat *.py | wc -l # นับบรรทัดโค้ด Python ทั้งหมด
grep -c "ERROR" /var/log/syslog # นับจำนวน ERROR (grep -c ทำงานคล้าย wc -l)
# diff เปรียบเทียบสองไฟล์ แสดงบรรทัดที่แตกต่าง
diff file1.txt file2.txt
diff -u file1.txt file2.txt # unified format (ใช้กับ patch)
diff -r dir1/ dir2/ # recursive เปรียบสองโฟลเดอร์
# สร้าง patch และนำไปใช้
diff -u old.c new.c > fix.patch
patch old.c < fix.patch
# cmp เปรียบเทียบ byte-by-byte (ใช้กับไฟล์ binary)
cmp file1.bin file2.bin
cmp -l file1 file2 # แสดงทุก byte ที่ต่าง
# ตรวจสอบความสมบูรณ์ของไฟล์ด้วย hash
md5sum linux.iso
# a1b2c3... linux.iso
sha256sum linux.iso # ปลอดภัยกว่า md5 ใช้บ่อยกว่าในปัจจุบัน
sha512sum linux.iso
# ตรวจสอบไฟล์ ISO กับ checksum ที่ผู้แจกจ่ายให้มา
sha256sum -c SHA256SUMS # -c = check
# linux.iso: OK
การประมวลผลข้อความเป็นจุดแข็งที่สุดของ Linux Shell เพราะตามปรัชญา Unix "Everything is a file" และส่วนใหญ่เป็นไฟล์ข้อความ การใช้เครื่องมือเหล่านี้ร่วมกันผ่าน pipe สามารถทำงานที่ซับซ้อนได้ในบรรทัดเดียว
grep (Global Regular Expression Print) ค้นหาบรรทัดที่ตรงกับ pattern
grep "ERROR" /var/log/syslog # ค้นหาคำว่า ERROR
grep -i "error" file.log # -i ไม่สนตัวพิมพ์เล็ก-ใหญ่
grep -v "DEBUG" app.log # -v เลือกบรรทัดที่ "ไม่" match
grep -n "TODO" *.py # -n แสดงเลขบรรทัด
grep -c "404" access.log # -c นับจำนวนบรรทัดที่ match
grep -r "password" /etc/ # -r recursive ค้นหาในทุกไฟล์
grep -l "api_key" -r src/ # -l แสดงเฉพาะชื่อไฟล์
grep -A 3 "Exception" app.log # -A แสดง 3 บรรทัดหลัง match
grep -B 2 "Exception" app.log # -B แสดง 2 บรรทัดก่อน match
grep -C 5 "ERROR" app.log # -C แสดง 5 บรรทัดรอบ ๆ (context)
grep -E "error|warning|fatal" app.log # -E = extended regex (เหมือน egrep)
grep -F "a.b.c" file.txt # -F = fixed string (ไม่ตีความ regex, เหมือน fgrep)
# ripgrep (rg) - รุ่นทันสมัย เร็วกว่า grep มาก เข้าใจ .gitignore
sudo apt install ripgrep
rg "TODO" . # ค้นทุกไฟล์ในโฟลเดอร์ปัจจุบัน
rg -i "warning" --type py # เฉพาะไฟล์ Python
rg "func \w+" -o # -o แสดงเฉพาะส่วนที่ match
Regular Expression เป็นภาษาสำหรับอธิบาย pattern ข้อความ Linux รองรับ 3 รสชาติ:
grep, sed (default) - ต้อง escape \(, \|, \+grep -E, sed -E, awk - ไม่ต้อง escapegrep -P, rg - ทรงพลังสุด (lookahead, backreference)Metacharacters หลัก:
| Symbol | ความหมาย | ตัวอย่าง |
|---|---|---|
. |
ตัวอักษรใด ๆ 1 ตัว | c.t → cat, cut, c7t |
* |
ซ้ำ 0 ครั้งขึ้นไป | ab* → a, ab, abb |
+ |
ซ้ำ 1 ครั้งขึ้นไป (ERE) | ab+ → ab, abb |
? |
มีหรือไม่มีก็ได้ (0 หรือ 1) | colou?r |
^ |
ต้นบรรทัด | ^Error |
$ |
ท้ายบรรทัด | done$ |
[abc] |
a, b หรือ c | [aeiou] |
[^abc] |
ไม่ใช่ a, b, c | [^0-9] |
\d |
ตัวเลข (PCRE) | \d{3}-\d{4} |
\w |
ตัวอักษรคำ | \w+@\w+ |
\s |
whitespace | |
| ` | ` | หรือ |
() |
group | (ab)+ |
{n,m} |
ซ้ำ n ถึง m ครั้ง | a{2,4} |
ตัวอย่าง:
# ค้นหา IP Address
grep -E '[0-9]{1,3}(\.[0-9]{1,3}){3}' access.log
# ค้นหา email (อย่างง่าย)
grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' contacts.txt
# ค้นหา HTTP response code 4xx หรือ 5xx ใน access log
grep -E ' (4|5)[0-9]{2} ' access.log
# ค้นหาบรรทัดที่ขึ้นต้นด้วย # (comment)
grep '^#' config.txt
# ค้นหาบรรทัดว่าง
grep -n '^$' file.txt
sed เป็น editor ที่ทำงานกับ stream ข้อความ ทีละบรรทัด เหมาะกับ find-replace อัตโนมัติ
# แทนที่ครั้งแรกในแต่ละบรรทัด (print ออกเฉย ๆ)
sed 's/foo/bar/' file.txt
# แทนที่ทั้งหมด (g = global)
sed 's/foo/bar/g' file.txt
# แก้ไขไฟล์จริง (-i = in-place) ระวัง! ไม่มี undo
sed -i 's/foo/bar/g' file.txt
# สำรองไฟล์เดิมไว้ก่อนแก้
sed -i.bak 's/foo/bar/g' file.txt # สร้าง file.txt.bak
# ใช้ตัวแยก (delimiter) อื่นเมื่อ pattern มี /
sed 's|/old/path|/new/path|g' config.txt
# ลบบรรทัด
sed '3d' file.txt # ลบบรรทัดที่ 3
sed '/^#/d' file.txt # ลบบรรทัดที่ขึ้นต้นด้วย #
sed '/^$/d' file.txt # ลบบรรทัดว่าง
sed '5,10d' file.txt # ลบบรรทัดที่ 5-10
# แทรกข้อความ
sed '1i\
# This is a header' file.txt # i = insert before line 1
sed '$a\
# End of file' file.txt # a = append after last line
# แสดงเฉพาะบางบรรทัด (-n ปิด auto-print, p = print)
sed -n '10,20p' file.txt # แสดงบรรทัด 10-20
sed -n '/Error/p' log.txt # แสดงเฉพาะบรรทัดที่มี Error
# หลาย expression ใน sed เดียว
sed -e 's/foo/bar/g' -e 's/hello/hi/g' file.txt
# ตัวอย่างจริง: แปลงนามสกุลไฟล์ .jpg เป็น .png ในชื่อหลาย ๆ ไฟล์
ls *.jpg | sed 's/\.jpg$/.png/'
awk เป็นภาษาสคริปต์ขนาดเล็กสำหรับประมวลผลข้อความแบบคอลัมน์ ทรงพลังมาก
แนวคิดหลัก: แบ่งบรรทัดเป็น field คั่นด้วย whitespace (default) เรียกเป็น $1, $2, ... และ $0 คือทั้งบรรทัด
ตัวแปรในตัว (built-in):
NR = หมายเลขบรรทัดที่กำลังประมวลผล (Record Number)NF = จำนวน field ในบรรทัดปัจจุบัน (Number of Fields)FS = Field Separator (input, default = whitespace)OFS = Output Field Separator# พิมพ์ field ที่ 1 และ 3 ของแต่ละบรรทัด
awk '{print $1, $3}' data.txt
# พิมพ์เฉพาะบรรทัดที่มีมากกว่า 3 field
awk 'NF > 3' data.txt
# เปลี่ยน field separator เป็น : (เช่น /etc/passwd)
awk -F: '{print $1, $7}' /etc/passwd # username กับ shell
# คำนวณผลรวม คอลัมน์ที่ 2
awk '{sum += $2} END {print "Total:", sum}' sales.txt
# เฉลี่ย
awk '{sum += $2; count++} END {print "Avg:", sum/count}' data.txt
# เงื่อนไข (pattern-action)
awk '$3 > 100 {print $1, $3}' data.txt # แสดงเฉพาะบรรทัดที่ field 3 > 100
# BEGIN และ END block
awk 'BEGIN {print "Report"; print "------"}
{print NR, $0}
END {print "Total lines:", NR}' file.txt
# ตัวอย่างจริง: สรุป access.log โดยนับ IP ที่เข้ามา
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
ตัวอย่าง awk script ที่ซับซ้อนขึ้น - สรุปยอดขายรายสินค้า:
# สมมุติไฟล์ sales.csv
# apple,5,25
# banana,3,15
# apple,2,10
# cherry,4,40
awk -F, '
{
total[$1] += $3 # บันทึกยอดแต่ละสินค้าใน associative array
qty[$1] += $2
}
END {
printf "%-10s %-8s %s\n", "Product", "Qty", "Total"
for (p in total)
printf "%-10s %-8d %d\n", p, qty[p], total[p]
}' sales.csv
# cut ตัดเฉพาะบางคอลัมน์
cut -d: -f1 /etc/passwd # -d = delimiter, -f = field
cut -d: -f1,6,7 /etc/passwd # หลาย field
cut -c1-10 file.txt # ตัดตามตำแหน่ง character
cut -c5- file.txt # ตั้งแต่ column 5 ถึงท้าย
# paste รวมไฟล์แบบเรียงข้าง (ทำเป็นคอลัมน์)
paste names.txt ages.txt # เอาสองไฟล์มาต่อข้าง
paste -d, names.txt ages.txt # คั่นด้วย comma
paste -s names.txt # -s = รวมเป็นบรรทัดเดียว
# join รวมสองไฟล์ตาม key (เหมือน SQL JOIN)
# users.txt: orders.txt:
# 1 Alice 1 Book
# 2 Bob 2 Pen
# 3 Carol 3 Paper
join users.txt orders.txt
# 1 Alice Book
# 2 Bob Pen
# 3 Carol Paper
sort file.txt # เรียงตามตัวอักษร
sort -n numbers.txt # -n = numeric (เรียงเป็นตัวเลข)
sort -r file.txt # -r = reverse (มาก→น้อย)
sort -u file.txt # -u = unique (ลบที่ซ้ำ)
sort -k 2 data.txt # -k = field ที่ใช้เรียง (field 2)
sort -k 2,2n -k 1,1 data.txt # เรียง field 2 เป็นเลข, แล้วด้วย field 1
sort -t: -k3 -n /etc/passwd # -t = delimiter, เรียงตาม UID
sort -h sizes.txt # -h = human-readable (1K, 2M, 3G)
sort -R file.txt # -R = random shuffle
# uniq ลบบรรทัด "ซ้ำที่ติดกัน" เท่านั้น (ต้อง sort ก่อน!)
sort file.txt | uniq # ลบที่ซ้ำ
sort file.txt | uniq -c # -c = นับจำนวนครั้งที่เจอ
sort file.txt | uniq -d # -d = แสดงเฉพาะที่ซ้ำ
sort file.txt | uniq -u # -u = แสดงเฉพาะที่ไม่ซ้ำ
# สูตรยอดนิยม: หา top-10 IP ที่เข้าเว็บบ่อยสุด
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# tr แปลง (translate) ตัวอักษร - ใช้ผ่าน pipe เท่านั้น
echo "Hello World" | tr 'a-z' 'A-Z' # → HELLO WORLD
echo "Hello World" | tr -d ' ' # -d = delete → HelloWorld
cat file.txt | tr -s ' ' # -s = squeeze ลดช่องว่างซ้ำ
echo "2024-10-15" | tr '-' '/' # → 2024/10/15
tr -cd 'a-zA-Z0-9\n' < input.txt # -c = complement (เก็บเฉพาะ)
# rev กลับตัวอักษรในบรรทัด
echo "ABCDE" | rev # → EDCBA
# fold ตัดบรรทัดยาวตามความกว้าง
fold -w 80 long_line.txt # ตัดที่คอลัมน์ 80
fold -s -w 80 text.txt # -s ไม่แยกคำกลางคำ
# column จัดเรียงเป็นคอลัมน์สวยงาม
cat /etc/passwd | column -t -s: # -t = table, -s = delimiter
ps aux | head | column -t
tee ส่ง input ไปทั้งหน้าจอ (stdout) และไฟล์พร้อมกัน - มีประโยชน์เมื่อต้องทั้งดูผลลัพธ์และบันทึก
# เขียนไฟล์ด้วย sudo (ไม่ได้ผลกับ > เพราะ redirect ทำโดย user shell ปกติ)
echo "127.0.0.1 myserver" | sudo tee -a /etc/hosts
# -a = append (ไม่เขียนทับ)
dmesg | tee -a boot.log
# ส่งไปหลายไฟล์พร้อมกัน
ls -l | tee file1.txt file2.txt file3.txt
# เข้าคู่กับ pipeline
cat data.txt | sort | tee sorted.txt | uniq -c
# sorted.txt ได้ข้อมูลเรียง, หน้าจอเห็นผลรวมจำนวนซ้ำ
แนวคิดนี้คือหัวใจของปรัชญา Unix: "โปรแกรมเล็ก ๆ ที่ทำงานอย่างเดียวให้ดี แล้วต่อกันเป็นสายท่อ"
|) และ Named Pipe (mkfifo)Pipe (|) ส่ง stdout ของคำสั่งซ้ายไปเป็น stdin ของคำสั่งขวา
# ใครคือผู้ใช้ที่ login อยู่มากสุด
who | awk '{print $1}' | sort | uniq -c | sort -rn
# จำนวนไฟล์ .py ในโปรเจกต์
find . -name '*.py' | wc -l
# 5 โปรเซสที่กิน RAM มากสุด
ps aux --sort=-%mem | head -6
Named Pipe (FIFO) เป็นไฟล์ในระบบไฟล์จริง ให้โปรเซสสองตัวสื่อสารกันแบบ stream ได้
# สร้าง named pipe
mkfifo mypipe
# Terminal 1: เขียนข้อมูลเข้า pipe (จะค้างรอจนมีคนอ่าน)
echo "Hello via FIFO" > mypipe
# Terminal 2: อ่านข้อมูลจาก pipe
cat mypipe
# → Hello via FIFO
# ใช้ประโยชน์: streaming log ข้ามโปรเซส
mkfifo /tmp/logpipe
(tail -f /var/log/syslog > /tmp/logpipe) &
grep ERROR /tmp/logpipe
<, >, >>, 2>, &>, 2>&1ทุกโปรเซสใน Unix มี file descriptor 3 ตัวหลัก:
flowchart LR
IN[stdin fd=0] -->|<| P((Process))
P -->|>| OUT[stdout fd=1]
P -->|2>| ERR[stderr fd=2]
OUT --> F1[file หรือ terminal]
ERR --> F2[error log หรือ terminal]
style IN fill:#98971a,stroke:#b8bb26,color:#282828
style P fill:#d79921,stroke:#fabd2f,color:#282828
style OUT fill:#458588,stroke:#83a598,color:#fbf1c7
style ERR fill:#cc241d,stroke:#fb4934,color:#fbf1c7
# > เขียนทับ (overwrite) ระวังข้อมูลเดิมหาย!
echo "Hello" > greeting.txt
# >> ต่อท้าย (append)
echo "World" >> greeting.txt
# < อ่าน input จากไฟล์
wc -l < access.log
# 2> เฉพาะ stderr
grep pattern /etc/ 2> errors.txt
# 1> หรือ > คือ stdout (1 ย่อได้)
command 1> output.log
# &> หรือ >& ทั้ง stdout และ stderr (bash shorthand)
command &> all.log
# 2>&1 รวม stderr เข้า stdout (อ่านว่า "2 follow 1")
command > all.log 2>&1
# ทิ้ง stderr (เงียบ error)
command 2> /dev/null
# ทิ้งทั้งหมด
command &> /dev/null
# เปิดไฟล์เป็น input และ output ของ file descriptor 3
exec 3<> somefile.txt
echo "write" >&3
exec 3<&- # ปิด fd 3
ลำดับการเขียน redirect สำคัญมาก:
command > file 2>&1 # ถูก: stdout → file, stderr → stdout (ซึ่งไป file)
command 2>&1 > file # ผิด: stderr → terminal, stdout → file
อุปกรณ์พิเศษใน Linux:
/dev/null = "ถังขยะ" เขียนอะไรลงไปก็หาย อ่านได้ EOF/dev/zero = แหล่ง byte 0 ไม่จำกัด ใช้สร้างไฟล์ pre-allocated/dev/urandom = แหล่งข้อมูลสุ่ม (non-blocking) ใช้สร้างรหัสผ่าน/คีย์/dev/random = เหมือน urandom แต่ block เมื่อ entropy หมด# ทิ้ง output
command > /dev/null 2>&1
# สร้างไฟล์ขนาด 100MB ทดสอบ
dd if=/dev/zero of=testfile bs=1M count=100
# สร้างรหัสผ่านสุ่ม 32 ตัวอักษร base64
head -c 24 /dev/urandom | base64
# สร้าง UUID
cat /proc/sys/kernel/random/uuid
xargs แปลง stdin ให้เป็น argument ของคำสั่ง (ไม่ใช่ stdin) มีประโยชน์มากเมื่อคำสั่งไม่อ่าน stdin เอง
# ส่งรายชื่อไฟล์จาก find ไปให้ rm
find . -name "*.tmp" | xargs rm
# -I {} ระบุตำแหน่งของ placeholder (จำเป็นเมื่อไม่ได้อยู่ท้าย)
ls *.jpg | xargs -I {} cp {} /backup/{}.bak
# -n จำกัดจำนวน argument ต่อการเรียก 1 ครั้ง
echo "1 2 3 4 5 6" | xargs -n 2 echo
# 1 2
# 3 4
# 5 6
# -P รันแบบขนาน (parallel) - เร่งความเร็วมาก
cat urls.txt | xargs -n 1 -P 10 wget -q
# -0 ใช้คู่กับ find -print0 เพื่อรองรับชื่อไฟล์ที่มีช่องว่าง
find . -name "*.log" -print0 | xargs -0 rm
# ดูคำสั่งที่จะถูกรันก่อน (-t = trace)
ls | xargs -t -I {} echo "Processing {}"
$(...) และ backtickแทนที่ output ของคำสั่งให้กลายเป็นส่วนหนึ่งของคำสั่งอื่น
# แบบ modern (แนะนำ - nestable)
echo "Today is $(date +%Y-%m-%d)"
echo "You have $(ls | wc -l) files"
# สร้างโฟลเดอร์ชื่อมี timestamp
mkdir "backup_$(date +%Y%m%d_%H%M%S)"
# ซ้อน substitution ได้
echo "Latest file: $(ls -t | head -1)"
# แบบเก่า (backtick) - ไม่แนะนำ ซ้อนยาก
echo "Today is `date`"
# เก็บลงตัวแปร
current_user=$(whoami)
uptime_days=$(uptime | awk '{print $3}')
<(...), >(...)แปลง output ของคำสั่งให้กลายเป็น ไฟล์ชั่วคราว (จริง ๆ เป็น /dev/fd/...) เพื่อให้คำสั่งที่ต้องการ "ไฟล์" เป็น argument ใช้ได้
# เปรียบเทียบ output ของสองคำสั่งโดยไม่ต้องสร้างไฟล์จริง
diff <(ls /dir1) <(ls /dir2)
# เปรียบเทียบไฟล์ที่ sort แล้ว โดยไม่แก้ไขต้นฉบับ
diff <(sort file1.txt) <(sort file2.txt)
# ดู config ที่ตัด comment ออกแล้วเทียบกัน
diff <(grep -v '^#' /etc/nginx/nginx.conf) <(grep -v '^#' /etc/nginx/nginx.conf.bak)
# >() ส่งไปเป็น "ไฟล์ output"
cat file.txt | tee >(grep ERROR > errors.log) >(grep WARN > warns.log) > /dev/null
# แยก stream เดียวเข้าหลาย grep พร้อมกัน
find เป็นคำสั่งค้นหาไฟล์ที่ทรงพลังที่สุด สามารถค้นโดยเงื่อนไขใด ๆ แล้วทำ action ต่อได้
# โครงสร้าง: find [path] [tests] [actions]
# ค้นหาตามชื่อ (case-sensitive)
find /home -name "*.pdf"
# ไม่สนตัวพิมพ์เล็ก-ใหญ่
find . -iname "*.jpg"
# ตามประเภท: f=file, d=directory, l=symlink, b=block, c=char, s=socket, p=fifo
find /etc -type f -name "*.conf"
find . -type d -name "node_modules"
# ตามขนาด: k=KB, M=MB, G=GB (+มากกว่า, -น้อยกว่า)
find /var -size +100M # ใหญ่กว่า 100 MB
find . -size -10k # เล็กกว่า 10 KB
find . -size 0 # ไฟล์ขนาด 0
# ตามเวลา (mtime=modify, atime=access, ctime=change metadata)
find . -mtime -7 # ถูกแก้ไขใน 7 วันที่ผ่านมา
find . -mtime +30 # ไม่ได้แก้ไขมากกว่า 30 วัน
find . -mmin -60 # ใน 60 นาทีที่แล้ว
# ตามสิทธิ์
find . -perm 644 # สิทธิ์ตรงกัน 644
find . -perm -u+x # มีสิทธิ์ execute ของเจ้าของ
find / -perm -4000 -type f # SUID files (สำคัญสำหรับ security audit)
# ตามเจ้าของ
find /home -user moo
find /var -group www-data
find . -nouser # ไฟล์ที่ไม่มีเจ้าของ (orphan)
# รวมหลายเงื่อนไข (AND default, ใช้ -o สำหรับ OR, ! หรือ -not สำหรับ NOT)
find . -type f -name "*.log" -size +10M
find . \( -name "*.tmp" -o -name "*.bak" \) -delete
# -exec ทำ action กับผลลัพธ์ {} = ไฟล์ที่พบ, \; = จบคำสั่ง
find . -name "*.log" -exec gzip {} \;
find . -name "*.old" -exec rm -v {} \;
# \; รันคำสั่งต่อไฟล์, + รวมไฟล์ทั้งหมดเป็นครั้งเดียว (เร็วกว่า)
find . -name "*.txt" -exec grep "TODO" {} +
# -delete ลบเลย (ระวังใช้ เมื่อแน่ใจแล้วเท่านั้น)
find /tmp -name "*.cache" -mtime +7 -delete
# ตัวอย่างใช้งานจริง:
# หาไฟล์ที่ใหญ่ที่สุด 10 อันใน /var
find /var -type f -exec du -h {} + | sort -rh | head
# หาไฟล์ที่มีข้อความ "password" โดยไม่รวม .git
find . -type f ! -path "*/.git/*" -exec grep -l "password" {} +
# ลบ __pycache__ ทั้งหมดในโปรเจกต์ Python
find . -type d -name "__pycache__" -exec rm -rf {} +
locate เร็วมากเพราะค้นจากฐานข้อมูลที่สร้างไว้ล่วงหน้า (แต่ข้อมูลอาจไม่ล่าสุด)
# ติดตั้ง (ถ้ายังไม่มี)
sudo apt install plocate # หรือ mlocate
sudo updatedb # สร้าง/อัปเดตฐานข้อมูล (ต้องเป็น root)
# ค้นหา
locate nginx.conf
locate -i readme # case-insensitive
locate -c "*.pdf" # นับจำนวน
locate -r "^/etc/.*\.conf$" # regex mode
# locate อัตโนมัติจะ updatedb ผ่าน systemd timer หรือ cron รายวัน
ทั้งสี่ใช้หาตำแหน่งของคำสั่ง แต่มีความต่าง:
# which: บอก path ของ executable ใน $PATH
which python3 # → /usr/bin/python3
which ls # → /usr/bin/ls
# whereis: หาทั้ง binary, source, manual
whereis gcc # → gcc: /usr/bin/gcc /usr/share/man/man1/gcc.1.gz
# type: บอกว่าเป็น builtin, alias, function, หรือ external (แม่นสุด)
type cd # → cd is a shell builtin
type ll # → ll is aliased to 'ls -lah'
type python3 # → python3 is /usr/bin/python3
# command -v: เหมือน which แต่เป็น POSIX มาตรฐาน ใช้ใน script ได้ปลอดภัย
if command -v docker &>/dev/null; then
echo "Docker is installed"
fi
fd คือ find รุ่นใหม่ที่ syntax ง่ายและเร็วกว่า เข้าใจ .gitignore
sudo apt install fd-find # Debian/Ubuntu (อาจเรียก fdfind)
# หรือ Arch: sudo pacman -S fd
fd pattern # เหมือน find -iname "*pattern*"
fd -e py # หาไฟล์ .py
fd -H pattern # รวม hidden files
fd -t d node_modules # -t d = type directory
fd pattern -x wc -l # -x = execute (เหมือน -exec ของ find)
ระบบสิทธิ์ของ Unix/Linux เป็นรากฐานของความปลอดภัย ทุกไฟล์มี เจ้าของ (owner/user), กลุ่ม (group), และ อื่น ๆ (others) และสำหรับแต่ละกลุ่มมีสิทธิ์ 3 อย่าง: r (read), w (write), x (execute)
รูปแบบ Symbolic: [who][op][perm]
chmod u+x script.sh # เจ้าของได้สิทธิ์ execute เพิ่ม
chmod g-w file.txt # group ลบสิทธิ์ write
chmod o=r document.pdf # others อ่านได้อย่างเดียว
chmod a+r report.pdf # ทุกคนอ่านได้
chmod u=rwx,g=rx,o=r script.sh # กำหนดทุกชุดพร้อมกัน
chmod -R g+w project/ # -R = recursive
รูปแบบ Octal: ผลรวมของ r=4, w=2, x=1 ในแต่ละตำแหน่ง (u, g, o)
แสดงเป็นสมการทางคณิตศาสตร์:
เมื่อ ของแต่ละกลุ่ม (u, g, o) คำนวณจาก โดย , , มีค่า 0 หรือ 1
| Octal | Binary | Perm |
|---|---|---|
| 7 | 111 | rwx |
| 6 | 110 | rw- |
| 5 | 101 | r-x |
| 4 | 100 | r-- |
| 3 | 011 | -wx |
| 2 | 010 | -w- |
| 1 | 001 | --x |
| 0 | 000 | --- |
chmod 755 script.sh # rwxr-xr-x (exec สำหรับทุกคน, write เฉพาะเจ้าของ)
chmod 644 notes.txt # rw-r--r-- (ไฟล์ปกติ)
chmod 600 ~/.ssh/id_rsa # rw------- (ไฟล์ลับ เฉพาะเจ้าของ)
chmod 700 ~/.ssh # rwx------ (โฟลเดอร์ลับ)
chmod 777 /tmp # rwxrwxrwx (ระวัง! เปิดทั้งหมด)
# เปลี่ยนเจ้าของ
sudo chown alice file.txt
sudo chown alice:developers file.txt # พร้อมเปลี่ยน group
sudo chown -R www-data:www-data /var/www/app # recursive (เว็บไซต์ทั้งหมด)
sudo chown --reference=ref.txt file.txt # ใช้เจ้าของเหมือน ref.txt
# เปลี่ยนแค่ group
sudo chgrp developers file.txt
sudo chgrp -R www-data /srv/site/
umask คือ "หน้ากาก" ที่ใช้กันสิทธิ์ออกเมื่อสร้างไฟล์/โฟลเดอร์ใหม่ คำนวณจาก:
666 - umask777 - umaskumask # ดูค่าปัจจุบัน (มักเป็น 0022 หรือ 0002)
umask 0022 # ไฟล์จะได้ 644, โฟลเดอร์ได้ 755 (default)
umask 0077 # ไฟล์จะได้ 600, โฟลเดอร์ได้ 700 (paranoid mode)
umask -S # แสดงแบบ symbolic: u=rwx,g=rx,o=rx
# ตั้งถาวรใน ~/.bashrc หรือ /etc/profile
echo "umask 0027" >> ~/.bashrc
ทั้งสามเป็น "special permission" ที่มีฟังก์ชันพิเศษ:
SUID (Set User ID) = 4xxx: โปรแกรมที่รันจะมีสิทธิ์ของเจ้าของไฟล์แทน user ผู้เรียก
ตัวอย่างคลาสสิก: /usr/bin/passwd เป็นของ root มี SUID เพื่อให้ user ทั่วไปแก้รหัสผ่านตัวเองได้
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 ... passwd ← s ในตำแหน่ง x ของ user = SUID
SGID (Set Group ID) = 2xxx:
Sticky Bit = 1xxx: ในไดเรกทอรี แม้คนอื่นมีสิทธิ์ write ก็ลบได้เฉพาะไฟล์ของตัวเอง
ตัวอย่างคลาสสิก: /tmp มี sticky bit
ls -ld /tmp
# drwxrwxrwt 20 root root ... /tmp ← t ในตำแหน่ง x ของ others = sticky
# การตั้งค่า special permission (prefix ตัวแรกใน octal 4 หลัก)
chmod 4755 myapp # SUID + 755
chmod 2775 shared_dir # SGID + 775
chmod 1777 shared_tmp # Sticky + 777
chmod 7755 power_app # SUID + SGID + Sticky + 755
# รูปแบบ symbolic
chmod u+s myapp # SUID
chmod g+s shared_dir # SGID
chmod +t shared_tmp # Sticky
# ค้นหา SUID ทั้งระบบ (security audit)
find / -perm -4000 -type f 2>/dev/null
ทุกโปรแกรมที่รันอยู่เป็น Process แต่ละตัวมี PID (Process ID), PPID (Parent Process ID), สถานะ, เจ้าของ, และทรัพยากรที่ใช้อยู่ การจัดการโพรเซสเป็นทักษะสำคัญของ sysadmin
stateDiagram-v2
[*] --> NEW: fork()
NEW --> READY: admitted
READY --> RUNNING: scheduler dispatch
RUNNING --> READY: timer / preempt
RUNNING --> WAITING: I/O หรือ event
WAITING --> READY: I/O เสร็จ
RUNNING --> STOPPED: SIGSTOP / SIGTSTP
STOPPED --> READY: SIGCONT
RUNNING --> TERMINATED: exit() / SIGKILL
TERMINATED --> [*]
# BSD style (ยอดนิยม)
ps aux
# USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
# System V style
ps -ef
# UID PID PPID C STIME TTY TIME CMD
# ดูเฉพาะโพรเซสของตัวเอง
ps -u $USER
# ดูแบบ tree
ps -ef --forest
ps axjf
pstree -p # pstree สวยกว่า (ติดตั้ง psmisc)
# กรองด้วย grep (ระวัง grep ก็เป็น process ด้วย)
ps aux | grep nginx
ps aux | grep [n]ginx # trick: ใส่ [] กัน grep ตัวเอง
# pgrep - หา PID ตามชื่อ
pgrep nginx
pgrep -u moo firefox
pgrep -l ssh # -l แสดงชื่อด้วย
pgrep -a python # -a แสดง command line เต็ม
เครื่องมือ monitor แบบ interactive:
top # มาพร้อมทุก distro
# คีย์ใน top:
# M = เรียงตาม memory
# P = เรียงตาม CPU
# k = kill process (ใส่ PID)
# r = renice
# q = quit
htop # สวยกว่า - color, scroll, tree view
sudo apt install htop
btop # สวยที่สุด (เขียนด้วย C++)
sudo apt install btop
glances # python-based, แสดงทุกอย่างรวมทั้ง disk, network
sudo apt install glances
Signal เป็นวิธีสื่อสารกับ process ที่กำลังรันอยู่
| Signal | เลข | ความหมาย |
|---|---|---|
| SIGHUP | 1 | Hang up - มักใช้ให้ daemon reload config |
| SIGINT | 2 | Interrupt จากคีย์บอร์ด (Ctrl+C) |
| SIGQUIT | 3 | Quit + dump core (Ctrl+) |
| SIGKILL | 9 | บังคับฆ่าทันที - ดักไม่ได้ ignore ไม่ได้ |
| SIGTERM | 15 | Terminate อย่างสุภาพ (ตั้งค่า default ของ kill) |
| SIGSTOP | 19 | หยุดโพรเซส (ดักไม่ได้) |
| SIGTSTP | 20 | Suspend จากคีย์บอร์ด (Ctrl+Z) |
| SIGCONT | 18 | Continue ให้โพรเซสที่หยุดอยู่ทำงานต่อ |
| SIGUSR1/2 | 10/12 | ใช้งานโดยแอปพลิเคชัน |
# kill - ตาม PID
kill 1234 # ส่ง SIGTERM (15)
kill -9 1234 # ส่ง SIGKILL - ใช้เมื่อ TERM ไม่ได้ผล
kill -HUP 1234 # reload config
kill -l # list signal ทั้งหมด
# killall - ตามชื่อ (ฆ่าทุกตัว)
killall firefox
killall -9 stuck-app
# pkill - ตามชื่อด้วย pattern
pkill nginx
pkill -u moo # ฆ่า process ของ user moo ทั้งหมด
pkill -f "python.*train.py" # -f = match full command line
# ตัวอย่างจริง: reload nginx configuration
sudo nginx -t && sudo kill -HUP $(cat /var/run/nginx.pid)
# หรือแบบสมัยใหม่:
sudo systemctl reload nginx
การควบคุม job ใน shell:
# รันในพื้นหลัง (background) ใส่ & ท้ายคำสั่ง
long_task.sh &
# [1] 12345 ← job number, PID
# ดู job ใน shell นี้
jobs
jobs -l # -l แสดง PID ด้วย
# นำกลับมา foreground
fg %1 # job number 1
fg # job ล่าสุด
# ส่งไป background (หลังจาก Ctrl+Z suspend แล้ว)
bg %1
# nohup: ให้ process รันต่อแม้ shell ปิด (ปกติ shell จะส่ง SIGHUP ให้ลูก ๆ)
nohup python3 long_script.py &
# output จะถูกเขียนไปที่ nohup.out
# disown: ปลด job ออกจาก shell
long_running_command &
disown %1
# สมัยใหม่: ใช้ systemd-run แทน nohup
systemd-run --user --scope python3 script.py
# หรือใช้ tmux/screen (ดีที่สุดสำหรับ SSH)
tmux new -s work
# Ctrl+b d เพื่อ detach
tmux attach -t work
Nice value (−20 ถึง 19): ยิ่งเลขต่ำ priority ยิ่งสูง (user ทั่วไปตั้งค่าลบไม่ได้)
# รันด้วย priority ต่ำลง (nice value สูง) - ไม่รบกวนงานอื่น
nice -n 10 ./backup.sh
# รันด้วย priority สูง (ต้อง root)
sudo nice -n -5 ./critical.sh
# เปลี่ยน priority ของ process ที่กำลังรัน
renice -n 15 -p 1234
renice -n 10 -u moo # ทุก process ของ user
# ionice - ควบคุม I/O priority (disk)
# class: 1=realtime, 2=best-effort (default), 3=idle
ionice -c 3 tar czf backup.tar.gz /data/ # IO idle - ไม่แย่ง IO งานอื่น
ionice -c 2 -n 0 important.sh # best-effort level 0 (สูงสุด)
# lsof = list open files
sudo lsof # ทั้งหมด (เยอะมาก)
sudo lsof -i # network connection
sudo lsof -i :80 # port 80
sudo lsof -i :22 -u moo # port 22 ของ user moo
sudo lsof -p 1234 # ตาม PID
sudo lsof +D /var/log # ทุกไฟล์ที่เปิดอยู่ในโฟลเดอร์นี้ (recursive)
sudo lsof /var/log/syslog # ใครเปิดไฟล์นี้อยู่
# fuser - หา process ที่ใช้ไฟล์/port
sudo fuser /var/log/syslog # แสดง PID
sudo fuser -v /var/log/syslog # verbose
sudo fuser -k /mnt/usb # -k = kill (ใช้ก่อน umount)
sudo fuser 8080/tcp # ใครใช้ port 8080
tar = Tape ARchive รวมหลายไฟล์เป็นไฟล์เดียว โดย default ไม่บีบอัด แต่รวมกับ gzip/bzip2/xz/zstd ได้
Option ที่ต้องจำ:
# สร้าง archive
tar cf archive.tar file1 file2 dir/ # ไม่บีบอัด (.tar)
tar czf archive.tar.gz dir/ # gzip (.tar.gz หรือ .tgz)
tar cjf archive.tar.bz2 dir/ # bzip2 (ช้า แต่บีบแน่นกว่า)
tar cJf archive.tar.xz dir/ # xz (บีบแน่นสุด)
tar --zstd -cf archive.tar.zst dir/ # zstd (สมดุลสุด)
# ดูเนื้อหาโดยไม่แตก
tar tf archive.tar.gz
tar tzvf archive.tar.gz | head # + verbose
# แตก archive
tar xf archive.tar # auto-detect การบีบอัด (tar ใหม่)
tar xzf archive.tar.gz -C /tmp/ # -C = extract ไปที่อื่น
# แตกเฉพาะบางไฟล์
tar xzf backup.tar.gz path/to/specific/file
# exclude ไฟล์บางอย่าง
tar czf backup.tar.gz --exclude='*.log' --exclude='node_modules' project/
# มี verbose + ดู progress ไฟล์ใหญ่
tar czvf huge.tar.gz big_folder/
# incremental backup (ครั้งแรกทำ full, ครั้งต่อไปเฉพาะที่เปลี่ยน)
tar czf backup_full.tar.gz -g snapshot.snar /data/
tar czf backup_incr1.tar.gz -g snapshot.snar /data/
บีบอัดไฟล์เดียว (ไม่รวมหลายไฟล์เหมือน zip/tar):
# gzip (เร็ว, กลาง)
gzip file.txt # ได้ file.txt.gz ไฟล์ต้นหายไป
gzip -k file.txt # -k = keep ต้นฉบับ
gzip -9 file.txt # -9 = อัดแน่นสุด (ช้า)
gunzip file.txt.gz # หรือ gzip -d
zcat file.txt.gz # อ่านโดยไม่แตก
# bzip2 (บีบแน่นกว่า แต่ช้า)
bzip2 file.txt
bunzip2 file.txt.bz2
bzcat file.txt.bz2
# xz (บีบแน่นสุดในสาม)
xz file.txt
unxz file.txt.xz
xzcat file.txt.xz
# zstd (รุ่นใหม่ เร็วมาก บีบดี)
sudo apt install zstd
zstd file.txt # ได้ file.txt.zst
unzstd file.txt.zst
zstdcat file.txt.zst
# เปรียบเทียบ (อ้างอิงทั่วไป):
# gzip: เร็ว, ratio ~2-3x
# bzip2: ช้า, ratio ~3x
# xz: ช้ามาก, ratio ~4x
# zstd: เร็วมาก, ratio ~2.5-3x (ปรับ level ได้ -1 ถึง -22)
เข้ากันได้กับ Windows:
# zip
zip -r archive.zip folder/ # -r = recursive
zip -e secret.zip file.txt # -e = encrypt (ใส่รหัส)
zip -9 tight.zip file.txt # max compression
unzip archive.zip # แตกที่นี่
unzip archive.zip -d /tmp # -d = destination
unzip -l archive.zip # -l = list
unzip -p archive.zip file.txt # -p = pipe to stdout
# 7z (อัดแน่นดีมาก รองรับหลายฟอร์แมต)
sudo apt install p7zip-full
7z a archive.7z folder/ # a = add
7z x archive.7z # x = extract (เก็บโครงสร้าง)
7z l archive.7z # l = list
7z a -p -mhe=on secret.7z data/ # encrypt headers ด้วย
# backup เฉพาะไฟล์ที่แก้ไขใน 7 วัน
find /home/moo -type f -mtime -7 -print0 | tar czf backup.tar.gz --null -T -
# backup เฉพาะ .md และ .txt
find ~/docs -type f \( -name "*.md" -o -name "*.txt" \) | \
tar czf docs_backup.tar.gz -T -
# backup โปรเจกต์ โดย exclude ของที่ไม่จำเป็น
tar czf project_$(date +%Y%m%d).tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='*.pyc' \
--exclude='__pycache__' \
~/projects/ai-course/
# backup ไป remote ผ่าน SSH
tar czf - /data | ssh user@backup-server "cat > /backup/data_$(date +%F).tar.gz"
# ping ทดสอบ reachability และ latency
ping google.com # หยุดด้วย Ctrl+C (Linux ping ต่อเนื่อง)
ping -c 4 8.8.8.8 # -c = count 4 แพ็กเก็ตแล้วหยุด
ping -i 0.2 target # -i = interval 0.2 วินาที
ping -s 1472 -M do target # -s ขนาด, -M do = don't fragment (หา MTU)
# traceroute เห็นทุก hop ตลอดเส้นทาง
traceroute google.com
traceroute -n google.com # -n = ไม่ resolve DNS (เร็วขึ้น)
traceroute -I target # ใช้ ICMP (default บาง distro ใช้ UDP)
# tracepath - ไม่ต้อง root
tracepath google.com
# mtr (My TraceRoute) = ping + traceroute แบบ real-time (แนะนำสุด)
sudo apt install mtr
mtr google.com
mtr -n -c 100 -r target # -r = report mode
คำสั่ง ifconfig และ route ถูกแทนที่ด้วย ip ที่ทรงพลังกว่า (จากชุด iproute2)
# ---------- interface / address ----------
ip addr # หรือ ip a
ip -4 addr # เฉพาะ IPv4
ip -6 addr # เฉพาะ IPv6
ip addr show eth0 # เฉพาะ interface หนึ่ง
# เพิ่ม/ลบ IP address
sudo ip addr add 192.168.1.10/24 dev eth0
sudo ip addr del 192.168.1.10/24 dev eth0
# ---------- link (interface up/down) ----------
ip link # หรือ ip l
sudo ip link set eth0 up
sudo ip link set eth0 down
sudo ip link set eth0 mtu 1500
# ---------- route (routing table) ----------
ip route # หรือ ip r
sudo ip route add 10.0.0.0/24 via 192.168.1.1
sudo ip route del 10.0.0.0/24
ip route get 8.8.8.8 # ดูว่าจะไป 8.8.8.8 ทางไหน
# ---------- ARP table / neighbor ----------
ip neigh # ARP cache
sudo ip neigh flush all # ล้าง cache
ss -t # TCP connections ที่ established
ss -u # UDP
ss -l # listening
ss -tlnp # ใช้บ่อย: TCP listening, no resolve, + process
# -t=TCP, -l=listen, -n=numeric, -p=process
# ใครฟัง port ไหน
sudo ss -tlnp
# LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=789,fd=3))
# connection ที่เชื่อมต่ออยู่กับ port 443
ss -t state established '( dport = :443 or sport = :443 )'
# นับ connection ต่อ state
ss -ta | awk '{print $1}' | sort | uniq -c
# ---------- curl - Swiss Army knife ของ HTTP ----------
curl https://example.com # GET + print to stdout
curl -o page.html https://example.com # -o = output file
curl -O https://example.com/file.zip # -O = ใช้ชื่อไฟล์จาก URL
curl -L https://bit.ly/xxx # -L = ตาม redirect
curl -I https://example.com # -I = HEAD request (ดูแค่ header)
curl -v https://example.com # -v = verbose
curl -s https://api.example.com/data # -s = silent (ไม่มี progress bar)
# ---- Method, Header, Body ----
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOKEN123" \
-d '{"name":"Moo","role":"lecturer"}'
# ใช้ไฟล์เป็น body
curl -X POST https://api.example.com/upload -d @data.json
# Basic Auth
curl -u username:password https://api.example.com/protected
# Download ต่อจากที่ค้าง
curl -C - -O https://example.com/bigfile.iso
# ---------- wget - เน้นดาวน์โหลดไฟล์ ----------
wget https://example.com/file.zip
wget -c url # -c = continue
wget -b url # -b = background (log ไป wget-log)
wget -r -np -k -E url # mirror เว็บทั้งเว็บ (-r recursive, -np ไม่ขึ้นไปโฟลเดอร์แม่)
# ---------- aria2c - รุ่นใหม่ รองรับ multi-connection, torrent ----------
aria2c -x 16 -s 16 url # 16 connections พร้อมกัน เร็วมาก
aria2c -i urls.txt # รายการ URL
# nslookup - เก่าแต่ยังใช้
nslookup google.com
nslookup google.com 8.8.8.8 # ใช้ DNS server เฉพาะ
# dig - ละเอียดที่สุด แนะนำ
dig google.com # default A record
dig google.com MX # mail record
dig google.com NS # name server
dig google.com AAAA # IPv6
dig google.com ANY
dig +short google.com # output สั้น
dig +trace google.com # ตามทุก resolver (DNS root → TLD → authoritative)
dig @8.8.8.8 google.com # ใช้ server 8.8.8.8
dig -x 8.8.8.8 # reverse lookup (IP → name)
# host - เรียบง่าย
host google.com
host -t MX google.com
host google.com 1.1.1.1
netcat = "Swiss Army knife ของเครือข่าย" ใช้เชื่อมต่อ/ฟัง TCP/UDP ได้ทุกรูปแบบ
# ทดสอบว่า port เปิดอยู่ไหม
nc -zv example.com 443 # -z = scan (no I/O), -v = verbose
nc -zv example.com 20-30 # range of ports
# ส่งข้อมูลหา server
echo "GET / HTTP/1.0" | nc example.com 80
# เปิด listener (server แบบง่ายสุด)
nc -l 9000 # ฟัง port 9000
# ในอีก terminal:
echo "hello" | nc localhost 9000
# ส่งไฟล์ระหว่างเครื่อง
# รับ: nc -l 9000 > received.tar.gz
# ส่ง: nc receiver-ip 9000 < file.tar.gz
# chat ง่าย ๆ
# server: nc -l 9000
# client: nc server-ip 9000
# socat - ทรงพลังกว่า nc รองรับ SSL, UNIX socket, etc.
socat - TCP:example.com:80 # เหมือน nc
socat TCP-LISTEN:8080,fork TCP:localhost:80 # forward port
socat OPENSSL:example.com:443,verify=0 - # เชื่อมต่อ TLS
nmap คือเครื่องมือ scan เครือข่ายและ port ที่นิยมที่สุด (หมายเหตุ: ใช้สแกนเฉพาะเครือข่ายของตัวเองเท่านั้น)
sudo apt install nmap
# สแกน host เดียว (port ยอดนิยม 1000 port)
nmap 192.168.1.10
# สแกนทั้ง subnet (host discovery)
nmap -sn 192.168.1.0/24 # -sn = ping scan ไม่สแกน port
# สแกน port ทั้งหมด
nmap -p- 192.168.1.10
# สแกนเฉพาะ port
nmap -p 22,80,443 target
nmap -p 1-1000 target
# ตรวจสอบ version ของ service
nmap -sV target
# ตรวจสอบ OS
sudo nmap -O target
# สแกนแบบเร็ว (top 100 ports)
nmap -F target
# aggressive - รวมทุก feature (-A = -O + -sV + -sC + --traceroute)
sudo nmap -A -T4 target
uname # ชื่อ kernel → Linux
uname -r # kernel version → 6.11.5-arch1-1
uname -m # architecture → x86_64
uname -a # ทั้งหมด
# hostname
hostname # แสดงชื่อเครื่อง
sudo hostname newname # ตั้งแบบชั่วคราว (รีบูตหาย)
# hostnamectl (systemd) - ตั้งถาวร
hostnamectl # แสดงข้อมูลครบ (static/pretty/transient, chassis, OS)
sudo hostnamectl set-hostname myserver
sudo hostnamectl set-chassis laptop # desktop, laptop, server, vm, container
uptime
# 14:32:08 up 5 days, 3:47, 2 users, load average: 0.45, 0.32, 0.28
# ปัจจุบัน, uptime, user logged in, load avg 1/5/15 นาที
# date - แสดง/ตั้งวันที่
date
date "+%Y-%m-%d %H:%M:%S" # format เอง
date +%s # Unix timestamp
date -d "2 days ago" # คำนวณวันที่
date -d "@1700000000" # แปลง timestamp → date
date -u # UTC
# timedatectl (systemd)
timedatectl # ข้อมูลเวลาทั้งหมด
sudo timedatectl set-timezone Asia/Bangkok
sudo timedatectl set-ntp true # เปิด NTP sync
timedatectl list-timezones | grep Asia
# cal - ปฏิทิน
cal # เดือนปัจจุบัน
cal 2026
cal 11 2026
cal -3 # 3 เดือน (ก่อน-ปัจจุบัน-หลัง)
# df = disk free (ระบบไฟล์)
df # byte แบบ block
df -h # human-readable (K, M, G)
df -h / # เฉพาะพาร์ทิชัน root
df -hT # -T = แสดง type ของ filesystem
df -i # inode usage (อาจหมดแม้ที่เหลือเยอะ!)
# du = disk usage (โฟลเดอร์/ไฟล์)
du /var/log # recursive byte
du -h /var/log # human-readable
du -sh /var/log # -s = summary (ไม่แสดงรายละเอียดย่อย)
du -sh */ # ขนาดของแต่ละโฟลเดอร์ย่อย
du -h --max-depth=1 /var # ควบคุมความลึก
du -sh /* 2>/dev/null | sort -rh | head # top 10 ของ root
# ทางเลือกใหม่: ncdu (ncurses disk usage) - ใช้คีย์เลื่อนดูได้
sudo apt install ncdu
ncdu / # สแกนทั้งระบบแล้ว browse ได้
# free = RAM / Swap
free # byte
free -h # human-readable
free -m # MB
free -s 2 # -s = update ทุก 2 วินาที
# lsblk = list block devices (disks, partitions)
lsblk # เห็น tree ของ disk
lsblk -f # -f = แสดง filesystem type + UUID + label
lsblk -p # -p = full path /dev/sda แทน sda
# blkid = แสดง UUID / filesystem ของแต่ละ block
sudo blkid
# /dev/sda1: UUID="abcd-1234" TYPE="ext4" PARTUUID="..."
# mount = เม้าต์ระบบไฟล์
sudo mkdir /mnt/usb
sudo mount /dev/sdb1 /mnt/usb # mount
sudo mount -o ro /dev/sdb1 /mnt/usb # read-only
sudo mount -t nfs server:/share /mnt/nfs # NFS
sudo mount -t ext4 -o rw,noatime /dev/sda2 /data
mount # ดู mount ทั้งหมด (ยาวมาก)
mount | grep sdb
findmnt # สวยกว่า tree view
# umount
sudo umount /mnt/usb
sudo umount -l /mnt/usb # -l = lazy (ถ้ามี file ที่เปิดอยู่)
# /etc/fstab - mount อัตโนมัติตอน boot
# UUID=xxx /data ext4 defaults,noatime 0 2
# ฟิลด์: device mountpoint type options dump fsck-pass
sudo mount -a # mount ทุกอย่างใน fstab
sudo systemctl daemon-reload
# lscpu = CPU info
lscpu
# Architecture, CPU(s), Model name, CPU MHz, L1/L2/L3 cache, Virtualization
# ดูว่ารองรับ virtualization (VT-x/AMD-V) ไหม
lscpu | grep -i virtualization
# lsusb = USB devices
lsusb
lsusb -t # tree
lsusb -v # verbose (เยอะมาก)
# lspci = PCI devices (VGA, network card, sound card)
lspci
lspci -k # -k = แสดง kernel driver ที่ใช้
lspci -nnk | grep -iA 3 vga
# lsmod = kernel modules ที่โหลดอยู่
lsmod
lsmod | grep nvidia
modinfo <module> # ดูรายละเอียด module
sudo modprobe <module> # โหลด module
sudo modprobe -r <module> # unload
# dmesg = kernel ring buffer (log ของ kernel)
sudo dmesg # ทั้งหมด (ยาวมาก)
sudo dmesg -T # -T = แปลงเวลาเป็น human-readable
sudo dmesg -w # -w = follow แบบ real-time
sudo dmesg | grep -i error
sudo dmesg | grep -i usb # ดูว่า USB ตัวใหม่เสียบเจออะไร
# journalctl (systemd) - log แบบสมัยใหม่
journalctl -xe # log ล่าสุด + explanation
journalctl -u nginx # เฉพาะ service
journalctl --since "1 hour ago"
journalctl -k # kernel log (เหมือน dmesg)
journalctl -f # follow
# man = manual page (มาตรฐาน Unix)
man ls
man 5 passwd # ระบุ section
man -k keyword # ค้นหา (เหมือน apropos)
man -f command # สั้น (เหมือน whatis)
# Section ของ man:
# 1 = user command
# 2 = system call
# 3 = library function
# 4 = device file
# 5 = config file format
# 7 = misc (protocol, convention)
# 8 = admin command
# คีย์ใน man (เหมือน less):
# / ค้นหา, n ถัดไป, q ออก
# info = manual แบบ hypertext ของ GNU (ละเอียดกว่า man)
info ls
# --help = ช่วยเหลือในตัว (เร็ว เน้น)
ls --help
rsync --help | less
# tldr - "too long; didn't read" ให้ตัวอย่างสั้นที่ใช้บ่อย
sudo apt install tldr # หรือ npm install -g tldr
tldr tar
tldr ffmpeg
tldr curl
# cheat - สร้าง cheatsheet ส่วนตัวได้
pip install cheat
cheat tar
ตัวอย่างการใช้คำสั่งในบทนี้ร่วมกันเพื่อแก้ปัญหาจริง เตรียมข้อมูลและคัดลอกบล็อกโค้ดไปทดสอบในเครื่องของผู้เรียนได้ทันที:
# ============================================================
# Lab 1: เตรียมสภาพแวดล้อม
# ============================================================
mkdir -p ~/linux-lab/{logs,data,backup,scripts}
cd ~/linux-lab
# สร้างข้อมูลตัวอย่าง
cat > data/sales.csv << 'EOF'
date,product,quantity,price
2025-10-01,apple,5,25
2025-10-01,banana,3,15
2025-10-02,apple,2,25
2025-10-02,cherry,4,40
2025-10-03,banana,6,15
2025-10-03,apple,3,25
EOF
# สร้าง log ตัวอย่าง
for i in {1..100}; do
level=$(shuf -e INFO WARN ERROR DEBUG -n 1)
echo "$(date -d "-$i minutes" '+%Y-%m-%d %H:%M:%S') [$level] Event number $i" \
>> logs/app.log
done
# ============================================================
# Lab 2: การวิเคราะห์ข้อความ
# ============================================================
# นับ log ตาม level
awk '{print $3}' logs/app.log | sort | uniq -c | sort -rn
# หายอดรวมและเฉลี่ยของ apple
awk -F, '$2=="apple" {total += $3*$4; count += $3}
END {print "Total sold:", count, "Revenue:", total}' data/sales.csv
# สรุปยอดทุกสินค้า
awk -F, 'NR>1 {rev[$2] += $3*$4; qty[$2] += $3}
END {for (p in rev) printf "%-10s qty=%d rev=%d\n", p, qty[p], rev[p]}' \
data/sales.csv
# ============================================================
# Lab 3: การจัดการไฟล์ขั้นสูง
# ============================================================
# หาไฟล์ที่ใหญ่กว่า 1KB แล้ว backup
find ~/linux-lab -type f -size +1k -exec cp {} backup/ \;
# สร้าง archive พร้อม timestamp
tar czf backup_$(date +%Y%m%d_%H%M%S).tar.gz logs/ data/
# ============================================================
# Lab 4: ติดตาม log แบบ real-time + filter
# ============================================================
# เปิด Terminal 1
tail -f logs/app.log | grep --line-buffered ERROR
# Terminal 2: เพิ่ม log เข้าไป
echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] Manual test error" >> logs/app.log
# ============================================================
# Lab 5: One-liner วิเคราะห์ระบบ
# ============================================================
# Top 5 processes ใช้ RAM
ps aux --sort=-%mem | awk 'NR<=6 {print $2, $4"%", $11}'
# นับจำนวน connection ตาม state
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c
# หาไฟล์ที่ใหญ่สุด 10 อันใน home
du -ah ~/ 2>/dev/null | sort -rh | head -10
# หาไฟล์ที่แก้ไขภายใน 1 ชั่วโมง
find ~/ -type f -mmin -60 2>/dev/null
# รายงานพื้นที่ดิสก์แบบสั้น
df -h | awk 'NR==1 || $5+0 > 50' # แสดงบรรทัดที่ใช้เกิน 50%
การฝึกทำ lab เหล่านี้จะช่วยให้ผู้เรียนเห็นว่าคำสั่งแต่ละตัว ไม่ได้มีประโยชน์โดดเดี่ยว แต่ พลังที่แท้จริงเกิดจากการต่อกันเป็น pipeline ตามปรัชญา Unix อย่างแท้จริง