I have a bash script with a few lines similar to the following
echo "Do something"
/bin/sh -c 'echo $$>pidfile && exec "command"' &
echo "Ran Command">/path/to/outputfile.txt
exit 0
Then I call that from a PHP script
return shell_exec("/path/to/bash/script arguments");
Now, when I do that, the command is run successfully, and outputfile.txt contains "Ran Command".
However, the PHP script times out after 10ish seconds. The bash script takes about 2-3 seconds to run
If I change the line to
return shell_exec("/path/to/bash/script arguments >/dev/null 2>&1");
Then it executes and the PHP script doesn't time out.
I understand why redirecting the output lets PHP continue executing, but I can't figure out why PHP is timing out in the first place requiring me to do that. Can someone give me some assistance with this?
Test this two versions and you get it:
test1.sh
/bin/sh -c 'sleep 10' >/dev/null 2>&1 &
test2.sh
/bin/sh -c 'sleep 10' &
run both with php on command line like
test1.php
<?php shell_exec('test1.sh');
test2.php
<?php shell_exec('test2.sh');
and see the difference.
test2.sh is taking 10ish seconds and test1.sh is working like your
return shell_exec("/path/to/bash/script arguments >/dev/null 2>&1");
I'm trying to list running services on a windows server via php. Therefore I'm using shell_exec with winexe.
My script:
$cmd = "winexe --interactive=0 --user='***' --password='***' //192.168.***.** \"net start\"";
$output = shell_exec($cmd);
echo $output;
Unfortunately on execution the page loads forever with no result. The command works on the command-line (Debian).
Anyone an idea?
Thanks in advance.
Save $cmd with correct format into a new bash file. Set cmd value for call this file. Remember set execution perms to this file.
Check if your apache user has perms for exec winexe
===
Try to launch
cat </dev/null | winexe --interactive=0 --ostype=1 --user=...
PHP code:
$number_server = 10;
exec("/bin/bash wrun.sh $number_server",$wuptime);
Bash script:
#!/bin/sh
for i in `seq echo $1`; do
ssh /usr/local/bin/wrun 'uptime
ps -elf | grep httpd | wc -l
free - m;mpstat'
done &
pid=$!
sleep 3
kill -9 $pid && echo "not respond in give time"
In this I want to pass the argument $number_server to the bash script from the php file.
#!/bin/sh
for i in `seq $1`; do
I am trying to open remote machine browser from my machine. I have setup password less connection ( considering the fact that both systems are in same n/w and are trusted).
I am able to run below script to launch browser, which takes 3 arguments
a). userName
b). ip address of remote machine
c). url to open in firefox
If i run this script in my bash shell, i am able to open the browser without any issues. But if i call this inside PHP, i am not able to launch the browser on remote machine...it shows all debug prints but fails open browser. Any pointers are greatly helpful. Below is my shell script to open browser on remote machine.
#!/bin/bash
if test $# != 3;
then
echo "
$0
This command line script is used to launch, browser remotely. You need to pass 3 arguments to this script.
YOU NEED TO PASS 3 ARGUMEMTS TO THIS SCRIPT,
For example , \$> sh $0 \"<userNameofRemoteSystem>\" \"<remoteSystemIP>\" \"<webPageAddress>\"
\$> sh $0 \"Uname\" \"172.17.64.94\" \"mail.google.com\" \n";
exit 1
fi
echo "<br><br>\nRECEIVED PARAMETERS,\n\tuserName\t-> |$1|\n\tipAddress\t-> |$2|\n\twebURL\t\t-> |$3|\n\n<br>";
echo "<br>Checking if Connection to |$2| WITH USERNAME |$1| is password less???<br><br>";
sleep 2
echo "<br>grep -wc $1 /home/user/.ssh/authorized_keys<br>";
count=`grep -wc $1 /home/user/.ssh/authorized_keys`;
echo "<br>got process count=|$count|<br>"
sleep 2
if [ "$count" != 1 ];
then
echo "
Looks like password less connection to |$2| is not configured with this server for username |$1|..
Please congfigure the same and run this script again...\n";
fi
echo "SUCCESSFULLY CONNECTED, LAUNCHING BROWSER ON |$2| WITH |$3|\n";
ssh $1#$2 "nohup sh openBrowser.sh $3" &
PID=$$;
echo "PID IS |$PID|\n";
sleep 2;
echo "<br>PROCESS OUTPUT LOOKS LIKE THIS";
ps aux | grep $PID | grep -v grep
echo "<br>";
echo "after sleep";
kill -9 $PID && echo "after kill pid=$PID, passed ssh $1#$2 \"nohup sh openBrowser.sh $3\" &";
Below is the php script i am using to call the shell script.
<?php
$c_url=$_POST['url'];
$c_name=$_POST['uname'];
$c_ip=$_POST['ipaddress'];
$output = system("/bin/sh /home/user/launchBrowser_remote.sh $uName $ipADDR $c_url");
echo "$output";
?>
Looks like i am getting wrong PID inside shell script and its killing the caller script rather than launching the ssh to remote ..... BTW i have tried both exec and shell_exec but no luck.
Any pointer are greatly helpful
Thanks
Make sure that the user that is running the php file (web server user if being called in that context) is set up for password-less authentication as well.
I have a PHP script that listens on a queue. Theoretically, it's never supposed to die. Is there something to check if it's still running? Something like Ruby's God ( http://god.rubyforge.org/ ) for PHP?
God is language agnostic but it would be nice to have a solution that works on windows as well.
I had the same issue - wanting to check if a script is running. So I came up with this and I run it as a cron job. It grabs the running processes as an array and cycles though each line and checks for the file name. Seems to work fine. Replace #user# with your script user.
exec("ps -U #user# -u #user# u", $output, $result);
foreach ($output AS $line) if(strpos($line, "test.php")) echo "found";
In linux run ps as follows:
ps -C php -f
You could then do in a php script:
$output = shell_exec('ps -C php -f');
if (strpos($output, "php my_script.php")===false) {
shell_exec('php my_script.php > /dev/null 2>&1 &');
}
The above code lists all php processes running in full, then checks to see if "my_script.php" is in the list of running processes, if not it runs the process and does not wait for the process to terminate to carry on doing what it was doing.
Just append a second command after the script. When/if it stops, the second command is invoked. Eg.:
php daemon.php 2>&1 | mail -s "Daemon stopped" you#example.org
Edit:
Technically, this invokes the mailer right away, but only completes the command when the php script ends. Doing this captures the output of the php-script and includes in the mail body, which can be useful for debugging what caused the script to halt.
Simple bash script
#!/bin/bash
while [true]; do
if ! pidof -x script.php;
then
php script.php &
fi
done
Not for windows, but...
I've got a couple of long-running PHP scripts, that have a shell script wrapping it. You can optionally return a value from the script that will be checked in the shell-script to exit, restart immediately, or sleep for a few seconds -and then restart.
Here's a simple one that just keeps running the PHP script till it's manually stopped.
#!/bin/bash
clear
date
php -f cli-SCRIPT.php
echo "wait a little while ..."; sleep 10
exec $0
The "exec $0" restarts the script, without creating a sub-process that will have to unravel later (and take up resources in the meantime). This bash script wraps a mail-sender, so it's not a problem if it exits and pauses for a moment.
Here is what I did to combat a similar issue. This helps in the event anyone else has a parameterized php script that you want cron to execute frequently, but only want one execution to run at any time. Add this to the top of your php script, or create a common method.
$runningScripts = shell_exec('ps -ef |grep '.strtolower($parameter).' |grep '.dirname(__FILE__).' |grep '.basename(__FILE__).' |grep -v grep |wc -l');
if($runningScripts > 1){
die();
}
You can write in your crontab something like this:
0 3 * * * /usr/bin/php -f /home/test/test.php my_special_cron
Your test.php file should look like this:
<?php
php_sapi_name() == 'cli' || exit;
if($argv[1]) {
substr_count(shell_exec('ps -ax'), $argv[1]) < 3 || exit;
}
// your code here
That way you will have only one active instace of the cron job with my-special-cron as process key. So you can add more jobs within the same php file.
test.php system_send_emails sendEmails
test.php system_create_orders orderExport
Inspired from Justin Levene's answer and improved it as ps -C doesn't work in Mac, which I need in my case. So you can use this in a php script (maybe just before you need daemon alive), tested in both Mac OS X 10.11.4 & Ubuntu 14.04:
$daemonPath = "FULL_PATH_TO_DAEMON";
$runningPhpProcessesOfDaemon = (int) shell_exec("ps aux | grep -c '[p]hp ".$daemonPath."'");
if ($runningPhpProcessesOfDaemon === 0) {
shell_exec('php ' . $daemonPath . ' > /dev/null 2>&1 &');
}
Small but useful detail: Why grep -c '[p]hp ...' instead of grep -c 'php ...'?
Because while counting processes grep -c 'php ...' will be counted as a process that fits in our pattern. So using a regex for first letter of php makes our command different from pattern we search.
One possible solution is to have it listen on a port using the socket functions. You can check that the socket is still listening with a simple script. Even a monitoring service like pingdom could monitor its status. If it dies, the socket is no longer listening.
Plenty of solutions.. Good luck.
If you have your hands on the script, you can just ask him to set a time value every X times in db, and then let a cron job check if that value is up to date.
troelskn wrote:
Just append a second command after the script. When/if it stops, the second command is invoked. Eg.:
php daemon.php | mail -s "Daemon stopped" you#example.org
This will call mail each time a line is printed in daemon.php (which should be never, but still.)
Instead, use the double ampersand operator to separate the commands, i.e.
php daemon.php & mail -s "Daemon stopped" you#example.org
If you're having trouble checking for the PHP script directly, you can make a trivial wrapper and check for that. I'm not sufficiently familiar with Windows scripting to put how it's done here, but in Bash, it'd look like...
wrapper_for_test_php.sh
#!/bin/bash
php test.php
Then you'd just check for the wrapper like you'd check for any other bash script: pidof -x wrapper_for_test_php.sh
I have used cmder for windows and based on this script I came up with this one that I managed to deploy on linux later.
#!/bin/bash
clear
date
while true
do
php -f processEmails.php
echo "wait a little while for 5 secobds...";
sleep 5
done