2009-02-26 40 views
23

Tôi có một công cụ mà tôi đã viết bằng python và thường nên được chạy như một daemon. Các phương pháp hay nhất để đóng gói công cụ này để phân phối, đặc biệt là các tệp cài đặt và tập lệnh/thực thi daemon sẽ được xử lý như thế nào?Python Daemon Packaging Thực tiễn tốt nhất

Relatedly được có bất kỳ công cụ phổ biến cho việc thiết lập các daemon chạy khi khởi động phù hợp cho nền tảng nhất định (ví dụ: init script trên Linux, dịch vụ trên cửa sổ, launchd trên os x)?

+1

Xem thêm câu hỏi SO này: http://stackoverflow.com/questions/473620/how-do-you-create-a-daemon-in-python – Rabarberski

Trả lời

11

Để trả lời một phần của câu hỏi của bạn, không có các công cụ tôi biết rằng sẽ làm thiết lập daemon portably ngay cả trên các hệ thống Linux cho phép Windows một mình hoặc Mac OS X.

phân phối

Hầu hết các Linux dường như được sử dụng trong vòng start-stop-daemon init script bây giờ, nhưng bạn vẫn sẽ có sự khác biệt nhỏ trong cách bố trí hệ thống tập tin và sự khác biệt lớn trong bao bì. Sử dụng autotools/configure, hoặc distutils/easy_install nếu dự án của bạn là tất cả Python, sẽ đi một chặng đường dài để làm cho nó dễ dàng hơn để xây dựng các gói cho các bản phân phối Linux/BSD khác nhau.

Windows là một trò chơi hoàn toàn khác và sẽ yêu cầu các tiện ích mở rộng Mark Hammond's win32 và có thể là Tim Golden's WMI tiện ích mở rộng.

Tôi không biết Launchd ngoại trừ "không có gì ở trên" có liên quan.

Để biết các mẹo về cách mã hóa các tập lệnh Python, tôi sẽ xem xét các ứng dụng Python đang thực sự thực hiện nó trong thế giới thực, ví dụ bên trong Twisted.

14

Công cụ tốt nhất tôi tìm thấy để trợ giúp với init.d script là "start-stop-daemon". Nó sẽ chạy bất kỳ ứng dụng nào, theo dõi các tệp run/pid, tạo chúng khi cần thiết, cung cấp các cách để ngăn chặn daemon, đặt id người dùng/nhóm quá trình và thậm chí có thể tạo nền cho quá trình của bạn.

Ví dụ, đây là một kịch bản mà có thể bắt đầu/dừng một máy chủ wsgi:

#! /bin/bash 

case "$1" in 
    start) 
    echo "Starting server" 

    # Activate the virtual environment 
    . /home/ali/wer-gcms/g-env/bin/activate 

    # Run start-stop-daemon, the $DAEMON variable contains the path to the 
    # application to run 
    start-stop-daemon --start --pidfile $WSGI_PIDFILE \ 
     --user www-data --group www-data \ 
     --chuid www-data \ 
     --exec "$DAEMON" 
    ;; 
    stop) 
    echo "Stopping WSGI Application" 

    # Start-stop daemon can also stop the application by sending sig 15 
    # (configurable) to the process id contained in the run/pid file 
    start-stop-daemon --stop --pidfile $WSGI_PIDFILE --verbose 
    ;; 
    *) 
    # Refuse to do other stuff 
    echo "Usage: /etc/init.d/wsgi-application.sh {start|stop}" 
    exit 1 
    ;; 
esac 

exit 0 

Bạn cũng có thể thấy có một ví dụ về làm thế nào để sử dụng nó với một virtualenv, mà tôi sẽ luôn khuyên.

-10

"thường phải được chạy dưới dạng daemon?"

Không - trên bề mặt - có nhiều ý nghĩa. "Nói chung" là không hợp lý. Đó là một daemon hay không. Bạn có thể muốn cập nhật câu hỏi của mình.

Ví dụ về daemon, đọc lên các daemon như httpd của Apache hoặc bất kỳ máy chủ cơ sở dữ liệu nào (chúng là daemon) hoặc daemon thư SMTPD.

Hoặc, có thể, đọc lên trên một cái gì đó đơn giản hơn, như daemon FTP, SSH daemon, Telnet daemon.

Trong thế giới Linux, bạn sẽ có thư mục cài đặt ứng dụng, một số thư mục làm việc, cùng với các thư mục tệp cấu hình.

Chúng tôi sử dụng /opt/ourapp cho ứng dụng (đó là Python, nhưng chúng tôi không cài đặt bằng Python của lib/site-packages)

Chúng tôi sử dụng /var/ourapp cho các tập tin làm việc và các tập tin cấu hình của chúng tôi.

Chúng tôi có thể sử dụng /etc/ourapp cho tệp cấu hình - nó sẽ nhất quán - nhưng chúng tôi không.

Chúng tôi chưa - sử dụng các tập lệnh init.d để khởi động. Nhưng đó là phần cuối cùng, tự động khởi động. Bây giờ, chúng ta có các quản trị viên sys khởi động các trình tiện ích.

Điều này được dựa một phần, trên http://www.pathname.com/fhs/http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/Linux-Filesystem-Hierarchy.html.

+2

Bạn thật đẹp khó khăn !? Daemons chỉ là chương trình được daemonized. Nó đôi khi hữu ích để chạy chúng như là quá trình thường xuyên cho Ctrl-c chúng, kiểm tra có đầu ra trên stdout vv – fulmicoton

+0

@Paul: Đồng ý. Bạn có thể làm rõ câu hỏi? –

0

Trên các hệ thống Linux, trình quản lý gói của hệ thống (Portage cho Gentoo, Aptitude cho Ubuntu/Debian, yum cho Fedora, v.v.) thường chăm sóc cài đặt chương trình bao gồm đặt init script vào đúng vị trí. Nếu bạn muốn phân phối chương trình của mình cho Linux, bạn có thể muốn xem xét gói nó thành định dạng thích hợp cho các trình quản lý gói phân phối khác nhau.

Lời khuyên này rõ ràng là không liên quan trên các hệ thống không có trình quản lý gói (Windows và Mac tôi nghĩ).

+0

Có hệ thống đóng gói cho nhiều Unices khác! Ví dụ pkgsrc cho NetBSD. – bortzmeyer

+0

Thú vị, tôi không biết rằng –

8

Có rất nhiều đoạn trên cung cấp internet để viết một daemon trong python tinh khiết (không có kịch bản bash)

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ trông sạch ...

Nếu bạn muốn viết của riêng bạn,
sự nguyên tắc giống như hàm bash daemon.

Về cơ bản:

Mở đầu:

  • bạn ngã ba đến một quá trình
  • mở một logfile để chuyển hướng stdout và stderr của bạn
  • Save the pid nơi nào đó.

Mở cửa:

  • Bạn gửi SIGTERM để quá trình với pid lưu trữ trong pidfile của bạn.
  • Với signal.signal (signal.SIGTERM, sigtermhandler), bạn có thể kết thúc quy trình dừng với tín hiệu SIGTERM.

Tôi không biết bất kỳ gói được sử dụng rộng rãi nào làm việc này.

+1

+1 Đối với trình nền Python. Tôi thực sự sử dụng một công thức tương tự như thế này, ngoại trừ tôi khởi chạy nó với start-stop-daemon từ một kịch bản Bash. Có lẽ một bước quá nhiều, nhưng nó mang lại cho tôi một cảm giác mờ ấm áp để hành xử giống như tất cả các daemon khác! –

3

Tôi không thể nhớ mình đã tải xuống ở đâu ... nhưng đây là tập lệnh chỉnh sửa tốt nhất mà tôi đã tìm thấy. Nó hoạt động rất đẹp (trên Mac và Linux.) (Lưu nó như daemonize.py)

import sys, os 
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): 
    # Perform first fork. 
    try: 
     pid = os.fork() 
     if pid > 0: 
      sys.exit(0) # Exit first parent. 
    except OSError, e: 
     sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror)) 
     sys.exit(1) 
    # Decouple from parent environment. 
    os.chdir("/") 
    os.umask(0) 
    os.setsid() 
    # Perform second fork. 
    try: 
     pid = os.fork() 
     if pid > 0: 
      sys.exit(0) # Exit second parent. 
    except OSError, e: 
     sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror)) 
     sys.exit(1) 
    # The process is now daemonized, redirect standard file descriptors. 
    for f in sys.stdout, sys.stderr: f.flush() 
    si = file(stdin, 'r') 
    so = file(stdout, 'a+') 
    se = file(stderr, 'a+', 0) 
    os.dup2(si.fileno(), sys.stdin.fileno()) 
    os.dup2(so.fileno(), sys.stdout.fileno()) 
    os.dup2(se.fileno(), sys.stderr.fileno()) 

Trong kịch bản của bạn, bạn sẽ chỉ đơn giản là:

from daemonize import daemonize 
daemonize() 

Và bạn cũng có thể xác định nơi để chuyển hướng stdio , err, v.v.

+4

Dường như bản dựng đầu tiên của hình này: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ –

3

Không phải là dấu đầu dòng bạc cho những gì bạn đang yêu cầu, nhưng hãy xem supervisord.Nó xử lý tất cả các bit thú vị của quá trình quản lý. Tôi sử dụng nó rất nhiều trong một môi trường sản xuất lớn. Ngoài ra, nó được viết bằng Python!

0

này blog entry đã làm cho nó rõ ràng cho tôi rằng có thực sự hai cách phổ biến để chương trình Python của bạn chạy dưới dạng deamon (tôi đã không tìm ra điều đó rõ ràng từ các câu trả lời hiện có):

Có hai cách tiếp cận để viết các ứng dụng daemon như các máy chủ bằng Python.

  • Đầu tiên là để xử lý tất cả các nhiệm vụ của sarting và daemon dừng bằng Python mã chính nó. Cách dễ nhất để thực hiện việc này là với gói python-daemon mà cuối cùng có thể thực hiện theo cách vào bản phân phối Python.

Poeljapon's answer là một ví dụ về cách tiếp cận 1 này, mặc dù nó không sử dụng gói python-daemon, nhưng liên kết đến một phong tục nhưng kịch bản python rất sạch sẽ.

  • Cách tiếp cận khác là để sử dụng các công cụ được cung cấp bởi hệ điều hành. Trong trường hợp Debain, điều này có nghĩa là viết tập lệnh init sử dụng chương trình start-stop-daemon .

Ali Afshar's answer là một ví dụ shell script của cách tiếp cận thứ 2, sử dụng start-stop-daemon.

Mục nhập blog tôi trích dẫn có ví dụ về tập lệnh shell và một số chi tiết bổ sung về những thứ như khởi động trình nền của bạn khi khởi động hệ thống và tự động khởi động lại trình nền của bạn khi nó dừng vì bất kỳ lý do gì.

0

sửa tôi nếu sai, nhưng tôi tin rằng câu hỏi là cách DEPLOY daemon. Đặt ứng dụng của bạn để cài đặt qua pip và sau đó đặt entry_point là cli(daemon()). Sau đó, tạo tập lệnh init chỉ cần chạy $app_name &

Các vấn đề liên quan