2009-12-28 31 views
40

Nếu tập lệnh PHP được chạy dưới dạng tập lệnh cron, việc bao gồm thường bị lỗi nếu đường dẫn tương đối được sử dụng. Ví dụ: nếu bạn cóĐường dẫn tương đối không hoạt động trong cron Kịch bản lệnh PHP

require_once('foo.php'); 

tệp foo.php sẽ được tìm thấy khi chạy trên dòng lệnh, nhưng không tìm thấy khi chạy từ tập lệnh cron.

Cách giải quyết điển hình cho việc này là chuyển chdir đầu tiên vào thư mục làm việc hoặc sử dụng đường dẫn tuyệt đối. Tôi muốn biết, tuy nhiên, những gì là khác nhau giữa cron và vỏ gây ra hành vi này. Tại sao nó thất bại khi sử dụng đường dẫn tương đối trong một kịch bản cron?

+0

Đây là một nguồn lực lớn cũng như: http://stackoverflow.com/questions/2857712/enable-proper-relative-path-in-cron – Webnet

Trả lời

11

Thư mục hoạt động của tập lệnh có thể khác khi chạy từ cron. Bổ sung, có một số nhầm lẫn về PHP yêu cầu() và bao gồm(), gây nhầm lẫn về thư mục hoạt động thực sự là vấn đề:

include('foo.php') // searches for foo.php in the same directory as the current script 
include('./foo.php') // searches for foo.php in the current working directory 
include('foo/bar.php') // searches for foo/bar.php, relative to the directory of the current script 
include('../bar.php') // searches for bar.php, in the parent directory of the current working directory 
1

Khi thực hiện máng một công việc cron kịch bản PHP của bạn có thể chạy trong bối cảnh khác nhau hơn nếu bạn bắt đầu nó bằng tay từ trình bao. Vì vậy, đường dẫn tương đối của bạn không trỏ đến đúng đường dẫn.

+0

đúng. Trong thực tế, thư mục làm việc của tập lệnh là thư mục làm việc của trình bao. Nên sử dụng tên đường dẫn tuyệt đối. – mauris

+1

tên đường dẫn tuyệt đối là một cơn ác mộng để quản lý khi bạn di chuyển các tập tin xung quanh ... chỉ cần sử dụng 'dirname (__FILE__)' – aequalsb

3

Một khả năng khác là phiên bản CLI đang sử dụng tệp php.ini khác. (Theo mặc định, nó sẽ sử dụng php-cli.ini và dự phòng cho php.ini chuẩn)

Ngoài ra, nếu bạn đang sử dụng các tệp .htaccess để đặt đường dẫn thư viện của bạn, điều này rõ ràng sẽ không hoạt động qua cli.

86

Thay đổi thư mục làm việc thành đường dẫn tệp đang chạy. Chỉ cần sử dụng

chdir(dirname(__FILE__)); 
include_once '../your_file_name.php'; //we can use relative path after changing directory 

trong tệp đang chạy. Sau đó, bạn sẽ không cần phải thay đổi tất cả các đường dẫn tương đối thành đường dẫn tuyệt đối trong mỗi trang.

+1

Điều này khiến tôi phát điên. Điều này sắp xếp nó ra hoàn hảo – Andy

+1

Điều này phải được đánh dấu là đúng – axelbrz

+1

Bạn cũng có thể sử dụng 'chdir (__ DIR __);' là một chút ngắn gọn hơn. – billynoah

7

Cơ hội duy nhất tôi nhận được "require_once" để làm việc với cron và apache đồng thời là

require_once(dirname(__FILE__) . '/../setup.php'); 
0

DIR làm việc mặc dù nó sẽ không hoạt động trên localhost của tôi vì nó có một con đường khác hơn sống của tôi máy chủ trang web. Tôi đã sử dụng nó để sửa nó.

if(__DIR__ != '/home/absolute/path/to/current/directory'){ // path for your live server 
     require_once '/relative/path/to/file'; 
    }else{ 
     require_once '/absolute/path/to/file'; 
    } 
+1

vẫn sử dụng câu lệnh có điều kiện có thể được thay thế bằng 'dirname (__FILE__)' – aequalsb

3

Bởi vì "thư mục làm việc hiện tại" cho công việc cron sẽ là thư mục nơi mà file crontab của bạn tồn tại - vì vậy bất kỳ đường dẫn tương đối với được liên quan đến thư mục đó.

Cách đơn giản nhất để xử lý với chức năng dirname() và hằng số PHP __FILE__. Nếu không, bạn sẽ cần chỉnh sửa tệp bằng các đường dẫn tuyệt đối mới bất cứ khi nào bạn di chuyển tệp vào một thư mục khác hoặc máy chủ có cấu trúc tệp khác.

dirname(__FILE__) 

__FILE__ là hằng số được định nghĩa bởi PHP là đường dẫn đầy đủ đến tệp mà tệp được gọi. Ngay cả khi tệp được bao gồm, __FILE__ sẽ LUÔN LUÔN tham chiếu đến đường dẫn đầy đủ của tệp - không phải tệp đang thực hiện bao gồm.

Vì vậy, dirname(__FILE__) trả về đường dẫn thư mục đầy đủ đến thư mục chứa tệp - bất kể nó được bao gồm từ đâu và basename(__FILE__) trả về tên tệp chính nó.

ví dụ: Giả sử "/home/user/public_html/index.php" bao gồm "/home/user/public_html/your_directory/your_php_file.php".

Nếu bạn gọi dirname(__FILE__) trong "your_php_file.php", bạn sẽ nhận được "/ home/user/public_html/your_directory" được trả về mặc dù tập lệnh đang hoạt động nằm trong "/ home/user/public_html" (lưu ý sự vắng mặt của dấu gạch chéo).

Nếu bạn cần thư mục chứa tệp BAO GỒM: dirname($_SERVER['PHP_SELF']) sẽ trả về "/ home/user/public_html" và giống như gọi dirname(__FILE__) trong tệp "index.php" vì đường dẫn tương đối giống nhau.

dụ tập quán:

@include dirname(__FILE__) . '/your_include_directory/your_include_file.php'; 

@require dirname(__FILE__) . '/../your_include_directory/your_include_file.php'; 
2

Ngoài các câu trả lời được chấp nhận ở trên, bạn cũng có thể sử dụng:

chdir(__DIR__); 
+0

chỉ khi bạn được phép thực thi 'chdir()' trong môi trường bạn đang ở trong – aequalsb

+0

là điều phổ biến? Tôi chưa bao giờ làm việc trong bất kỳ môi trường nào mà chức năng đó không được phép. – billynoah

+0

tôi đã trải nghiệm nó liên quan đến PHP safe_mode. http://php.net/manual/en/features.safe-mode.functions.php, nhưng điều này đã không được chấp nhận http://php.net/manual/en/features.safe-mode.php. - đó là không được chấp nhận không bị xóa ... có nghĩa là, nó vẫn có thể gặp phải. – aequalsb

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