I want to pass the stdout of a command in bash (ex. uptime) to a PHP variable, let's say uptime too.
How this can be done?
Use shell_exec for returning the output of shell commands:
<?php
$output = shell_exec('uptime');
echo $output;
?>
Result:
18:17 up 12 days, 13:39, 3 users, load averages: 1.80 1.78 1.75
↳ http://php.net/manual/en/function.shell-exec.php
Related
In my test.php script I have this:
$out = exec ( 'ps -ef' );
echo $out;
Which outputs just this when I run "php test.php":
root 16682 2 0 Jan30 ? 00:00:00 [NFSv4 callback]
However, when I run "ps -ef" from the command line I get the usual long list of processes for all users..
Any ideas why the php script produces such different results?
Please try
shell_exec ( 'ps -ef' );
This will return the entire output, whereas exec returns the last line of output:
http://php.net/manual/en/function.exec.php
I have a bash script abcd.sh
#!/bin/sh
for i in `seq 8`; do ssh w$i 'uptime;ps -elf|grep httpd|wc -l;free -m;mpstat'; done &
pid=$!
sleep 1
kill -9 $pid
I want to use PHP in my bash script.
eg: in bash script I want to set value of seq through PHP.
Mmm, if you are using bash, you should maybe use a bash shebang on line 1 so people know you are expecting bash features to be available. And if you are using bash, you can use a bash sequence anyway:
#!/bin/bash
for i in {1..8}; do echo $i; done
Update 1
If the number of servers is obtained through PHP, you can do something like this:
numservers=$(php -r 'echo 8;')
for i in $(seq $numservers); do echo $i; done
1
2
3
4
5
6
7
8
Update 2
Ok, you said the number of servers is dynamic, but then you say it is set in the script (which seems contradictory), but this is what you do:
numservers=10
for i in $(seq $numservers); do echo $i; done
1
2
3
4
5
6
7
8
9
10
Why don't you write the entire shell script in PHP?
#!/usr/bin/php
<?php
for ($i = 0; $i < 8; $i++) {
exec("ssh w$i 'uptime;ps -elf|grep httpd|wc -l;free -m;mpstat'");
}
?>
(code is untested, just an example)
It's not easy to understand what you want.
Maybe this helps. The script defines a var PHP_VAR in bash and use this var in PHP. Then we call a PHP code snippet an put the output in the shell var output. At last we output the var output (but you can do something else with it).
Attation: All the output from the PHP will be found in the var output.
#!/bin/bash
echo "I am a bash echo"
export PHP_VAR="I was in php"
# Here we start php and put the output in 'output'
output=$(php << EOF
<?php \$inner_var = getenv("PHP_VAR");
echo \$inner_var; ?>
EOF
)
# usage var 'output' with php output
echo "---$output---"
I am trying to execute system commands in PHP and capture the output of those commands where that output covers multiple lines. I am using exec(), but it seems like it only returns a value for commands that generate output on a single line.
For example, if I run date at the command line I get:
Wed May 15 15:07:32 EST 2013
As expected, if I run this command from PHP as an exec using this...
exec("date", $exec_results);
...then the value of $exec_results becomes...
Array ( [0] => Wed May 15 15:07:32 EST 2013 )
However, when I run time from the command line I get this...
real 0m0.000s
user 0m0.000s
sys 0m0.000s
...but when I do it from PHP with this...
exec("time", $exec_results);
... the value of $exec_results is empty:
Array( )
I don't actually need to run date or time in my application but these are just examples of how the single line vs. multi-line output on the command line seems to change what gets back to PHP.
The documents say:
If the output argument is present, then the specified array will be filled with every line of output from the command.
So why is the $exec_results array not being filled with all the lines seen when the time command is run in the command line?
Notes - I have run the command line entries as the apache user to rule out privileges.
This should work for you
ob_start();
passthru("ls -la");
$dat = ob_get_clean();
So here's the full list:
system() => Execute an external program and displays the output.
passthru() => Same than system, but casts the output in binary "as is" from the shell to the PHP output (typically the HTTP response).
exec() => Captures the output and only the last line of the output into a string.
shell_exec() => Same than exec, but capturing full output, not only the last line.
So, my preference: Always use shell_exec() and then do with the full-string whatever you want.
How to test
$ php -a
Interactive mode enabled
php > echo( shell_exec( "echo hello; echo bye" ) );
hello
bye
php >
https://www.php.net/manual/en/function.shell-exec.php
I changed my post for the working solution:
Use the 'script' command of unix to get the result.
you will surely have to remove "extra lines" of the temporary log file.
exec('script -c "time" /tmp/yourfile.txt');
$result = file('/tmp/yourfile.txt');
var_dump($result);
You should always put a full path to your temporary file, anywhere you put it
that's it !
I've been wrestling with exec(), trying to capture the output from it when I add a task using the at Unix system command. My problem is that it is giving no output when run from my script, however running it from the terminal and PHP in interactive mode prints out a couple of lines.
The command I want to execute is this:
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
var_dump() gives string(0) "", and print_r() spits out Array (). I've tried using shell_exec(), which outputs NULL, however the following outputs hi when run in a web page context:
echo exec("echo 'hi'");
This also outputs stuff:
echo exec("atq");
However, as soon as I use at, nothing is output. How can I get the output of:
exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
Because at present it outputs nothing when run as "normal" by PHP through Apache, however running the command in the terminal as well as in PHP's interactive console gives me the expected result of something like:
php > echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
warning: commands will be executed using /bin/sh
job 1219 at Sun Jun 10 12:43:00 2012
safe_mode is off, and I cannot work out why I don't get any output from at with a piped-in echo statement, when executing atq or any other commend with exec() gives me output. I've searched and read this question, all to no avail.
How can I get exec() to return the output from at to either a string, or an array if using a second argument with exec()?
Working, one line solution
I didn't realise it could be this simple. All that is required is to reroute stderr to stdout by putting 2>&1 at the end of the command to execute. Now any output from at is printed to stdout, therefore captured by exec():
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);
My old solution:
I was trying to keep to a one/two line solution, however the only thing that worked in the end was using proc_open() because at logs to stderr, which exec() doesn't read! I'd like to thank #Tourniquet for pointing this out, however he has deleted his answer. To quote:
As far as i can see, at outputs to stderr, which isn't captured by
exec. I'm not really confident in it, but consider using
http://php.net/manual/en/function.proc-open.php, which allows you to
direct stderr to its own pipe.
This is actually the correct way of doing things. My solution (because I only want stderr) was to do this:
// Open process to run `at` command
$process = proc_open("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", array(2 => array("pipe", "w")), $pipes);
// Get stuff from stderr, because `at` prints out there for some odd reason
if(is_resource($process)) {
$output = stream_get_contents($pipes[2], 100);
fclose($pipes[2]);
$return_value = proc_close($process);
}
$output now contains whatever at printed to stderr (which should really go to stdout because it's not an error), and $return_value contains 0 on success.
Here a more complex solution with proc_open. I'm writing this answer because, in my case, the '2>&1' workaround doesn't work.
function runCommand($bin, $command = '', $force = true)
{
$stream = null;
$bin .= $force ? ' 2>&1' : '';
$descriptorSpec = array
(
0 => array('pipe', 'r'),
1 => array('pipe', 'w')
);
$process = proc_open($bin, $descriptorSpec, $pipes);
if (is_resource($process))
{
fwrite($pipes[0], $command);
fclose($pipes[0]);
$stream = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
}
return $stream;
}
Usage examples:
// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));
Another example using the command parameter:
// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');
Another example using the force parameter (this can be useful for commands that will change the output during the execution process):
// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);
I hope this helps :-)
Try to create a minimum (non-)working example. Break everything down, and test only one thing at a time.
Here is one error in your bash:
hpek#melda:~/temp$ echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes
at: pluralization is wrong
job 22 at Sun Jun 10 14:48:00 2012
hpek#melda:~/temp$
Write minute instead og minutes.
My output from at is send to me by mail!!
I was trying to execute this command
echo exec("top");
and
echo exec("/usr/bin/top");
neither works (returns blank output)
does anybody know why?
Because top is an interactive program that is meant to be run on a terminal, not be executed from a script. You are probably want to run the 'ps' command with arguments which will sort output by cpu utilization.
http://www.devdaily.com/linux/unix-linux-process-memory-sort-ps-command-cpu
You actually can call top and echo its output. Code that worked for me:
passthru('/usr/bin/top -b -n 1');
-b - running in batch mode
-n 1 - only one iteration
It probably works, but exec() doesn't return anything. Read the Manual: exec()
$output = null;
exec('top', $output);
echo $output;
But you have another problem: top doesn't exit by itself. You cannot use it here, because you need to send the interrupt-signal (just realized: q is ok too).
One solution is to make top to stop after one iteration
$output = null;
exec('top -n 1', $output);
var_dump($output);
If you want to put it in a variable :
ob_start();
passthru('/usr/bin/top -b -n 1');
$output = ob_get_clean();
ob_clean();
I used:
$cpu = preg_split('/[\s]+/', shell_exec('mpstat 1 1'));
$cpu = 100-$cpu[42];
100% minus the idle time.