Code:
$exchangesnapin = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010";
$output = shell_exec('powershell '.$exchangesnapin.';"get-mailboxdatabase" 2>&1');
echo( '<pre>' );
echo( $output );
echo( '</pre>' );
Result:
Name Server Recovery ReplicationType
---- ------ -------- ---------------
Mailbox Database 0651932265 EGCVMADTEST False None
Mailbox Database 0651932266 EGCVMADTEST False None
I tried with
echo( $output[1] );
The result was only a letter 'N'. I believe its taking the Name column but one character at a time.
$output[1] is 'N', $output[2] is 'a'.
Is there any way I can get the mailbox list into array?
you are trying to execute an external program (powershell) from PHP and have the output as an array.
In order to execute an external program in PHP, you could use:
exec() function
shell_exec() function
system() function
backtick operator
process control extensions
using process control extensions (PCNTL, popen) gives you more control, but takes more code and time. using the execution functions are simpler.
In this situation, using exec() could help you to have the output of powershell in an array whose each index is a line from the powershell output.
<?php
$output = array(); // this would hold the powershell output lines
$return_code = 0; // this would hold the return code from powershell, might be used to detect execution errors
$last_line = exec("powershell {$exchangesnapin} get-mailboxdatabase 2>&1", $output, $return_code);
echo "<pre>";
// print_r($output); view the whole array for debugging
// or iterate over array indexes
foreach($output as $line) {
echo $line . PHP_EOL;
}
echo "</pre>";
?>
Please note that (as the documentation says) if you only want to echo the output of powershell, you could use the passthru() function. using exec() uses memory to store the output of the external program, but using passthru would not use this storage, resulting in less memory usage. But the output could not be used for further processing, and is sent to the PHP standard output right a way.
In the end, please note that external program execution requires careful data validation to reduce the risk of unwanted system effects. Make sure you use escapeshellarg() on the data that constructs the execution command.
Related
With a PHP script which runs in CLI mode, I want to get the cursor position in a portable way.
With the code :
// Query Cursor Position
echo "\033[6n";
In the terminal, this code reports the cursor position, as
wb ?> ./script.php
^[[5;1R
wb ?> ;1R
But, I can't retrieve the two values (row: 5, column: 1) in the code.
After some tests with output buffering :
ob_start();
echo "\033[6n";
$s = ob_get_contents();
file_put_contents('cpos.txt',$s);
I've "\033[6n" in the cpos.txt file, not the device answer.
And reading STDIN :
$timeout = 2;
$sent = false;
$t = microtime(true);
$buf = '';
stream_set_blocking(STDIN,false);
while(true){
$buf .= fread(STDIN,8);
if(!$sent){
echo "\033[6n";
$sent = true;
}
if($t+$timeout<microtime(true))
break;
}
var_dump($buf);
The buffer is empty but the terminal show the device answer :
wb ?> ./script.php
^[[5;1R
string(0) ""
wb ?>
Is there a way, without curses, to get the cursor position ?
The code you have so far almost works, and you'll find that hitting enter and waiting for your timeout to complete does produce a string containing the answer, but with a \n character on the end. (Note the string length of 7 instead of 0.)
$ php foo.php
^[[2;1R
string(7) "
"
The issue here is that stream_set_blocking does not prevent the terminal from buffering input line-by-line, so the terminal doesn't send anything to stdin of your program until the enter key is pressed.
To make the terminal send characters immediately to your program without line-buffering, you need to set the terminal to "non-canonical" mode. This disables any line-editing features, such as the ability to press backspace to erase characters, and instead sends characters to the input buffer immediately. The easiest way to do this in PHP is to call the Unix utility stty.
<?php
system('stty -icanon');
echo "\033[6n";
$buf = fread(STDIN, 16);
var_dump($buf);
This code successfully captures the response from the terminal into $buf.
$ php foo.php
^[[2;1Rstring(6) ""
However, this code has a couple of issues. First of all, it doesn't re-enable canonical mode in the terminal after it's finished. This could cause issues when trying to input from stdin later in your program, or in your shell after your program exits. Secondly, the response code from the terminal ^[[2;1R is still echoed to the terminal, which makes your program's output look messy when all you want to do is read this into a variable.
To solve the input echoing issue, we can add -echo to the stty arguments to disable input echoing in the terminal. To reset the terminal to its state before we changed it, we can call stty -g to output a list of current terminal settings which can be passed to stty later to reset the terminal.
<?php
// Save terminal settings.
$ttyprops = trim(`stty -g`);
// Disable canonical input and disable echo.
system('stty -icanon -echo');
echo "\033[6n";
$buf = fread(STDIN, 16);
// Restore terminal settings.
system("stty '$ttyprops'");
var_dump($buf);
Now when running the program, we don't see any junk displayed in the terminal:
$ php foo.php
string(6) ""
One last potential improvement we can make to this is to allow the program to be run when stdout is redirected to another process / file. This may or may not be necessary for your application, but currently, running php foo.php > /tmp/outfile will not work, as echo "\033[6n"; will write straight to the output file rather than to the terminal, leaving your program waiting for characters to be sent to stdin as the terminal was never sent any escape sequence so will not respond to it. A workaround for this is to write to /dev/tty instead of stdout as follows:
$term = fopen('/dev/tty', 'w');
fwrite($term, "\033[6n");
fclose($term); // Flush and close the file.
Putting this all together, and using bin2hex() rather than var_dump() to get a listing of characters in $buf, we get the following:
<?php
$ttyprops = trim(`stty -g`);
system('stty -icanon -echo');
$term = fopen('/dev/tty', 'w');
fwrite($term, "\033[6n");
fclose($term);
$buf = fread(STDIN, 16);
system("stty '$ttyprops'");
echo bin2hex($buf) . "\n";
We can see that the program works correctly as follows:
$ php foo.php > /tmp/outfile
$ cat /tmp/outfile
1b5b323b3152
$ xxd -p -r /tmp/outfile | xxd
00000000: 1b5b 323b 3152 .[2;1R
This shows that $buf contained ^[[2;1R, indicating the cursor was at row 2 and column 1 when its position was queried.
So now all that's left to do is to parse this string in PHP and extract the row and column separated by the semicolon. This can be done with a regex.
<?php
// Example response string.
$buf = "\033[123;456R";
$matches = [];
preg_match('/^\033\[(\d+);(\d+)R$/', $buf, $matches);
$row = intval($matches[1]);
$col = intval($matches[2]);
echo "Row: $row, Col: $col\n";
This gives the following output:
Row: 123, Col: 456
It's worth noting that all this code is only portable to Unix-like operating systems and ANSI/VT100-compatible terminals. This code may not work on Windows unless you run the program under Cygwin / MSYS2. I'd also recommend that you add some error handling to this code in case you don't get the response from the terminal that you expect for whatever reason.
(this is really a comment, but it's a bit long)
Using hard coded terminal sequences is a very long way from "portable". While most terminal emulators available currently will support ANSI, vt100 or xterm codes which have a common base there is a very well defined API for accessing interactive terminals known as "curses". A PHP extension is available in pecl. This is just a stub interface to the curses system - present on any Unix/Linux system. While it is possible to set this up on mswindows, using cygwin or pdcurses, it's not an easy fit. You omitted to mention what OS you are working on. (The mswindows console uses ANSI sequences)
There is a toolkit (hoa) based on termcap (predecessor to curses) which might be useful.
To "retrieve" the data you just need to read from stdin (although it would be advisable to uses non-blocking up for this).
I'm running a simple command in a loop
the command itself is ffmpeg, but I do not believe it's related to the issue
so, I have:
exec($exec.' 2>&1', $output, $return);
if($return)
{
foreach($output as $line)
{
file_put_contents($log_file, $line, FILE_APPEND);
}
}
This way, if anything goes wrong with the command I can read the output in the log. It works, however $output contains the entire shell history of the command. To clarify: every time an error occurs, all output that was generated by the particular command (including hundreds of successful executions from throughout the day) is dumped to the file. What should be a 5 line error being written is instead the entire 1000+ line history. I used the exact same code on CentOS and it gave me the expected output of only the output generated by the instance most recently executed.
From the documentation:
Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
I can't explain why it worked differently on CentOS.
I am looking for something in php that would given output (raw) of a system command in a variable along with the return code.
exec does this, but the output is in array and hence the data returned is not proper(as \n comes in new index).
system outputs the data in the output stream and not in a variable.
shell_exec does not give the return value but gives raw data.
Sounds like you're looking for output buffering:
ob_start();
system($command, $returnCode);
$output = ob_get_clean();
This should preserve all white-space characters at the end of each output line (exec as you wrote destroys these, so implode would not be an option).
Alternatively, you can open a process and aquire the pipes (standard output, STDOUT) and read the output out of these. But it's more complicated (but gives you more options). See proc_open.
I'm building a RAKEFILE and I want to display the output on a php generated page as it gets executed.
I tried using system() since the PHP docs mention this:
The system() call also tries to automatically flush the web server's output buffer after each line of output if PHP is running as a server module.
This seems to work with multiple shell comands but when I execute rake I only get the first line:
(in /Users/path/to/proj)
Any ideas?
Cheers!
Try use exec() function
exec($command, $output);
$output is an array
//retrieved data
for($out = '',$x = 0,$len = count($output); $x < $len; $x++) {
$out .= $output[$x] . "\r\n";
}
or simple:
$out = join("\r\n", $output);
The system() call also tries to automatically flush the web server's output buffer after > each line of output if PHP is running as a server module.
This means you would only get the last line of output from the return value. The example in the system() manual page shows that and it suggests to use passthru() to get raw output. I usually use exec() though.
Turs out both functions system() & exec() actually work. The generated rake output when using --verbose isn't taken into consideration though. That's why I was confused. If anyone has more extensive knowledge on the distinction, do share :)
I want to see the output of the following code in the web browser:
code:
<?php
$var = system('fdisk -l');
echo "$var";
?>
When I open this from a web browser there is no output in the web browser. So how can I do this? Please help!
Thanks
Puspa
you can use passthru, like so:
$somevar = passthru('echo "Testing1"');
// $somevar now == "Testing1"
or
echo passthru('echo "Testing2"');
// outputs "Testing2"
use exec('command', $output);
print_r($output);
First of all, be sure that you (=user under which php runs) are allowed to call the external program (OS access rights, safe_mode setting in php.ini). Then you have quite a few options in PHP to call programs via command line. The most common I use are:
system
This function returns false if the command failed or the last line of the returned output.
$lastLine = system('...');
shell_exec or backtick operators
This function/operator return the whole output of the command as a string.
$output = shell_exec('...'); // or:
$output = `...`;
exec
This function returns the last line of the output of the command. But you can give it a second argument that then contains all lines from the command output.
$lastLine = exec('...'); // or capturing all lines from output:
$lastLine = exec('...', $allLines);
Here is the overview of all functions for these usecases: http://de.php.net/manual/en/ref.exec.php