2010-08-04 17 views
7

मैं एक रैपर वर्ग का उपयोग कर एक थर्ड पार्टी स्क्रिप्ट चला रहा हूं जो मैंने लिखा है जो shell_exec() और पाइप को फ़ाइल में पाइप कोड का उपयोग करके बाद में पार्स करता है। मुझे जिक्र करना चाहिए कि यह काम कर रहा है, लेकिन मैं कार्यक्षमता को बढ़ाने की कोशिश कर रहा हूं, जिसमें एक ऐसे मामले का सामना करना पड़ा जिस पर मैंने सोचा नहीं था।shell_exec() टाइमआउट प्रबंधन और निष्पादन()

shell_exec() पर टाइमआउट प्रबंधित करना सबसे अच्छा कैसे है? मैं इसे try() catch() में लपेटने की सोच रहा था, लेकिन मुझे यकीन नहीं है कि समय घटक को सर्वोत्तम तरीके से कैसे संभालना है।

मैं यहाँ shell_exec() और exec() से संबंधित पर कुछ सवाल पढ़ने किया गया है और ऐसा लगता है कि exec() को आउटपुट पैरामीटर पारित करके आप एक वापसी प्राप्त कर सकते हैं, लेकिन है कि स्क्रिप्ट की वापसी की स्थिति के साथ परिष्करण पर भरोसा करता है। इसके अलावा मेरे मिनी टेस्ट पेज में, मुझे लगता है कि यह किसी भी आउटपुट को वापस करने के लिए नहीं मिल रहा है!

अन्य विकल्प जो मैंने सोचा था, एक एजेक्स स्टाइल स्पिनर के साथ एक मोडल डायलॉग का उपयोग कर रहा था, जबकि स्क्रिप्ट यह काम कर रहा था, और जावास्क्रिप्ट में मैन्युअल टाइमआउट सेट कर रहा था। जिसके बाद उपयोगकर्ता ने असफल/टाइमआउट और समापन के बारे में एक मॉडल संवाद संदेश दिया।

क्या इस उपयोग के मामले में कोई स्वीकार्य तरीके हैं?

मेरे मिनी परीक्षण, निम्नलिखित शामिल था,

public $e_return = array(); 
public $e_status = ''; 
// Paths are absolute from/
public function execCheck($domain){ 
    exec($this->ssl_check_path." -s ".$domain." -p 443 > ".$this->folder.$this->filename." 2>&1 &", &$this->e_return, &$this->e_status); 
} 

// Returns 
Array 
(
) 

0 

रेफरी के रूप में इस सवाल का उपयोग करना, Can't execute PHP script using PHP exec

http://www.php.net/manual/en/function.exec.php

उत्तर

7

मैं तुम्हें proc_open का उपयोग कर इस पर गौर सुझाव है। आप इसे स्ट्रीम संसाधन वापस करने के लिए कॉन्फ़िगर कर सकते हैं, मैन्युअल रूप से टाइमर रख सकते हैं, और यदि प्रक्रिया पूर्ण होने से पहले टाइमर समाप्त हो जाती है, तो आप इसे proc_terminate से समाप्त कर सकते हैं। यदि टाइमर की समयसीमा समाप्त होने से पहले यह पूरा हो जाता है, तो आप उस डेटा को पकड़ने के लिए proc_closestream_get_contents का उपयोग कर सकते हैं जो अन्यथा stdout पर लिखा गया होगा।

http://www.php.net/manual/en/function.proc-open.php

+0

धन्यवाद मुझे लगता है कि एक कोशिश आज दे सकते हैं और देख मैं कैसे जाना :) –

+1

मैं भी इस सवाल पाया जाएगा बहुत आसान, http://stackoverflow.com/questions/2603912/php-set-timeout-for-script-with-system-call-set-time-limit-not-working –

15

देखें मैं ऐसे कार्य के लिए कोड के कुछ काम कर रहे टुकड़ा लिखें। फ़ंक्शन निकास कोड (0 - ठीक है,> 0 - त्रुटि) देता है और संदर्भ चर के लिए stdout, stderr लिखता है।

/*execute program and write all output to $out 
terminate program if it runs more than 30 seconds */ 
execute("program --option", null, $out, $out, 30); 
echo $out; 

function execute($cmd, $stdin=null, &$stdout, &$stderr, $timeout=false) 
{ 
    $pipes = array(); 
    $process = proc_open(
     $cmd, 
     array(array('pipe','r'),array('pipe','w'),array('pipe','w')), 
     $pipes 
    ); 
    $start = time(); 
    $stdout = ''; 
    $stderr = ''; 

    if(is_resource($process)) 
    { 
     stream_set_blocking($pipes[0], 0); 
     stream_set_blocking($pipes[1], 0); 
     stream_set_blocking($pipes[2], 0); 
     fwrite($pipes[0], $stdin); 
     fclose($pipes[0]); 
    } 

    while(is_resource($process)) 
    { 
     //echo "."; 
     $stdout .= stream_get_contents($pipes[1]); 
     $stderr .= stream_get_contents($pipes[2]); 

     if($timeout !== false && time() - $start > $timeout) 
     { 
      proc_terminate($process, 9); 
      return 1; 
     } 

     $status = proc_get_status($process); 
     if(!$status['running']) 
     { 
      fclose($pipes[1]); 
      fclose($pipes[2]); 
      proc_close($process); 
      return $status['exitcode']; 
     } 

     usleep(100000); 
    } 

    return 1; 
} 
0

मैं popen() साथ करने की कोशिश की है, लेकिन वहाँ बाद में प्रक्रिया समाप्त करने के लिए कोई रास्ता नहीं है। इसके अलावा, stream_get_contents() विंडोज पर stream_set_blocking का उपयोग करते समय स्ट्रीम को ब्लॉक करता है, इसलिए मुझे इसके बजाय फ़्रेड का उपयोग करना पड़ा। इसके अलावा, proc_terminate विंडोज पर ठीक से काम नहीं करता है, इसलिए मुझे वैकल्पिक हत्या समारोह का उपयोग करना पड़ा।

मैं इस के साथ आया है, यह अब विंडोज और लिनक्स पर दोनों काम करना चाहिए:

function execute($command, $timeout = 5) { 
    $handle = proc_open($command, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipe); 

    $startTime = microtime(true); 

    /* Read the command output and kill it if the proccess surpassed the timeout */ 
    while(!feof($pipe[1])) { 
     $read .= fread($pipe[1], 8192); 
     if($startTime + $timeout < microtime(true)) break; 
    } 

    kill(proc_get_status($handle)['pid']); 
    proc_close($handle); 

    return $read; 
} 

/* The proc_terminate() function doesn't end proccess properly on Windows */ 
function kill($pid) { 
    return strstr(PHP_OS, 'WIN') ? exec("taskkill /F /T /PID $pid") : exec("kill -9 $pid"); 
} 
संबंधित मुद्दे