Lệnh Linux mọi dev cần biết

1. Tổng quan

Dev nào cũng từng SSH vào server, mở terminal debug hay deploy một con app, rồi loay hoay tìm lệnh đúng. Bài này tổng hợp các lệnh Linux dùng nhiều nhất trong công việc hàng ngày: quản lý file, tìm kiếm, xử lý text, theo dõi process, kiểm tra mạng, xem log. Đọc xong, bạn có bộ lệnh “sống còn” để debug nhanh mà không cần Google lại mỗi lần.

Mình dùng bash trên Ubuntu/Debian làm ví dụ chính, các lệnh này hầu như giống nhau trên mọi distro.

2. Thao tác file và thư mục cơ bản

mkdir -p ~/projects/order-service/src/main/java
cd ~/projects/order-service
touch application.properties
ls -la
  • mkdir -p tạo cả cây thư mục lồng nhau, không báo lỗi nếu thư mục đã tồn tại.
  • touch tạo file trống (hoặc update timestamp nếu đã có).
  • ls -la list tất cả file (kể cả file ẩn .env, .git) kèm quyền, owner, size.
drwxr-xr-x  3 nonla nonla 4096 Oct  5 10:00 .
-rw-r--r--  1 nonla nonla    0 Oct  5 10:00 application.properties

Một số lệnh di chuyển/xóa cần cẩn thận:

cp -r src/ src-backup/     # copy đệ quy thư mục
mv OrderService.java OrderServiceImpl.java   # rename hoặc di chuyển
rm -rf target/            # xóa đệ quy, không hỏi lại

Lưu ý: rm -rf không có thùng rác, xóa là mất. Luôn kiểm tra đường dẫn bằng pwd trước khi chạy, đặc biệt khi copy-paste lệnh từ nơi khác.

3. Tìm kiếm với find và grep

3.1. find — tìm file theo điều kiện

find . -name "*.java" -newer pom.xml

Lệnh này tìm tất cả file .java được sửa đổi sau pom.xml — hữu ích khi muốn biết file nào vừa đổi trước khi commit.

find . -type f -size +10M

Tìm file lớn hơn 10MB, thường dùng để dọn log hoặc build artifact chiếm dung lượng.

3.2. grep — tìm nội dung trong file

grep -rn "PaymentService" --include="*.java" src/
  • -r tìm đệ quy trong thư mục con.
  • -n in kèm số dòng.
  • --include giới hạn chỉ file .java, tránh lục cả target/.
src/main/java/com/nonla/OrderController.java:15:    private final PaymentService paymentService;

Kết hợp grep với find qua pipe khi cần lọc phức tạp hơn:

find . -name "*.log" | xargs grep -l "OutOfMemoryError"

xargs truyền list file từ find sang grep -l (chỉ in tên file chứa pattern, không in nội dung).

4. Xử lý text với awk, sed, cut

Đây là nhóm lệnh “ăn log” — cực mạnh khi bạn cần bóc dữ liệu từ output dài dòng.

cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
  • awk '{print $1}' lấy cột đầu tiên (thường là IP) mỗi dòng log.
  • sort | uniq -c nhóm và đếm số lần xuất hiện.
  • sort -rn sắp giảm dần theo số, head -5 lấy top 5.
    152 192.168.1.10
     98 10.0.0.5
     47 172.16.0.3

Đây là cách nhanh nhất để tìm IP gọi request nhiều nhất mà không cần viết script.

sed dùng để thay thế text trực tiếp trong file:

sed -i 's/spring.profiles.active=dev/spring.profiles.active=prod/' application.properties

-i sửa trực tiếp file (in-place). Nếu muốn an toàn hơn, dùng sed -i.bak '...' để tự tạo file backup .bak.

cut tách cột theo delimiter, nhẹ hơn awk khi chỉ cần một cột đơn giản:

cat /etc/passwd | cut -d: -f1 | head -3

5. Theo dõi tiến trình và tài nguyên hệ thống

ps aux | grep java

In toàn bộ process, lọc dòng chứa java — cách nhanh để biết app Spring Boot của bạn có đang chạy và PID là bao nhiêu.

nonla    12345  2.1  5.3 2345678 432100 ?      Sl   10:00   0:15 java -jar order-service.jar

Cột thứ 2 là PID. Dùng PID này để kill hoặc xem chi tiết:

kill -15 12345     # gửi SIGTERM, cho app graceful shutdown
kill -9 12345       # force kill, chỉ dùng khi -15 không ăn

Lưu ý: kill -9 không cho app chạy shutdown hook (ví dụ đóng connection pool, flush log). Luôn thử -15 trước.

Xem tài nguyên theo thời gian thực:

top -o %MEM

-o %MEM sắp process theo RAM dùng nhiều nhất — hữu ích khi nghi ngờ memory leak. Muốn giao diện đẹp hơn thì cài htop.

Kiểm tra disk:

df -h
du -sh /var/log/*

df -h xem dung lượng từng partition (human-readable). du -sh xem từng thư mục con trong /var/log chiếm bao nhiêu — rất cần khi server báo “no space left on device”.

6. Kiểm tra mạng và port

ss -tulnp | grep 8080
  • ss thay thế netstat cũ, nhanh hơn.
  • -t TCP, -u UDP, -l listening, -n numeric (không resolve DNS), -p kèm process.
tcp   LISTEN  0  128  0.0.0.0:8080  0.0.0.0:*  users:(("java",pid=12345,fd=45))

Biết ngay port 8080 đang bị process Java PID 12345 chiếm — rất hữu ích khi gặp lỗi Address already in use.

Test API nhanh bằng curl:

curl -s -X POST http://localhost:8080/api/orders \
  -H "Content-Type: application/json" \
  -d '{"customerId":1,"amount":99.5}'

-s silent (ẩn progress bar), -X POST chọn method, -d body JSON. Thêm -i nếu muốn xem cả response headers.

Lệnh lsof dùng khi cần biết chính xác file/socket nào process đang mở:

lsof -i :8080

7. Quyền truy cập file

chmod +x deploy.sh
chown nonla:nonla application.properties
chmod 640 .env
  • chmod +x cho phép thực thi script.
  • chown user:group đổi owner — thường cần sudo khi file thuộc user khác.
  • chmod 640 nghĩa là owner đọc/viết (6), group chỉ đọc (4), người khác không có quyền (0) — chuẩn cho file secret như .env.
-rw-r----- 1 nonla nonla 128 Oct  5 10:00 .env

Lưu ý: đừng bao giờ chmod 777 cho production. Đó là cách nhanh nhất để mọi user trên máy đọc/sửa file nhạy cảm của bạn.

8. Nén và giải nén

tar -czvf order-service.tar.gz order-service/
tar -xzvf order-service.tar.gz -C /opt/apps/
  • -c tạo archive, -x giải nén, -z dùng gzip, -v verbose, -f chỉ định tên file.
  • -C khi giải nén chỉ định thư mục đích thay vì giải vào thư mục hiện tại.

Khi deploy, kết hợp với scp hoặc rsync để đẩy file lên server:

scp order-service.tar.gz user@10.0.0.5:/opt/apps/
rsync -avz --progress target/*.jar user@10.0.0.5:/opt/apps/

rsync chỉ truyền phần dữ liệu thay đổi (delta transfer), nhanh hơn scp nhiều khi update file lớn nhiều lần.

9. Xem log real-time

tail -f /var/log/order-service/app.log

-f (follow) giữ terminal mở và in thêm dòng mới ngay khi file được ghi tiếp — lệnh bắt buộc phải biết khi debug production.

Lọc log theo pattern khi tail:

tail -f app.log | grep --line-buffered "ERROR"

--line-buffered cần thiết vì grep mặc định buffer theo block, nếu không có cờ này output có thể bị trễ khi pipe với tail -f.

Nếu app chạy dưới systemd, dùng journalctl thay vì tìm file log thủ công:

journalctl -u order-service -f --since "10 minutes ago"

-u chỉ định service unit, -f follow, --since giới hạn thời gian — tránh phải đọc cả triệu dòng log cũ.

10. Chạy lệnh Linux từ Java

Nhiều lúc bạn cần gọi lệnh shell trực tiếp từ code Java, ví dụ kiểm tra disk trước khi ghi file lớn:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;

public class ShellRunner {

    public static String run(List<String> command) throws Exception {
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.redirectErrorStream(true);
        Process process = builder.start();

        try (BufferedReader reader =
                new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String output = reader.lines().reduce("", (a, b) -> a + b + "\n");
            process.waitFor();
            return output;
        }
    }
}
  • ProcessBuilder nhận list argument (không phải một chuỗi lệnh ghép tay, tránh shell injection).
  • redirectErrorStream(true) gộp stderr vào stdout để đọc một luồng duy nhất.
  • process.waitFor() chặn thread hiện tại tới khi process con kết thúc.

Test với JUnit 5 + AssertJ:

import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;

class ShellRunnerTest {

    @Test
    void shouldReturnCurrentDirectoryListing() throws Exception {
        String output = ShellRunner.run(List.of("ls", "-la"));

        assertThat(output).contains("total");
    }
}

Test này chạy ls -la thật trên hệ thống và kiểm tra output có chứa dòng total (dòng đầu tiên ls -la luôn in ra tổng số block) — xác nhận ProcessBuilder thực sự gọi được shell command.

Lưu ý: gọi shell command từ Java production code là con dao hai lưỡi — dễ phụ thuộc OS, khó test, và nguy cơ injection nếu argument lấy từ input người dùng. Chỉ dùng cho tool nội bộ hoặc script vận hành, tránh dùng cho logic nghiệp vụ chính.

11. Lỗi hay gặp

  • Chạy rm -rf với biến môi trường rỗng, ví dụ rm -rf $DIR/* khi $DIR chưa set — xóa nhầm thư mục gốc. Luôn dùng set -u trong script hoặc kiểm tra biến trước.
  • Quên sudo khi cần quyền root, dẫn đến lỗi Permission denied mơ hồ — kiểm tra bằng ls -la trước khi đổ lỗi cho app.
  • Dùng kill -9 theo thói quen, khiến app Spring Boot không kịp đóng connection pool, gây leak trên database.
  • Pipe grep sau tail -f mà quên --line-buffered, tưởng log không chạy nhưng thực ra bị buffer.
  • Chạy chmod 777 để “cho nhanh qua lỗi quyền” — tạo lỗ hổng bảo mật, đặc biệt nguy hiểm với file .env hay key SSH.

12. Kết luận

Những lệnh trong bài — find, grep, awk/sed, ps/kill, ss/curl, tar, tail -f, journalctl — là bộ công cụ tối thiểu để bạn tự debug mà không phải chờ team DevOps. Thành thạo chúng không có nghĩa phải nhớ hết flag, chỉ cần biết lệnh nào giải quyết vấn đề gì và tra man khi cần chi tiết. Terminal vẫn là công cụ debug nhanh nhất, kể cả khi bạn đã có đủ Grafana, Kibana hay APM tool xung quanh.

linuxdevopsbashproductivityjava