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---"
Related
This question already has answers here:
PHP reading shell_exec live output
(3 answers)
Closed 6 years ago.
I have to execute a batch file (I.e. .bat ) and get the result on an HTML page.
I used this PHP code to get a result:
<?php
echo "<br>";
$result = shell_exec('start file.bat');
iconv("CP850","UTF-8",$result);
echo "<pre>$result </pre>";
?>
Now the problem is that I get a result only when the batch file execution finishes, and I want to have the result in real time, like running via command line.
Found in the comments of the shell_exec documentation's page of PHP
If you're trying to run a command such as "gunzip -t" in shell_exec and getting an empty result, you might need to add 2>&1 to the end of the command, eg:
Won't always work:
echo shell_exec("gunzip -c -t $path_to_backup_file");
Should work:
echo shell_exec("gunzip -c -t $path_to_backup_file 2>&1");
In the above example, a line break at the beginning of the gunzip output seemed to prevent shell_exec printing anything else. Hope this saves someone else an hour or two.
I believe it is what you really have to do.
Reference: http://php.net/manual/en/function.shell-exec.php#106250
As already mentioned in the comments to your question you need to fork a process in such way that you can communicate with it. That is not possible with imple functions like exec() and the like.
Instead take a look at this simple example:
File test.sh:
#!/bin/bash
echo start counting ...
for counter in 1 2 3
do
echo * counter is at value $counter *
sleep 3
done
echo ... finished counting.
File test.php:
<?php
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
);
echo "forking process ...\n";
$process = proc_open('./test.sh', $descriptorspec, $pipes);
if (is_resource($process)) {
echo "... successfully forked process ...\n";
while (!feof($pipes[1])) {
echo fread($pipes[1], 1024);
flush();
}
echo "... process has finished ...\n";
fclose($pipes[0]);
fclose($pipes[1]);
echo "... pipes closed ...\n";
proc_close($process);
echo "... process closed.\n";
} else {
echo "... failed to fork process!\n";
}
The obvious output of a test run of that php script is:
forking process ...
... successfully forked process ...
start counting ...
* counter is at value 1 *
* counter is at value 2 *
* counter is at value 3 *
... finished counting.
... process has finished ...
... pipes closed ...
... process closed.
But the interesting part here is that this output is not sent in one go once that forked process has finished, but in what you referred to as "a live manner". So the first four lines appear immediately, the next two with a 3 second delay each, then the rest of the output.
Please note that the above example is meant as a demonstration for a Linux CLI environment. So it does not care about html markup but outputs plain text and relies on bash as a shell environment for the forked process. You will have to adapt that simple demonstration to your needs, obviously.
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
#!/bin/bash
cd /maintenance;
for (( i=1;i<1000;i++)); do
php -q dostuff.php $i
done
I use this shell script to call the dostuff.php script and pass the $i as an agrv to the script. The script connects to a webservice that returns results 50 items at a time. The $i value is the page number... I have no way to know how many times it needs to be called (how many pages) until I get a response code back from CURL inside that script that I test for. I need to pass my own response code back to the shell script to have it stop looping... it will never get to 1000 iterations... it was just a quick loop I made.
If I use exec("php -q dostuff.php $i", $output, $return_var) how do I tell the script to keep executing and passing the incremented $i value until my php script exits with a response code of 0?
There has got to be a better way. Maybe a while? Just not that good with this syntax.
I have to start at page 1 and repeat until page XXX incrementing by 1 each iteration. When there are no more results I can test for this in the dostuff.php and exit(0). What is the best way to implement this in the shell script?
Thanks!
You can check for the return value of the script, and break the loop if it isn't what is expected.
Usually a script returns 0 when it ran successfully, and something else otherwise, so if I assume your script respect this condition you could do:
#!/bin/bash
cd /maintenance;
for (( i=1;i<1000;i++)); do
php -q dostuff.php $i
if [ $? -ne 0 ]; then break; fi
done
On the other hand, if you want your script to return 0 if the loop shouldn't continue then you should do:
if [ $? -eq 0 ]; then break; fi
Edit: to take the comment into account to simplify the script:
If your script returns 0 when it shouldn't be called again, you instead do:
#!/bin/bash
cd /maintenance;
for (( i=1;i<1000;i++)); do
if php -q dostuff.php $i; then break; fi
done
As already suggested in the comments, you might get way better control if you dont wrap the php script inside a bash script but instead use php-cli as the shell script (PHP is kinda shell):
#!/usr/bin/php
<?php
for ($i = 0; $i < 1000; $i++) {
// contents of dostuff.php integrated
}
You might also be interested in using STDOUT, STDIN and STDERR:
http://php.net/manual/en/features.commandline.io-streams.php
I wrote this in Linux BASH shell, but if there's a better solution in PHP that would be fine.
I need to produce a random selection from an array of 12 elements. This is what I've been doing so far:
# Display/return my_array that's been randomly selected:
# Random 0 to 11:
r=$(( $RANDOM % 12 ))
echo ${my_array[$r]}
Each time the call is made, it randomly selects an element. However, too often, it "randomly" selects the same element in a row sometimes several times. How can this be accomplish in BASH shell or PHP so make a random selection which is also not a repeat of the last one selected? Thanks!
r=$last
while [ "$last" = "$r" ]
do
r=$(($RANDOM % 12))
done
export last=$r
If you are calling the script again and again, then suppose the script name is test.sh you need to call it like . test.sh instead of ./test.sh, it will make the script run in current shell. Else even the export is not needed. Otherwise creating a temp file approach is another robust way of getting the last value.
You can create a permutation and then pop values from it
perm=`echo $perm | sed 's/[0-9]\+//'` #remove the first number from $perm
if [ -z "$perm" ];then #if perm == ""
perm=`shuf -e {0..12}` #create new permutation
#now perm="11 7 0 4 8 12 9 5 10 6 2 1 3" for example
fi
echo $perm | cut -d' ' -f1 #show the first number from $perm
Note that this script is stateful. It need to store the generated permutation between executions. Is does it by storing them in a shell variable $perm. Because shell scripts cannot modify the calling shell environment, you need to execute it itside your current shell:
source ./next-index.sh
having saved the script is to next-index.sh file.
You could alternatively save $perm to file between executions.
This simple script:
<?php
$cmd='./HandBrakeCLI -i ./a.flv -o ./ab.mkv';
echo exec($cmd.'&');
?>
outputs:
Encoding: task 1 of 1, 0.46 %
Or a similarly low percentage and produces no real output file.