Oct 282015
 

Thời kỳ mới đi làm tôi nghĩ cứ phải gõ thật nhiều cho quen cho nhớ nhưng lâu dần việc đó cho cảm giác thật nhàm chán. Hiện giờ, những gì tôi hay làm thường xuyên tôi thường lưu vào một nơi. Khi cần tôi chỉ việc lôi ra, sửa lại đôi chút. Kipalog là một nơi lưu trữ như vậy, thậm chí còn tốt hơn 😀

Bài viết này mục đích sẽ tập trung các đoạn script nhỏ ngắn. Mỗi script tôi sẽ đề cập đến tình huống sử dụng nó. Nếu bạn nào thấy có thể làm tốt hơn, tối ưu hơn, hoặc chỉ cần một cách khác hơn thì hãy để lại comment. Những comment của bạn rất giá trị với tôi. Bài viết này sẽ được update dài dài. Bạn nào thích có thể bổ sung thêm các script nữa nhé 😀

Tắt hàng loạt process theo pid

Tình huống: 
Tại sao tôi không dùng killall ? Vì một số ứng dụng tạo ra nhiều process có tên khác nhau ví dụ mysql chẳng hạn. Khi start mysql service thường nó duy trì hai process mysqld_safe và mysqld và một còn một lý do là đôi khi process bị treo, signal SIGTERM không thể tắt được process. Trong tình huống đó tôi phải dùng SIGKILL. Tuy không phải giải pháp tốt nhưng đôi khi vẫn phải dùng. Killall mặc định lại sử dụng signal SIGTERM.

Script:
ps -elf | grep <process_name> | grep -v "grep" | awk '{print $4}' | xargs kill -s SIGTERM

grep -v “grep” để loại bỏ chính process grep mà đang sử dụng trong script
$4 là vị trí của PID – cột thứ 4 trong output của ps -elf

UPDATE 1:
Bạn Lê Mạnh Cường có đóng góp một cách khác và cũng ít phải qua nhiều pipe hơn nên sẽ tối ưu hơn. Tôi cập nhật luôn vào bài viết chính:

ps -elf | awk '/<process_name>/ && !/awk/ {print $4}' | xargs -r kill -s SIGTERM

  • Số pipe sử dụng đã giảm hẳn
  • Câu lệnh cuối có sử dụng tham số -r của xargs để ép xargs sẽ không làm gì cả nếu input không có. (-r là một gnu extension)

Sử dụng nohup để duy trì process ngay khi cả shell bị đóng

Tình huống: 
Một số process chạy background làm nhiệm vụ lắng nghe sự kiện nào đó thì cần được duy trì liên tục. Khởi động một lần và chạy liên tục. Nghe có vẻ giống một service. Thực ra có thể viết một init script để khởi chạy các process kiểu như vậy. Nhưng có một cách đơn giản hơn. Đó là dùng nohup. Tôi không chắc là tốt hơn nhưng chỉ là đơn giản hơn.

Tiện ích này cho phép duy trì process chạy trong chế độ background ngay cả khi shell mà tôi gọi nohup bị đóng. Nó cũng cho phép ghi log.

Script:

nohup  /usr/bin/php long_running_process.php > /var/log/nohup_long_running_process.log &

Nếu tôi cần câu lệnh trên được chạy sau khi hệ thống reboot thì tôi chỉ cần đặt câu lệnh đó vào một script. Ví dụ: test_long_running_process.sh Sau đó trong file /etc/rc.local (File này luôn được gọi mỗi khi hệ thống khởi động) Tôi khai báo:
/full/path/to/test_long_running_process.sh

Duy trì một số lượng file nhất định trong một thư mục

Tình huống:
Để đảm bảo hệ thống phục hồi khi có thảm họa xảy ra, tôi cần thực hiện backup định kỳ. Các bản backup này ban đầu thì không đáng kể về dung lượng nhưng quá trình tích lũy sẽ ngốn sạch không gian lưu trữ. Để tránh tình huống này xảy ra, tôi cần phải định kỳ xóa bớt các bản backup đã quá cũ. Ở đây có ba yêu cầu cho nhiệm vụ này:

  • Duy trì một số lượng nhất định các bản backup. Chú ý các bản backup ở đây là thư mục
  • Các bản backup được giữ lại phải là mới nhất
  • Định kỳ theo dõi và xóa bỏ nếu số lượng bản backup vượt quá số quy định.

Điều kiện:
Các thư mục kết xuất từ quá trình backup không nên đặt ở dạng quá đặc biệt như thư mục ẩn, có dấu – ở đầu dòng hoặc có new line trong tên. Script không hỗ trợ xử lý các thư mục có tên kỳ dị như vậy.

Script:
Ở đây tôi duy trì ba bản backup mới nhất
Script backup_cleaner.sh

ls -td1 /data/backup/*/ | tail -n +4 | xargs -r rm -rfv 2> /var/log/backup_cleaner.log

-t để sort các thư mục con trong thư mục /data/backup theo thời gian. Những thư mục mới nhất sẽ xếp trên đầu.
-d để chỉ list các directory trong /data/backup/*/ vì các bản backup được kết xuất ở dạng thư mục.

Chú ý:
Để ls chỉ liệt kê được thư mục con của /data/backup. Bạn phải dùng dạng cú pháp

ls -td /data/backup/*/

Sử dụng

ls -td /data/backup/*

sẽ trả về cả file lẫn thư mục con.

-1 để các kết quả được sắp xếp theo từng dòng, mỗi dòng một kết quả (Script vẫn chạy đúng mục đích khi không có tham số -1 này)

Kết quả của câu lệnh ban đầu được chuyển vào tail để lấy ra các kết quả từ thứ tư trở đi rồi đẩy vào rm -rf để xóa. Như vậy sẽ luôn giữ lai ba kết quả đầu tiên, cũng là mới nhất.

Chú ý:
Vì kết quả cuối cùng của script là xóa thư mục nên trong lệnh đầu tiên tôi phải sử dụng đường dẫn tuyệt đối để câu lệnh rõ ràng nhất có thể.

Cuối cùng để hoạt động này được định kỳ thực hiện, tôi đẩy script này vào crontab
sudo crontab -e

*/1 * * * * /full/path/to/backup_cleaner.sh