If you want to capture standard output and standard error separately, you can use temporary files or named pipes:
<span><span><span class="hljs-variable">$stderrFile</span></span><span> = </span><span><span class="hljs-title function_ invoke__">tempnam</span></span><span>(</span><span><span class="hljs-title function_ invoke__">sys_get_temp_dir</span></span><span>(), </span><span><span class="hljs-string">'stderr'</span></span><span>);
</span><span><span class="hljs-variable">$cmd</span></span><span> = </span><span><span class="hljs-string">"ls /nonexistent 2> <span class="hljs-subst">$stderrFile</span>"</span></span>;
<p></span>$handle = popen($cmd, "r"</span>);<br>
</span>$output = '';<br>
</span>while<span> (!</span>feof($handle)) {<br>
$output .= fread($handle, 1024</span>);<br>
}<br>
</span>$status = pclose($handle);</p>
<p>$stderr = file_get_contents($stderrFile);<br>
unlink($stderrFile);</p>
<p>echo "Standard Output:\n$output\n";<br>
</span>echo "Standard Error:\n$stderr\n";<br>
</span>echo "Command Return Status: $status\n";<br>
</span></span>
This allows you to capture both output streams separately, making error handling more precise.
proc_open() lets you directly manipulate standard input, output, and error. It is more complex to use but offers greater functionality.
<span><span><span class="hljs-variable">$descriptorspec</span></span><span> = [
</span><span><span class="hljs-number">0</span></span><span> => [</span><span><span class="hljs-string">"pipe"</span></span>, </span><span><span class="hljs-string">"r"</span></span>], </span><span><span class="hljs-comment">// Standard Input</span></span><span>
</span><span><span class="hljs-number">1</span></span><span> => [</span><span><span class="hljs-string">"pipe"</span></span>, </span><span><span class="hljs-string">"w"</span></span>], </span><span><span class="hljs-comment">// Standard Output</span></span><span>
</span><span><span class="hljs-number">2</span></span><span> => [</span><span><span class="hljs-string">"pipe"</span></span>, </span><span><span class="hljs-string">"w"</span></span>] </span><span><span class="hljs-comment">// Standard Error</span></span><span>
];
<p></span>$process = proc_open('ls /nonexistent', $descriptorspec, $pipes<span>);</p>
<p></span>if (is_resource($process<span>)) {<br>
</span>fclose<span>(</span>$pipes<span>[</span>0<span>]);</p>
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$pipes</span></span><span>[</span><span><span class="hljs-number">1</span></span><span>]);
</span><span><span class="hljs-variable">$stderr</span></span><span> = </span><span><span class="hljs-title function_ invoke__">stream_get_contents</span></span><span>(</span><span><span class="hljs-variable">$pipes</span></span><span>[</span><span><span class="hljs-number">2</span></span><span>]);
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$pipes</span></span><span>[</span><span><span class="hljs-number">2</span></span><span>]);
</span><span><span class="hljs-variable">$status</span></span><span> = </span><span><span class="hljs-title function_ invoke__">proc_close</span></span><span>(</span><span><span class="hljs-variable">$process</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Standard Output:\n<span class="hljs-subst">$stdout</span>\n"</span></span>;
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Standard Error:\n<span class="hljs-subst">$stderr</span>\n"</span></span>;
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Command Return Status: <span class="hljs-subst">$status</span>\n"</span></span>;
}
This method accurately separates the two output streams and is better suited for complex requirements.