2013-07-11 30 views
6

Tôi đã đọc nhiều bài viết và nhiều bài viết chi tiết rằng scipts trong một công việc cron cần phải giữ các biến môi trường cần thiết để chạy bên trong bản thân script do việc mở các shell trong cron. Tình trạng của tôi là duy nhất trong đó các biến đường dẫn của tôi tất cả được thiết lập như được thảo luận, do đó sẽ thành công gọi trứng python pysaunter bằng cách sử dụng subprocess.call(), nhưng dường như nó bị phá vỡ từ đó. Điều này làm cho toàn bộ quá trình phá vỡ trong một công việc cron.Python Script không chạy trong crontab gọi pysaunter

Để rõ ràng, đây là các bước tôi tham khảo:

1) cronjob calls run_test.py -n foo 
2) run_test.py sets the environment variables correctly 
(cur_shell_path=sys.path (converted to proper path string, not shown here) 
my_env= os.environ.copy() 
my_env["PATH"] = my_env["PATH"] + cur_shell_path) 
3) run_test.py calls subprocess.call("pysaunter -m foo -v", env=my_env, shell=True) 

Kết quả của bước 3 cho thấy rằng nó là tìm trứng và bắt đầu thành công để tải các module cần thiết từ pysaunter, nhưng sau đó nó phá vỡ khi cố gắng tìm một thư mục được sử dụng để sửa đổi pysaunter. Lỗi đọc:

ImportError: no module named helpers 

Tôi đã cố thêm đường dẫn này vào môi trường nhiều lần nhưng dường như không tìm thấy thư mục chứa helpers.py. Lệnh pysaunter -m foo -v hoạt động bình thường khi được gọi từ một trình bao tương tác.

Tôi không thể tìm thấy nhiều trợ giúp trên pysaunter, vì vậy tôi giả định rằng quá nhiều chi tiết cụ thể pysaunter sẽ không cần thiết ở đây. Tuy nhiên, nếu bạn biết nhiều hơn về pysaunter, vui lòng cho tôi biết nếu bạn cần thêm thông tin. Tôi không chắc chắn những gì để chia sẻ.

Tôi cũng đã đọc nhiều bài đăng thảo luận về khả năng thay đổi hành vi mặc định của trình bao bằng cách chỉnh sửa .profile/.bash_profile. Tôi đã cố gắng tìm một nơi có thể làm cho các biến đường dẫn của tôi có thể truy cập trên toàn cầu, nhưng tôi không thể tìm thấy bất cứ thứ gì. Tôi không chắc làm thế nào điều này được thực hiện, và nó có thể sửa chữa vấn đề của tôi, vì vậy nếu bạn biết bất cứ điều gì về điều đó xin vui lòng cho tôi biết.

Lưu ý cuối cùng, điều này đang chạy trên máy Mac 10.7.5.

Trả lời

3

Sau nhiều thử và sai, và nhiều, nhiều bài viết stackoverflow.com và hướng dẫn khác trực tuyến, và với sự giúp đỡ của một kịch bản Perl tôi thấy rằng đã làm một cái gì đó tương tự, tôi đã có thể tìm ra những gì cần thiết để được thực hiện để có được điều này để làm việc.

Dưới đây là các bước để đảm bảo mọi thứ được thiết lập chính xác:

  1. Đảm bảo rằng bạn có các biến mà bạn cần trong PYTHONPATH (tìm thấy herehere, và cho biết thêm đi here.) Bên trong .profile hoặc .bash_profile cho bất kỳ trình bao nào bạn muốn thử nghiệm tập lệnh của mình để đảm bảo nó hoạt động.

  2. Sửa crontab bạn để bao gồm các thư mục cần thiết để chạy kịch bản của bạn trong một công việc định kỳ (tìm thấy herehere).

    a) Đảm bảo đưa thư mục gốc vào biến PATH (.) Như được giải thích here. Về cơ bản, nếu bạn đang chạy một tập tin thực thi với lệnh của bạn nó cần để có thể tìm thấy gốc hoặc thư mục nơi thực thi được lưu trữ và cũng có thể là: (/ sbin:/bin:/usr/sbin:/usr/bin).

  3. Trong tệp crontab của bạn, hãy tạo một cronjob sẽ thay đổi thư mục hiện tại thành thư mục mà bạn đã chạy tập lệnh thành công trước đó (ví dụ:/Users/user/Documents/foo).

    a) Điều này sẽ trông giống như sau:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
  4. Kể từ khi vấn đề của tôi xử lý đặc biệt với gọi một thực thi, nó là cần thiết để lưu ý rằng có nhiều cách viết kịch bản Python để chạy (mặc dù trong quá trình khám phá, tôi đã học được rằng điều này làm việc cho bất kỳ cuộc gọi nào được thực hiện bằng cách sử dụng tiến trình con trong cron).

    Phương pháp đầu tiên trông như thế này:

    ... #some script calls 
    my_env = os.environ.copy() 
    my_env["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>") 
    os.chdir("<path/to/desired/directory>") 
    subprocess.Popen(<call_as_string>, env=my_env, shell=True) 
    

    Và thứ hai trông như sau:

    ... #some script calls 
    os.environ["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>") 
    os.chdir("<path/to/desired/directory>") 
    subprocess.Popen(<call_as_list_of_arguments) 
    

    Kể từ khi thực thi cần đường dẫn đến thư mục giúp đỡ bao gồm trong vỏ nơi nó được gọi là từ, nó là cần thiết để vượt qua biến môi trường để thực thi như được giải thích here. Tuy nhiên, những gì tôi tìm thấy là việc sửa đổi biến PATH trong môi trường không làm việc cho một công việc cron, nhưng thiết lập PYTHONPATH đã làm. Tôi đọc here rằng biến PATH được sử dụng bởi trình bao để chỉ tìm kiếm các tệp thực thi, vì vậy đối với một trình bao mới bên trong cronjob, bạn cần phải vượt qua vỏ một PYTHONPATH để tìm các mô-đun Python mới. (Đây cũng là explained in the Python docs.)

    Sự khác biệt giữa hai phương pháp khác nhau được giải thích trong tài liệu quy trình con được trích dẫn trong câu hỏi, nhưng có thể tìm thấy hướng dẫn tốt về mô-đun này here.

1

Những gì bạn đã nói không có ý nghĩa.

Bạn nói shell_env = sys.path. sys.path là danh sách các thư mục cho python tìm kiếm các mô-đun, chứ không phải ánh xạ biến môi trường!

Sau đó, bạn sử dụng điều đó trong subprocess.call. Có lẽ bạn muốn viết env=my_env.

Đó là vấn đề tiếp theo. Trước tiên, PATH phải là danh sách thư mục được phân tách bằng ':'. Bạn chỉ cần kéo shell_path vào thư mục cuối cùng.

Cuối cùng, trăn sử dụng PYTHONPATH như một danh sách để xác định vị trí các module python (mà có vẻ là những gì vấn đề bạn đang gặp phải.)

+1

Cảm ơn bạn đã chỉ ra vấn đề của mình, tôi hiện đã khắc phục sự cố để hiển thị rằng my_env đang được chuyển. Ngoài ra, trên các máy dựa trên Unix, dấu hai chấm (:) được sử dụng để tách các giá trị đường dẫn, do đó không thể là vấn đề. Cuối cùng, Pythonpath được sử dụng để tìm kiếm thư mục cục bộ, mà trên Unix được định nghĩa bởi nơi mà shell được [khởi chạy] (http://docs.python.org/release/1.5.1p1/tut/searchPath.html). Vì các công việc cron gọi một shell không tương tác không được khởi chạy từ thư mục chính xác và không đọc một .profile hoặc .bash_profile, không có đường dẫn nào được thêm vào và do đó Pythonpath không được thiết lập. – derigible

+1

Bạn đã đúng về dấu hai chấm. Tôi đã sửa nó. Bạn cần đặt PYTHONPATH trong công việc cron. Bạn có thể tạo một kịch bản trình bao bọc để đặt PYTHONPATH thành thư mục mong muốn và sau đó gọi tập lệnh python. – korylprince

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