2012-07-04 34 views
10

Tôi có một tập lệnh được thiết kế để chạy cả dưới dạng trang web và qua bảng điều khiển. Phát hiện phương pháp nào được sử dụng để gọi kịch bản có vẻ khá thẳng về phía trước, nhưng khi tập lệnh được chạy từ bảng điều khiển, tôi cần biết liệu tập lệnh có đang chạy tương tác hay không (lệnh nhập của người dùng hoặc chuyển hướng đầu vào từ một tệp).Phát hiện xem tập lệnh PHP có đang chạy tương tác hay không

php script.php so php script.php < input_file

Đây có phải là có thể?

Trả lời

25

Tôi cũng cần một giải pháp nhẹ linh hoạt hơn posix_isatty có thể phát hiện:

  • là kịch bản được chạy từ nhà ga
  • là kịch bản nhận dữ liệu thông qua một đường ống hoặc từ một tập tin
  • Đầu ra có được chuyển hướng đến một tệp

Sau một chút thử nghiệm và đào tạo thông qua tiêu đề libc, tôi đã đưa ra một lớp rất đơn giản có thể thực hiện tất cả những điều trên và hơn thế nữa.

class IOMode 
{ 
    public $stdin; 
    public $stdout; 
    public $stderr; 

    private function getMode(&$dev, $fp) 
    { 
     $stat = fstat($fp); 
     $mode = $stat['mode'] & 0170000; // S_IFMT 

     $dev = new StdClass; 

     $dev->isFifo = $mode == 0010000; // S_IFIFO 
     $dev->isChr = $mode == 0020000; // S_IFCHR 
     $dev->isDir = $mode == 0040000; // S_IFDIR 
     $dev->isBlk = $mode == 0060000; // S_IFBLK 
     $dev->isReg = $mode == 0100000; // S_IFREG 
     $dev->isLnk = $mode == 0120000; // S_IFLNK 
     $dev->isSock = $mode == 0140000; // S_IFSOCK 
    } 

    public function __construct() 
    { 
     $this->getMode($this->stdin, STDIN); 
     $this->getMode($this->stdout, STDOUT); 
     $this->getMode($this->stderr, STDERR); 
    } 
} 

$io = new IOMode; 

Một số ví dụ về cách sử dụng, để hiển thị những gì nó có thể phát hiện.

Input:

$ php io.php 
// Character device as input 
// $io->stdin->isChr == true 

$ echo | php io.php 
// Input piped from another command 
// $io->stdin->isFifo == true 

$ php io.php < infile 
// Input from a regular file (name taken verbatim from C headers) 
// $io->stdin->isReg == true 

$ mkdir test 
$ php io.php < test 
// Directory used as input 
// $io->stdin->isDir == true 

Output:

$ php io.php 
// $io->stdout->isChr == true 

$ php io.php | cat 
// $io->stdout->isFifo == true 

$ php io.php > outfile 
// $io->stdout->isReg == true 

Lỗi:

$ php io.php 
// $io->stderr->isChr == true 

$ php io.php 2>&1 | cat 
// stderr redirected to stdout AND piped to another command 
// $io->stderr->isFifo == true 

$ php io.php 2>error 
// $io->stderr->isReg == true 

Tôi đã không bao gồm các ví dụ cho các thiết bị liên kết, ổ cắm, hay chặn lại, nhưng không có lý do chúng không nên hoạt động vì mặt nạ chế độ thiết bị cho chúng nằm trong lớp.

(Không thử nghiệm trên Windows - quãng đường đi có thể thay đổi)

+1

Rất đẹp, 1 - Trong hoàn cảnh nào sẽ 'S_IFLNK' và' S_IFSOCK' trở thành sự thật? – DaveRandom

+1

@DaveRandom: Tôi chưa bao giờ thực sự phát hiện ra (hoặc cần chúng), tôi đã bao gồm chúng cho đầy đủ khi tôi nhận được mặt nạ từ các tiêu đề C. Chúng rõ ràng là liên kết và ổ cắm liên quan, nhưng khi tôi đang thử nghiệm, tôi không thể có được thứ gì để kích hoạt chúng. – Leigh

+0

Cảm ơn bạn rất nhiều. Điều đó làm chính xác những gì tôi muốn! :) – Fania

4

posix_isatty()

if (posix_isatty(0)) { 
    // STDIN is a TTY 
} else { 
    // STDIN is a pipe or has no associated TTY 
} 

Rõ ràng đây chỉ hoạt động trên hệ điều hành POSIX tuân thủ, nơi PHP có phần mở rộng posix cài đặt. Tôi không biết về tương đương Windoze.

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