❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.
Ở các bài trước, bạn đã biết cách tạo file, xóa file, phân quyền, quản lý tiến trình. Nhưng sức mạnh thực sự của Linux nằm ở khả năng xử lý text. Hôm nay mình sẽ giới thiệu bộ công cụ mà dân sysadmin dùng hằng ngày: pipe, grep, redirect, awk, sed và một số lệnh xử lý dữ liệu khác.

Nắm được mấy thứ này, bạn có thể lọc log, phân tích traffic, tìm lỗi trong hàng triệu dòng text chỉ với một dòng lệnh.
Pipe (|), Nối lệnh lại với nhau
Pipe là ký tự |, dùng để lấy output của lệnh bên trái làm input cho lệnh bên phải. Đây là khái niệm nền tảng nhất khi làm việc với text trên Linux.
Cú pháp:
lệnh_1 | lệnh_2 | lệnh_3
Ví dụ, bạn muốn xem có bao nhiêu tiến trình nginx đang chạy:
ps aux | grep nginx
Lệnh ps aux liệt kê toàn bộ tiến trình, sau đó pipe sang grep nginx để chỉ lọc ra dòng nào có chữ “nginx”.
Một ví dụ khác, đếm số dòng trong file:
cat /etc/passwd | wc -l
Hoặc xem 20 file lớn nhất trong thư mục hiện tại:
du -sh * | sort -rh | head -20
Bạn có thể nối bao nhiêu pipe cũng được. Mỗi lệnh trong chuỗi nhận output từ lệnh trước và xử lý tiếp.
grep, Tìm text nhanh và mạnh
grep là lệnh dùng nhiều nhất khi làm việc với text trên Linux. Nó tìm các dòng chứa chuỗi ký tự bạn chỉ định, trong file hoặc trong output từ pipe.
Cú pháp cơ bản:
grep "chuỗi_cần_tìm" tên_file
Các option hay dùng
-i, Không phân biệt hoa thường (case insensitive):
grep -i "error" /var/log/syslog
Lệnh trên sẽ tìm được cả “Error”, “ERROR”, “error”.
-n, Hiện số dòng:
grep -n "failed" /var/log/auth.log
Output sẽ kèm số dòng ở đầu, giúp bạn biết chính xác lỗi nằm ở đâu trong file.
-r, Tìm đệ quy trong thư mục:
grep -r "listen 80" /etc/nginx/
Tìm trong tất cả file bên trong thư mục /etc/nginx/ và các thư mục con.
-v, Invert, hiện những dòng KHÔNG chứa chuỗi:
grep -v "^#" /etc/nginx/nginx.conf
Lọc bỏ tất cả dòng comment (bắt đầu bằng #), chỉ hiện config thực sự.
-c, Đếm số dòng khớp:
grep -c "404" /var/log/nginx/access.log
Cho biết có bao nhiêu request trả về lỗi 404.
-E, Dùng regex mở rộng:
grep -E "error|warning|critical" /var/log/syslog
Tìm đồng thời nhiều từ khóa bằng regex.
Hiện thêm context xung quanh kết quả
Khi grep tìm thấy lỗi, bạn thường muốn xem thêm vài dòng trước/sau để hiểu ngữ cảnh:
# -A 3: hiện thêm 3 dòng SAU dòng khớp (After)
grep -A 3 "error" /var/log/syslog
# -B 2: hiện thêm 2 dòng TRƯỚC dòng khớp (Before)
grep -B 2 "error" /var/log/syslog
# -C 2: hiện thêm 2 dòng cả trước và sau (Context)
grep -C 2 "error" /var/log/syslog
Ví dụ thực tế: Tìm lỗi trong log
Giả sử website bạn bị lỗi, cần tìm xem chuyện gì xảy ra:
# Tìm tất cả lỗi PHP trong error log
grep -i "fatal\|error" /var/log/php-fpm/error.log
# Tìm lỗi trong 1 giờ gần nhất (giả sử log có timestamp dạng "Mar 15 16:")
grep "Mar 15 16:" /var/log/syslog | grep -i error
# Đếm số lần xuất hiện lỗi 502 trong access log
grep -c " 502 " /var/log/nginx/access.log
Redirect, Điều hướng input/output
Trên Linux, mỗi lệnh có 3 luồng dữ liệu:
- stdin (0): dữ liệu đầu vào
- stdout (1): kết quả bình thường
- stderr (2): thông báo lỗi
Redirect cho phép bạn chuyển hướng các luồng này thay vì hiện ra terminal.
Ghi output ra file
>, Ghi đè file (tạo mới nếu chưa có, xóa nội dung cũ nếu đã có):
echo "Hello" > output.txt
ls -la /etc > danh-sach.txt
>>, Nối thêm vào cuối file (không xóa nội dung cũ):
echo "Dòng mới" >> output.txt
date >> log.txt
Cẩn thận với >! Nếu bạn gõ nhầm > thay vì >>, nội dung cũ sẽ bị xóa sạch không cứu được.
Redirect stderr
2>, Chuyển hướng chỉ phần lỗi:
# Lưu lỗi vào file riêng
find / -name "*.conf" 2> errors.txt
# Bỏ qua lỗi hoàn toàn
find / -name "*.conf" 2>/dev/null
&>, Chuyển hướng cả stdout và stderr vào cùng một file:
command &> all-output.txt
Redirect input
<, Đọc input từ file thay vì từ bàn phím:
mysql -u root -p database_name < backup.sql
wc -l < /etc/passwd
/dev/null, Hố đen của Linux
/dev/null là một file đặc biệt, mọi thứ ghi vào đây sẽ biến mất. Dùng khi bạn muốn chạy lệnh mà không cần thấy output:
# Chạy lệnh, bỏ qua mọi output
command > /dev/null 2>&1
# Viết ngắn hơn (bash 4+)
command &> /dev/null
Hay gặp trong crontab khi bạn không muốn nhận email thông báo mỗi lần cron chạy.
Kết hợp pipe và redirect
Sức mạnh thực sự đến khi bạn kết hợp pipe với redirect:
# Tìm 20 dòng error cuối cùng trong syslog, lưu ra file
grep -i error /var/log/syslog | tail -20 > errors.txt
# Liệt kê user đang login, sắp xếp, lưu file
who | sort > users-online.txt
# Tìm tất cả file .log lớn hơn 100MB
find /var/log -name "*.log" -size +100M 2>/dev/null | sort > large-logs.txt
awk, Xử lý dữ liệu theo cột
awk là công cụ xử lý text mạnh, đặc biệt hữu ích khi dữ liệu có cấu trúc theo cột (như file log, CSV). Mình sẽ giới thiệu những cách dùng cơ bản nhất.
In cột chỉ định
Trong awk, $1 là cột 1, $2 là cột 2, $0 là toàn bộ dòng. Mặc định các cột phân tách bằng khoảng trắng.
# In cột 1 và cột 4 từ access log (IP và thời gian)
awk '{print $1, $4}' /var/log/nginx/access.log
# In cột 1 (username) từ /etc/passwd, phân tách bằng dấu :
awk -F: '{print $1}' /etc/passwd
# In dòng có cột 9 = 404 (HTTP status code)
awk '$9 == 404 {print $0}' /var/log/nginx/access.log
Đếm và tính toán
# Đếm số request từ mỗi IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn
# Tính tổng bytes (cột 10) trong access log
awk '{sum += $10} END {print sum}' access.log
# Tính tổng và format ra MB
awk '{sum += $10} END {printf "%.2f MB\n", sum/1024/1024}' access.log
sed, Tìm và thay thế text
sed (stream editor) dùng để thay đổi nội dung text. Phổ biến nhất là tìm và thay thế.
Thay thế text
# Thay thế lần đầu tiên trong mỗi dòng
sed 's/old/new/' file.txt
# Thay thế tất cả (global)
sed 's/old/new/g' file.txt
# Thay thế và ghi trực tiếp vào file (-i)
sed -i 's/old-domain.com/new-domain.com/g' config.conf
# Thay thế không phân biệt hoa thường
sed 's/error/WARNING/gi' log.txt
Option -i sẽ sửa trực tiếp file gốc. Nếu muốn an toàn, dùng -i.bak để tạo bản backup trước khi sửa: sed -i.bak 's/old/new/g' file.txt
Xóa dòng và in theo range
# Xóa dòng 5
sed '5d' file.txt
# Xóa từ dòng 10 đến dòng 20
sed '10,20d' file.txt
# Xóa dòng trống
sed '/^$/d' file.txt
# Chỉ in dòng 5 đến 10 (tương tự head/tail nhưng linh hoạt hơn)
sed -n '5,10p' file.txt
# Xóa tất cả dòng comment
sed '/^#/d' config.conf
Ví dụ thực tế
# Đổi port SSH trong config
sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config
# Thêm dòng sau dòng chứa "server_name"
sed -i '/server_name/a\ include /etc/nginx/extra.conf;' /etc/nginx/sites-available/default
# Xóa tất cả comment và dòng trống để xem config gọn
sed '/^#/d; /^$/d' /etc/nginx/nginx.conf
sort, uniq, cut, tr, Bộ công cụ xử lý data
Mấy lệnh này tuy đơn giản nhưng khi kết hợp với pipe thì rất mạnh.
sort, Sắp xếp
# Sắp xếp theo alphabet
sort file.txt
# Sắp xếp theo số
sort -n numbers.txt
# Sắp xếp ngược (lớn đến nhỏ)
sort -rn numbers.txt
# Sắp xếp theo cột 3, phân tách bằng dấu phẩy
sort -t',' -k3 -n data.csv
uniq, Loại bỏ dòng trùng
# Loại bỏ dòng trùng liên tiếp (phải sort trước)
sort file.txt | uniq
# Đếm số lần xuất hiện
sort file.txt | uniq -c
# Chỉ hiện dòng bị trùng
sort file.txt | uniq -d
uniq chỉ loại bỏ dòng trùng liên tiếp, nên bạn cần sort trước. Đây là combo kinh điển: sort | uniq -c | sort -rn
cut, Cắt cột
# Lấy cột 1 từ file CSV (phân tách bằng dấu phẩy)
cut -d',' -f1 data.csv
# Lấy cột 1 và 3
cut -d',' -f1,3 data.csv
# Lấy username từ /etc/passwd
cut -d: -f1 /etc/passwd
# Lấy ký tự từ vị trí 1 đến 10
cut -c1-10 file.txt
tr, Chuyển đổi ký tự
# Chuyển chữ thường thành chữ hoa
echo "hello" | tr 'a-z' 'A-Z'
# Xóa ký tự xuống dòng thừa
cat file.txt | tr -s '\n'
# Thay tab thành dấu phẩy
cat file.txt | tr '\t' ','
# Xóa tất cả số
echo "abc123def456" | tr -d '0-9'
Pipeline kinh điển: Top 10 IP truy cập
Đây là ví dụ mà sysadmin nào cũng dùng. Phân tích access log để tìm 10 IP truy cập nhiều nhất:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
Giải thích từng bước:
awk '{print $1}', lấy cột đầu tiên (IP address)sort, sắp xếp để các IP giống nhau nằm cạnh nhauuniq -c, đếm số lần xuất hiện của mỗi IPsort -rn, sắp xếp theo số lượng, từ cao xuống thấphead -10, chỉ lấy 10 dòng đầu
Output trông kiểu này:
4523 192.168.1.100
3891 10.0.0.50
2104 203.0.113.42
1876 198.51.100.7
...
tee, Vừa xem vừa lưu
tee giống như một ngã ba: nó vừa hiện output ra terminal, vừa ghi vào file cùng lúc.
# Vừa xem trên terminal, vừa lưu vào file
ping google.com | tee ping-result.txt
# Nối thêm thay vì ghi đè
df -h | tee -a disk-log.txt
# Kết hợp trong pipeline
grep "error" /var/log/syslog | tee errors.txt | wc -l
Ví dụ cuối rất hay: nó lọc error, lưu vào file errors.txt, đồng thời đếm xem có bao nhiêu dòng error tất cả.
Một trường hợp hữu ích nữa là khi cần ghi file với quyền root:
# Không hoạt động vì redirect chạy với user hiện tại
echo "nameserver 8.8.8.8" > /etc/resolv.conf
# Hoạt động vì tee chạy với sudo
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
xargs, Chuyển output thành arguments
Một số lệnh không đọc input từ pipe. Ví dụ rm không đọc tên file từ stdin. Lúc này xargs giúp chuyển output của lệnh trước thành tham số cho lệnh sau.
# Tìm và xóa tất cả file .tmp
find /tmp -name "*.tmp" | xargs rm -f
# Tìm file .log cũ hơn 30 ngày và xóa
find /var/log -name "*.log" -mtime +30 | xargs rm -f
# An toàn hơn với tên file có khoảng trắng
find /tmp -name "*.tmp" -print0 | xargs -0 rm -f
Option -print0 và -0 dùng null character thay vì xuống dòng để phân tách, đảm bảo tên file có khoảng trắng hoặc ký tự đặc biệt vẫn xử lý đúng.
Một số ví dụ khác:
# Nén tất cả file .log lại
find /var/log -name "*.log" | xargs gzip
# Kill tất cả tiến trình của user cụ thể
ps aux | grep "^username" | awk '{print $2}' | xargs kill
# Download nhiều URL từ file
cat urls.txt | xargs -n1 wget
Option -n1 nghĩa là mỗi lần chỉ truyền 1 argument, hữu ích khi lệnh chỉ nhận từng tham số một.
Checkpoint: Bài tập thực hành
Dưới đây là một số bài tập để bạn tự luyện. Tất cả đều dùng các lệnh đã học trong bài này.
Bài 1: Phân tích access log
Giả sử bạn có file /var/log/nginx/access.log, hãy thực hiện:
# 1. Tìm top 10 IP truy cập nhiều nhất
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 2. Đếm số request theo HTTP status code
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 3. Tìm các URL trả về lỗi 500
awk '$9 == 500 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 4. Xem top 10 URL được truy cập nhiều nhất
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 5. Tính tổng bandwidth (bytes) đã dùng
awk '{sum += $10} END {printf "Total: %.2f MB\n", sum/1024/1024}' /var/log/nginx/access.log
Bài 2: Lọc error trong syslog
# 1. Tìm tất cả dòng có chứa "error" (không phân biệt hoa thường)
grep -i "error" /var/log/syslog
# 2. Đếm số lần xuất hiện error theo từng service
grep -i "error" /var/log/syslog | awk '{print $5}' | sort | uniq -c | sort -rn
# 3. Lọc error trong 1 giờ gần nhất và lưu ra file
grep "$(date '+%b %d %H')" /var/log/syslog | grep -i error > /tmp/recent-errors.txt
# 4. Tìm các lỗi SSH failed login
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
Bài 3: Kết hợp sed với pipeline
# 1. Xem Nginx config sạch (bỏ comment và dòng trống)
sed '/^[[:space:]]*#/d; /^$/d' /etc/nginx/nginx.conf
# 2. Export danh sách user (chỉ lấy username và shell)
awk -F: '{print $1, $7}' /etc/passwd | sort
# 3. Thay đổi hàng loạt domain trong config
find /etc/nginx/sites-available/ -type f | xargs sed -i 's/old-domain.com/new-domain.com/g'
Tổng kết
Trong bài này bạn đã học:
- Pipe (
|), nối output/input giữa các lệnh - grep, tìm kiếm text với nhiều option mạnh
- Redirect, điều hướng stdout, stderr, stdin bằng
>,>>,2>,&>,< - awk, xử lý dữ liệu theo cột, đếm và tính toán
- sed, tìm và thay thế text, xóa dòng
- sort, uniq, cut, tr, bộ công cụ xử lý data trong pipeline
- tee, vừa hiện terminal vừa ghi file
- xargs, chuyển output thành arguments cho lệnh khác
Những lệnh này đơn lẻ thì bình thường, nhưng khi kết hợp qua pipe thì bạn có thể xử lý data phức tạp chỉ trong một dòng lệnh. Sysadmin hay gọi đây là "one-liner" và đây thực sự là kỹ năng khiến bạn làm việc nhanh gấp nhiều lần so với dùng GUI.
Bài tiếp theo mình sẽ đi vào shell scripting, nơi bạn sẽ kết hợp tất cả những gì đã học thành các script tự động hóa hoàn chỉnh.
Có thể bạn cần xem thêm
- Đọc log hệ thống trên Linux VPS - journalctl và /var/log
- Quản lý file và thư mục trên Linux - Lệnh cơ bản cho VPS
- Troubleshooting VPS Linux - Cách xủ lý sự cố VPS phổ biến
- Logging, Monitoring và IDS trên Linux VPS - auditd, AIDE và Wazuh
- Shell Scripting cơ bản trên Linux - Tự động hóa tác vụ VPS
- Quản lý process trên Linux - ps, kill, htop cho VPS
Về tác giả
Trần Thắng
Chuyên gia tại AZDIGI với nhiều năm kinh nghiệm trong lĩnh vực web hosting và quản trị hệ thống.