Thursday, November 21, 2024

Một số ví dụ cách viết script tìm kiếm và nén file

-

1. Lặp các thư mục cũ hơn 2 tháng và nén chúng lại theo từng tháng.

Giả sử mình có thư mục với thông tin file và thư mục con như sau:

$ ls -al
total 24
drwxr-xr-x 13 root root  416 Jun  5 14:37 .
drwx------ 21 root root  672 Jun  4 13:47 ..
drwxr-xr-x 13 root root  416 Jun  5 12:11 .git
-rw-r--r--  1 root root   38 May 18 17:37 .gitignore
drwxr-xr-x  4 root root  128 Jun  5 12:43 compressed
-rw-r--r--  1 root root 1967 May 30 09:40 inventory.ini
-rw-r--r--  1 root root  169 Jun  4 09:05 node.sh
-rw-r--r--  1 root root 1490 May 30 04:22 playbook.yml
-rwxr--r--  1 root root  377 May 20 17:20 push.sh
drwxr-xr-x  9 root root  288 May 30 14:02 roles
drwxr-xr-x 15 root root  480 Jun  5 12:11 roles1
drwxr-xr-x 15 root root  480 Jun  5 12:15 roles2
-rw-r--r--  1 root root 2983 Jun  5 14:12 sh.sh

Với mong muốn mình sẽ nén các thư mục cũ hơn 2 tháng tại thư mục cha (nếu là file tại thư mục cha thì bỏ qua).

Trường hợp này thường xảy ra khi các bạn ghi logs thành các thư mục con, mỗi thư mục con sẽ chứa các file logs tương ứng với tháng đó.

Nếu giữ toàn bộ các thư mục logs cùng với các file logs trong thư mục đó trong thời gian dài sẽ dẫn đến chiếm dung lượng không đáng phải có. Kịch bản là chúng ta sẽ nén các thư mục logs cũ hơn 2 tháng (tức là chỉ giữ lại thư mục logs 2 tháng gần nhất để chúng ta xem khi cần thiết và các thư mục logs cũ hơn sẽ nén lại để tránh tốn dung lượng lưu trữ).

Mình sẽ dùng script dưới để giải quyết vấn đề này.

#!/bin/bash
# Tìm và lấy danh sách các thư mục
directories=$(find . -maxdepth 1 -type d -mtime +60 ! -name '.*' ! -name '.git_*' -exec ls -ld --time-style=long-iso {} + | awk '{split($6, a, "-"); gsub("/$", "", $NF); printf("%s\n", substr($NF, 3), a[3], a[2], a[1])}')

# Kiểm tra nếu danh sách thư mục rỗng
if [ -z "$directories" ]; then
    echo "Không có thư mục nào tồn tại."
    exit 1
fi

# Lặp qua từng thư mục và nén chúng
for dir in $directories; do
    # Lấy tên thư mục
    dirname=$(basename "$dir")
    
    # Tạo tệp tin nén
    tar -czvf "$dirname.tar.gz" "$dir"
    
    echo "Đã nén thư mục $dir thành $dirname.tar.gz"
done

Giải thích đoạn lệnh lấy giá trị directories:

find . -maxdepth 1 -type d -mtime +60 ! -name '.*' ! -name '.git_*' -exec ls -ld --time-style=long-iso {} + | awk '{split($6, a, "-"); gsub("/$", "", $NF); printf("%s\n", substr($NF, 3), a[3], a[2], a[1])}'

Đoạn lệnh trên có mục đích tìm và lưu trữ danh sách các thư mục cùng cấp với tệp tin thực thi. Dưới đây là giải thích từng phần của lệnh:

  • find .: Tìm kiếm trong thư mục hiện tại và các thư mục con.
  • -maxdepth 1: Chỉ tìm kiếm trong thư mục hiện tại, không tìm kiếm trong các thư mục con.
  • -type d: Chỉ tìm kiếm các thư mục (directories).
  • -mtime +60: Tìm kiếm các thư mục có thời gian sửa đổi (modification time) lớn hơn 60 ngày. Nếu muốn thời gian tính từ thời điểm hiện tại thì bạn dùng tham số -1, với -2 là các thư mục cách thời điểm hiện tại 2 ngày.
  • ! -name '.*': Loại trừ các thư mục ẩn (bắt đầu bằng dấu chấm).
  • ! -name '.git_*': Loại trừ các thư mục bắt đầu bằng .git_.
  • -exec ls -ld --time-style=long-iso {} +: Thực thi lệnh ls -ld --time-style=long-iso trên danh sách các thư mục tìm được.
  • awk '{split($6, a, "-"); gsub("/$", "", $NF); printf("%s\n", substr($NF, 3), a[3], a[2], a[1])}': Sử dụng awk để xử lý đầu ra từ lệnh ls và hiển thị tên của các thư mục.

Kết quả của lệnh này sẽ là danh sách các thư mục cùng cấp với tệp tin thực thi, thỏa mãn các điều kiện được chỉ định (không phải thư mục ẩn, không phải thư mục .git_*, và có thời gian sửa đổi trong vòng 1 ngày), được hiển thị theo định dạng tên_thư_mục.

Đoạn tiếp theo mình kiểm tra nếu danh sách thư mục rỗng và in ra màn hình cho người quản trị biết không có thư mục tồn tại.

if [ -z "$directories" ]; then
    echo "Không có thư mục nào tồn tại."
    exit 1
fi

Đoạn cuối mình duyệt tất cả các thư mục đã lấy được ở biến directories và nén chúng lại tại thư mục gốc.

for dir in $directories; do
    dirname=$(basename "$dir")
    tar -czvf "$dirname.tar.gz" "$dir"
    echo "Đã nén thư mục $dir thành $dirname.tar.gz"
done

Phần output khi chạy script.

compressed/
compressed/thang_5.tar.gz
compressed/thang_6.tar.gz
Đã nén thư mục compressed thành compressed.tar.gz
roles1/
roles1/[NES Nintendo] 10 yard fight.nes
roles1/[NES Nintendo] 1942.nes
roles1/[NES Nintendo] 1943.nes
roles1/[NES Nintendo] 1944.nes
roles1/[NES Nintendo] 1999.NES
roles1/[NES Nintendo] 720.nes
roles1/[NES Nintendo] 8 eyes.nes
roles1/[NES Nintendo] A Nightmare On Elm Street.nes
roles1/[NES Nintendo] Abadox.nes
roles1/[NES Nintendo] Action52(Unl).nes
roles1/[NES Nintendo] Addams Family - Pugsley's Scavenger Hunt, The (U).nes
roles1/[NES Nintendo] Addams family.nes
roles1/sh.sh
Đã nén thư mục roles1 thành roles1.tar.gz
roles2/
roles2/[NES Nintendo] 10 yard fight.nes
roles2/[NES Nintendo] 1942.nes
roles2/[NES Nintendo] 1943.nes
roles2/[NES Nintendo] 1944.nes
roles2/[NES Nintendo] 1999.NES
roles2/[NES Nintendo] 720.nes
roles2/[NES Nintendo] 8 eyes.nes
roles2/[NES Nintendo] A Nightmare On Elm Street.nes
roles2/[NES Nintendo] Abadox.nes
roles2/[NES Nintendo] Action52(Unl).nes
roles2/[NES Nintendo] Addams Family - Pugsley's Scavenger Hunt, The (U).nes
roles2/[NES Nintendo] Addams family.nes
roles2/sh.sh
Đã nén thư mục roles2 thành roles2.tar.gz

Kết quả bạn sẽ có 3 file nén roles1.tar.gz, roles2.tar.gz và compressed.tar.gz vì nó có trong danh sách biến directories, riêng roles cũng là một thư mục nhưng nó không nằm trong danh sách directories nên nó sẽ không được nén.

$ ls -al
total 7132
drwxr-xr-x 16 root root     512 Jun  5 14:50 ./
drwx------ 21 root root     672 Jun  4 13:47 ../
drwxr-xr-x 13 root root     416 Jun  5 12:11 .git/
-rw-r--r--  1 root root      38 May 18 17:37 .gitignore
drwxr-xr-x  4 root root     128 Jun  5 12:43 compressed/
-rw-r--r--  1 root root 3647900 Jun  5 14:50 compressed.tar.gz
-rw-r--r--  1 root root    1967 May 30 09:40 inventory.ini
-rw-r--r--  1 root root     169 Jun  4 09:05 node.sh
-rw-r--r--  1 root root    1490 May 30 04:22 playbook.yml
-rwxr--r--  1 root root     377 May 20 17:20 push.sh*
drwxr-xr-x  9 root root     288 May 30 14:02 roles/
drwxr-xr-x 15 root root     480 Jun  5 12:11 roles1/
-rw-r--r--  1 root root 1812171 Jun  5 14:50 roles1.tar.gz
drwxr-xr-x 15 root root     480 Jun  5 12:15 roles2/
-rw-r--r--  1 root root 1812184 Jun  5 14:50 roles2.tar.gz
-rw-r--r--  1 root root    2983 Jun  5 14:50 sh.sh

2. Lặp thư mục qua từng tháng và nén các thư mục trong cùng một tháng.

Kịch bản dưới đây sẽ giúp các bạn lọc các thư mục con ở trong thư mục cha được tạo ra trong cùng một tháng và gom chúng lại thành các file nén theo thời gian bạn mong muốn.

Dưới đây là full đoạn code.

# Lấy danh sách các thư mục
directories=$(find . -maxdepth 1 -type d -mtime -10 ! -name '.*' ! -name '.git_*' ! -name 'compressed' -exec ls -ld --time-style=long-iso {} + | awk '{split($6, a, "-"); gsub("/$", "", $NF); printf("%s_%s%s%s\n", substr($NF, 3), a[2], a[3], a[1])}')

# Tạo thư mục lưu trữ nén
mkdir -p compressed

# Lặp qua từng tháng và nén các thư mục trong cùng một tháng
for month in {1..12}; do
    # Gộp các thư mục theo tháng
    month_directories=$(echo $(echo "$directories" | grep "_$(printf "%02d" $month)") | cut -d_ -f1)

    # Kiểm tra nếu có thư mục trong tháng
    if [ -n "$month_directories" ]; then
        echo "Tháng $month:"
        echo "$month_directories"

        # Tạo tên file nén
        archive_name="thang_$month.tar.gz"

        # Nén các thư mục vào file nén
        tar -czvf "compressed/$archive_name" $month_directories

        echo "Đã nén các thư mục trong tháng $month thành file $archive_name"
    fi
done

# Kiểm tra nếu không có thư mục nào tồn tại
if [ ! -d "compressed" ]; then
    echo "Không có thư mục nào tồn tại."
    exit 1
fi

Đoạn lệnh lấy giá trị directories mình đã giải thích ở trên nên mình không giải thích lại. Ý nghĩa các đoạn code mình cũng đã giải thích trong phần comment nên mình cũng không giải thích nữa nhé.

Đây là phần output khi chạy script.

Tháng 5:
roles
roles/
roles/cmc-vz-backup-01/
roles/cmc-vz-backup-01/handlers/
roles/cmc-vz-backup-01/handlers/example.yml
roles/cmc-vz-backup-01/handlers/tcp-status.sh
roles/cmc-vz-backup-01/tasks/
roles/cmc-vz-backup-01/tasks/main.yml
roles/cmc-vz-backup-01/vars/
roles/cmc-vz-backup-01/vars/main.yml
roles/cmc-vz-backup-02/
roles/cmc-vz-backup-02/handlers/
roles/cmc-vz-backup-02/handlers/example.yml
roles/cmc-vz-backup-02/handlers/tcp-status.sh
roles/cmc-vz-backup-02/tasks/
roles/cmc-vz-backup-02/tasks/main.yml
roles/cmc-vz-backup-02/vars/
roles/cmc-vz-backup-02/vars/main.yml
roles/cmc-vz-storage-01/
roles/cmc-vz-storage-01/handlers/
roles/cmc-vz-storage-01/handlers/example.yml
roles/cmc-vz-storage-01/handlers/tcp-status.sh
roles/cmc-vz-storage-01/tasks/
roles/cmc-vz-storage-01/tasks/main.yml
roles/cmc-vz-storage-01/vars/
roles/cmc-vz-storage-01/vars/main.yml
roles/cmc-vz-storage-02/
roles/cmc-vz-storage-02/handlers/
roles/cmc-vz-storage-02/handlers/example.yml
roles/cmc-vz-storage-02/handlers/tcp-status.sh
roles/cmc-vz-storage-02/tasks/
roles/cmc-vz-storage-02/tasks/main.yml
roles/cmc-vz-storage-02/vars/
roles/cmc-vz-storage-02/vars/main.yml
roles/cmc-vz-virtualization/
roles/cmc-vz-virtualization/handlers/
roles/cmc-vz-virtualization/handlers/vz-network-config.sh
roles/cmc-vz-virtualization/keypair/
roles/cmc-vz-virtualization/keypair/authorized_keys
roles/cmc-vz-virtualization/keypair/id_rsa
roles/cmc-vz-virtualization/tasks/
roles/cmc-vz-virtualization/tasks/disable_firewalld.yml
roles/cmc-vz-virtualization/tasks/keypair.yml
roles/cmc-vz-virtualization/tasks/login_config.yml
roles/cmc-vz-virtualization/tasks/main.yml
roles/cmc-vz-virtualization/tasks/network_config.yml
roles/cmc-vz-virtualization/tasks/packages_install.yml
roles/cmc-vz-virtualization/tasks/ssh_block.yml
roles/cmc-vz-virtualization/tasks/va_agent.yml
roles/cmc-vz-virtualization/vars/
roles/cmc-vz-virtualization/vars/main.yml
roles/cmc-vz-wan/
roles/cmc-vz-wan/handlers/
roles/cmc-vz-wan/handlers/example.yml
roles/cmc-vz-wan/handlers/tcp-status.sh
roles/cmc-vz-wan/tasks/
roles/cmc-vz-wan/tasks/main.yml
roles/cmc-vz-wan/vars/
roles/cmc-vz-wan/vars/main.yml
roles/ods-vz-virtualization/
roles/ods-vz-virtualization/handlers/
roles/ods-vz-virtualization/handlers/vz-network-config.sh
roles/ods-vz-virtualization/keypair/
roles/ods-vz-virtualization/keypair/authorized_keys
roles/ods-vz-virtualization/keypair/id_rsa
roles/ods-vz-virtualization/tasks/
roles/ods-vz-virtualization/tasks/disable_firewalld.yml
roles/ods-vz-virtualization/tasks/hostname_config.yml
roles/ods-vz-virtualization/tasks/keypair.yml
roles/ods-vz-virtualization/tasks/login_config.yml
roles/ods-vz-virtualization/tasks/main.yml
roles/ods-vz-virtualization/tasks/network_config.yml
roles/ods-vz-virtualization/tasks/packages_install.yml
roles/ods-vz-virtualization/tasks/ssh_block.yml
roles/ods-vz-virtualization/tasks/va_agent.yml
roles/ods-vz-virtualization/vars/
roles/ods-vz-virtualization/vars/main.yml
Đã nén các thư mục trong tháng 5 thành file thang_5.tar.gz
Tháng 6:
roles1
roles1/
roles1/[NES Nintendo] 10 yard fight.nes
roles1/[NES Nintendo] 1942.nes
roles1/[NES Nintendo] 1943.nes
roles1/[NES Nintendo] 1944.nes
roles1/[NES Nintendo] 1999.NES
roles1/[NES Nintendo] 720.nes
roles1/[NES Nintendo] 8 eyes.nes
roles1/[NES Nintendo] A Nightmare On Elm Street.nes
roles1/[NES Nintendo] Abadox.nes
roles1/[NES Nintendo] Action52(Unl).nes
roles1/[NES Nintendo] Addams Family - Pugsley's Scavenger Hunt, The (U).nes
roles1/[NES Nintendo] Addams family.nes
roles1/sh.sh
Đã nén các thư mục trong tháng 6 thành file thang_6.tar.gz

Và kết quả bạn sẽ có 2 file nén như dưới.

$ ls -al compressed/
total 2128
drwxr-xr-x  4 root root     128 Jun  5 15:02 .
drwxr-xr-x 13 root root     416 Jun  5 14:55 ..
-rw-r--r--  1 root root   16200 Jun  5 15:07 thang_5.tar.gz
-rw-r--r--  1 root root 1812171 Jun  5 15:07 thang_6.tar.gz

Lưu ý: Đoạn code mình chỉ hướng dẫn các bạn logic để giải quyết vấn đề, để cho hoàn hảo bạn cần cập nhật thêm tính năng cho code. Đoạn code mình để output để các bạn dễ theo dõi, thực tế bạn hãy ngắt phần output để cho hệ thống nhẹ hơn.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories