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ệnhls -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ụngawk
để xử lý đầu ra từ lệnhls
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.