2012-03-12 31 views
10

Trong Ruby 1.9.x, điều gì có thể là một cách đơn giản để không cho phép kịch bản Ruby của tôi chạy lại, hoặc chờ cho phiên bản trước đó kết thúc? **Làm thế nào để hạn chế các trường hợp đồng thời của cùng một tập lệnh Ruby?

Tôi hy vọng sẽ tránh được việc khóa tập tin lộn xộn hoặc quá trình kiểm tra bảng.

Có điều gì đó giống như global mutex hoặc semaphore đã có trong lõi không? Tôi đã nghiên cứu bản gốc Mutex nhưng điều đó dường như chỉ áp dụng cho các chủ đề trong một quá trình Ruby, không phải qua các quy trình khác nhau.

** Sau đó, tôi có thể thêm chức năng hết thời gian chờ hoặc giới hạn vào các phiên bản N hoặc tìm cách sử dụng nhiều khóa toàn cầu (mỗi tài nguyên trên toàn hệ thống chỉ nên có tối đa một phiên bản).

Trả lời

2

Điều này thường được giải quyết ở cấp hệ điều hành, bằng cách kiểm tra một tệp cờ và không cố khởi chạy lại, không phải trong tập lệnh.

Nhưng, nếu bạn muốn kiểm tra tập lệnh, hãy tìm một tệp semaphore ở một vị trí đã biết. Nếu nó tồn tại và nó không nằm trong một cửa sổ thời gian nhất định phù hợp với cửa sổ khởi chạy của bạn, hãy xóa tệp và tạo một tệp mới. Nếu nó nằm trong cửa sổ thời gian của bạn thì hãy thoát.

Bạn có thể sử dụng tính năng khóa tệp hoặc lưu trữ dấu thời gian trong tệp hoặc nhiều lần kiểm tra khác nếu bạn không khởi chạy bằng cơ chế loại cron. Mỗi phương pháp đều có điểm cộng và nhược điểm của nó.

Bạn sẽ muốn ngắt các ngắt để khi thoát khỏi Control-C, bạn cũng xóa tệp đó.

Đọc qua các câu hỏi liên quan ở bên phải. Mặc dù họ đang bao gồm các ngôn ngữ khác nhau, các câu trả lời được đề xuất sẽ giúp hiểu các vấn đề và cách có thể để làm việc xung quanh chúng trên tất cả các ngôn ngữ.

+0

Tôi đã bọc hầu hết Ruby của tôi bằng các tập lệnh Bash mà chính họ sử dụng mã như '[-z" $ (pidof -x -o% PPID -o $$ $ {0 ## * /}) "] || exec echo "$ (ngày) $ 0: $$ đã có mùi PID: $ (pidof -x $ 0), ... bye !!" 'tuy nhiên phục vụ các mục đích khác. Một giải pháp thậm chí tốt hơn đã được chứa trong Ruby chính nó là khóa bất kỳ tập tin cố định để viết ví dụ. '/ tmp/scriptname.rb.lock'. Tại lối ra hoặc thậm chí nếu mã của tôi treo (mà nó thường làm tăng ngoại lệ) hệ thống sẽ xóa khóa đó. Tôi sẽ chỉ đi với hack đó cho đến khi có một giao diện thuần túy, thuần túy cho các semaphores toàn cầu - mà tôi sẽ có nhu cầu cho dù sao đi nữa. – Marcos

5

mã rất ngắn này sẽ đóng băng tại chỗ cho đến khi một lockfile trong/tmp đặt tên theo kịch bản của bạn bị khóa độc quyền:

File.open("/tmp/#{File.basename $0}.lock", File::RDWR|File::CREAT, 0644).flock(File::LOCK_EX) 

Bất kỳ chương trình nào khác khóa nó, Ruby hay không, chỉ cần chấm dứt hoặc bị giết , cho phiên bản mới hơn để bỏ chặn và tiếp tục. Vì vậy, bây giờ workaround này làm những gì tôi cần. Tôi có thể gọi chương trình của Ruby của tôi với

timeout 1m ./myrubyscript.rb 

từ gói bash kịch bản nếu tôi nhận được thiếu kiên nhẫn, ví dụ. (Trong ví dụ đó, myrubyscript.rb sẽ chấm dứt sau 1 phút cho dù có hay không và khóa tệp của nó để tiếp tục thực hiện những gì nó được viết để làm.)