Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Dùng daemontools để chạy chương trình trong chế độ ngầm khi Linux khởi động
Bài viết này đề cập 2 đề tài:
- Chạy chương trình trong chế độ ngầm (daemon/service)
- Khởi động chương trình khi Linux khởi động
Thường ta giải quyết đề tài 1 một cách giản dị bằng cách chạy lệnh nohup <chương trình> &
, giải quyết đề tài 2 bằng cách tùy distro mà cấu hình inittab hoặc ttys hoặc init.d hoặc rc.local. Tuy nhiên 2 cách trên có vấn đề:
- Nếu chương trình bị bug gì đó, đang chạy bị chết thì làm sao chạy nó lại?
- Mỗi distro có cách cấu hình khác nhau, đang dùng CentOS mà chuyển sang Ubuntu thì phải cấu hình lại rất phiền (không portable). Cấu hình khó. Đang chạy mà muốn tắt đi cũng khó.
Bài viết này giới thiệu công cụ daemontools rất được ưa chuộng, giúp giải quyết cả 2 một cách đẹp mắt.
Cài đặt
Ta theo hướng dẫn ở trang chủ của daemontools. Có thể cần thêm cái patch theo hướng dẫn ở đây. daemontools bắt phải theo cấu trúc thư mục như sau:
- /package/admin/daemontools: Symlink, trỏ đến thư mục daemontools-0.76
- /package/admin/daemontools-0.76: Thư mục chứa chương trình daemontools
- /command: Thư mục chứa symlink các lệnh, trỏ đến các lệnh trong thư mục /package/admin/daemontools/command
- /usr/local/bin: Thư mục chứa symlink các lệnh, trỏ đến các symlink trong thư mục /command
- /service: Mỗi thư mục con trong này ứng với một service của ta, ta sẽ chỉ làm việc với thư mục này, những thư mục khác ở trên không cần quan tâm. Sau khi cài theo hướng dẫn trên, daemontools sẽ tự động cấu hình để khi Linux khởi động, svscanboot sẽ được tự động chạy. Nó sẽ kiểm tra các thư mục con của /service rồi xử lí cần thiết.
$ ll /package/admin/
daemontools -> daemontools-0.76
daemontools-0.76
$ ls -l /package/admin/daemontools-0.76/
command
compile
package
src
$ ls -l /command/
envdir -> /package/admin/daemontools/command/envdir
envuidgid -> /package/admin/daemontools/command/envuidgid
fghack -> /package/admin/daemontools/command/fghack
multilog -> /package/admin/daemontools/command/multilog
pgrphack -> /package/admin/daemontools/command/pgrphack
readproctitle -> /package/admin/daemontools/command/readproctitle
setlock -> /package/admin/daemontools/command/setlock
setuidgid -> /package/admin/daemontools/command/setuidgid
softlimit -> /package/admin/daemontools/command/softlimit
supervise -> /package/admin/daemontools/command/supervise
svc -> /package/admin/daemontools/command/svc
svok -> /package/admin/daemontools/command/svok
svscan -> /package/admin/daemontools/command/svscan
svscanboot -> /package/admin/daemontools/command/svscanboot
svstat -> /package/admin/daemontools/command/svstat
tai64n -> /package/admin/daemontools/command/tai64n
tai64nlocal -> /package/admin/daemontools/command/tai64nlocal
$ ls -l /usr/local/bin/
envdir -> /command/envdir
envuidgid -> /command/envuidgid
fghack -> /command/fghack
multilog -> /command/multilog
pgrphack -> /command/pgrphack
readproctitle -> /command/readproctitle
setlock -> /command/setlock
setuidgid -> /command/setuidgid
softlimit -> /command/softlimit
supervise -> /command/supervise
svc -> /command/svc
svok -> /command/svok
svscan -> /command/svscan
svscanboot -> /command/svscanboot
svstat -> /command/svstat
tai64n -> /command/tai64n
tai64nlocal -> /command/tai64nlocal
Cấu hình service
Giả sử ta có script /opt/myapp/bin/runner.sh nội dung như sau:
#!/bin/sh
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT_DIR"
JAVA_OPTS='-Xms512m -Xmx1024m -XX:MaxPermSize=128m -server -Djava.awt.headless=true'
CLASS_PATH="$ROOT_DIR/lib/*"
exec java $JAVA_OPTS -cp $CLASS_PATH $@
Bạn chỉ cần hiểu là script này dùng để chạy hàm main trong class Java nào đó. Ví dụ muốn chạy thử hàm main trong class myapp.Main, ta sẽ chạy thủ công lệnh: runner.sh myapp.Main
.
Để lệnh /opt/myapp/bin/runner.sh myapp.Main
được chạy bằng user me khi Linux khởi động, theo qui định của daemontools ta tạo thư mục /service/myapp. Trong đó ta tạo tập tin run nội dung như sau:
#!/bin/sh
exec setuidgid me /opt/myapp/bin/runner.sh myapp.Main
Nếu không có lệnh setuidgid của daemontools thì runner.sh sẽ được chạy bằng user root.
Set quyền thực thi:
$ sudo chmod +x /service/myapp/me
Trong vòng 5 giây sau khi set quyền, daemontools sẽ tự động chạy tập tin trên. Nếu process Java chết thì daemontools sẽ tự động chạy lại tập tin trên.
Để điều khiển service, dùng lệnh svc:
- Gửi signal TERMINATE đến process Java để bảo nó tắt:
$ sudo svc -t /service/myapp
. Sau khi tắt daemontools sẽ tự động khởi động lại service, do đó thao tác này tương đương với restart service. - Tắt hẳn service:
$ sudo svc -d /service/myapp
. - Sau khi tắt, muốn bật lại:
$ sudo svc -u /service/myapp
.
Chú ý
Để điều khiển service, lệnh svc sẽ gửi các signal đến process của service. Do đó để ý ở trên có 2 cái exec, mục đích là để /bin/sh thay thế process của nó bằng process của chương trình Java. Nếu bỏ exec đi thì svc không còn điều khiển chính xác được nữa!
daemontools qui định process của service phải chạy ở chế độ foreground bình thường. Nếu không, sẽ phải dùng thêm lệnh fghack nó cung cấp.
Trên đây là cách dùng daemontools đơn giản, đáp ứng được hầu hết nhu cầu thường gặp. Nếu có thêm nhu cầu, ví dụ ghi output từ stdout và stderr của service ra tập tin log, hãy đọc tài liệu và google về các lệnh khác daemontools cung cấp.
Kết luận
Các ngôn ngữ như Java, Perl, Python, Ruby v.v. đều có công cụ riêng để biến chương trình thành daemon, nhưng nếu mỗi lần viết chương trình lại phải mất công giải quyết vụ này (và cả vụ tự đông chạy khi Linux khởi động nữa chứ) thì rất phiền toái. Đó chính là lí do những công cụ như daemontools được ưa chuộng hơn.






