0

Cách tạo script tự khởi động lại webserver Nodejs khi bị crash

Xin chào các bạn, lâu lắm mới có thời gian quay lại viết bài. Chủ yếu là do vừa mới tìm ra được một cách quá hay (mình nghĩ vậy, rất cool! 😀 ) để tạo script cho webserver tự khởi động lại khi bị crash. Mình cũng ghi chú thêm cách “chạy nền” script để không cần phải giữ session ssh. Đọc hết nhé!

Thí nghiệm

Sau đây mình sẽ có một thí nghiệm nhỏ.  Đó là tạo một app Nodejs xuất ra thông báo “tôi đang chạy” mỗi giây để mô phỏng việc app sẽ liên tục. Đơn giản thôi!

Thử chạy,  bạn sẽ thấy hiển thị như dưới:

Dĩ nhiên app sẽ chạy mãi không ngừng đâu, nên mình phải bấm Ctrl+C để thoát ra.

Bây giờ, chúng ta sẽ giả lập việc app bị crash sau khoảng 10 giây chạy vì nó quá… “mệt”. Mình thêm vào biến start để đếm thời gian và khi quá 10 giây thì ném ra lỗi “Run out of time”

Chạy script trên với Nodejs, bạn sẽ thấy hiển thị như bên dưới.

Yeah! Trong phần thí nghiệm này mình đã mô phỏng thành công việc chạy app Nodejs liên tục và việc app bị crash. Phần tiếp theo bên dưới, cùng xem cách Tự khởi động lại app khi bị crash như thế nào!

Tạo script tự khởi động lại webserver khi bị crash

Về bản chất thì một tiến trình không thể tự mình khởi động lại khi bị crash! Bởi vì đã để bị crash là coi như die. Chết rồi thì làm méo gì control được gì nữa, ngay cả việc có được chôn cất tử tế không đã là khó khăn thì nói gì đến tự mình hồi sinh. Do đó, ngay từ đầu ta cần dùng một tiến trình khác để khởi động webserver (hay là myapp.js như thí nghiệm ở trên) cũng như theo dõi và xử lý hậu quả sau đó khi bị crash.

Có rất nhiều ứng dụng cho phép làm được việc đó, nhưng mình giới thiệu ở đây một cách thuần tự nhiên nhất, không cần cài app nào cả, đó là dùng shell script:

Tạo script self_restart.sh với nội dụng như trên. sau đó cho phép script có thể thực thi lệnh:

Từ bây giờ, khi chạy lệnh ./self_restart.sh, con shell này sẽ chạy mãi cho đến khi script tự kết thúc với exit code 0 – nghĩa là không bị lỗi gì cả. Còn nếu xảy ra lỗi, myscript() sẽ return exit code >= 1 và vòng lặp lại được tiếp tục, do đó myscript() sẽ được gọi lần nữa. Tada!!! myapp.js đã được triệu hồi.

Giải thích một chút về con shell này nhé.

  • myscript() là khai báo hàm trong bash shell. Trong hàm này, bạn có thể gọi bất cứ lệnh nào để start server, ứng dụng mà bạn cần nó tự khởi động khi crash.
  • until ....; do đây là một vòng lặp trong bash shell, cho phép thực hiện mãi cho đến khi nào đúng thì thôi. Có thể coi nó là một cách viết khác của while [ ! myscript]; do vậy đó.
  • Tại sao lại sleep 1 cái này là khoảng thời gian backup thôi! Sau khi app bị crash, dành ra 1 ít thời gian trống để hệ điều hành dọn dẹp lại bộ nhớ, I/O,… rồi thì hãy khởi động lại app.

Tự chạy khi khởi động server

Dùng crontab như sau:

@reboot sẽ chạy khi hệ điều hành bị khởi động lại.

Chạy nền script

Để tránh phải giữ session ssh, không cần giữ cửa sổ command line

Bài này mình cũng nói thêm 1 vấn đề mà rất rất nhiều bạn hay gặp phải khi mới dùng Linux nói chung. Đó là khi các bạn chạy app trên dòng lệnh thông qua ssh, đến khi thoát ssh thì cũng làm tắt luôn tiếng trình đang chạy.

Sở dĩ bị chuyện này là do, mỗi tiến trình chạy trên bash shell (command-line) nào thì sẽ bind vào Input/Output của bash shell đó. SSH cũng là một dạng remote shell cho nên nó cũng bị binding vào input/output của tiến trình đang chạy. Nếu bạn tắt ssh đi, đồng nghĩa với việc ngắt I/O của tiến trình và tiến trình sẽ crash và dừng luôn!

Vậy làm sao để tắt terminal, tắt command line, tắt ssh mà app command line vẫn chạy? Đó là thay vì bind output vào cmd thì ta direct output qua một luồng khác. Thực hiện đơn giản như sau:

Trong ví dụ trên, mình đã redirect output vào file .log thay vì xuất lên terminal trên màn hình. Sau khi chạy lệnh trên mình có thể yên tâm đóng terminal, command line mà không sợ app bị tắt mất. Không tin? Chạy lệnh tail -fn 10 self_restart.log bạn sẽ thấy nội dung file liên tục được cập nhật!

Bonus

Ờ, nó chạy ngầm giờ tui tắt không được đây này!

Ok ok, tìm xem Process ID nó bao nhiều rồi kill thôi!

Kết luận

Với cách làm tạo self_restart.sh như trên, bạn không chỉ áp dụng được cho Nodejs mà có thể áp dụng cho mọi thứ chạy trên dòng lệnh: python, php, js, go, …. miễn là bạn setup hàm myscript() hợp lý.

  • Sử dụng until ... ; do để restart command
  • Dùng @reboot trong crontab để run khi restart
  • dùng nohup ... > ...log & để chạy nền

Hehe, nếu bạn gặp khó khăn gì, comment bên dưới hoặc trên Facebook fan page, mình sẽ cố gắng giúp đỡ. Thân!

Hoàng Tựa

Yêu thích lập trình web và tạo ra những thứ đẹp đẽ.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.