Php web application long response time after running Powershell script - php

I'm writing a php web application hosted on iis web server and i'm actually trying to make a read-only powershell live web console.
This is how it works:
1) in my "console" main page i have a div and some buttons, the div starts empty
2) when you click a button, the click generates an ajax call to a page called "engines.php" and starts to load into my div the content of "engine515data.php"
3) "engines.php" first runs a query to delete some records from a XXX table, then runs a powershell script located on a remote server
4) this powershell script replaces some files (.dll etc...) on many different remote servers and inserts some records in the same XXX table
5) "engine515data.php" runs a select from the table updated by powershell script and echoes every row
Web app is running on IIS 10 with PHP 7.3
Ajax call in my main page:
$(document).ready(function() {
$('#515S').on('click', function(){
var version = $(this).attr('version');
$.ajax({
type:'POST',
url:'engines.php',
data: {runEngine: 1, version: version},
async:true,
success:function(data){
}
});
var interval = setInterval(function () {
$('#show').load('engine515data.php');
$('#clearConsole').on('click', function(){
$("#show").html("Console is ready and waiting for a script to be executed...");
clearInterval(interval);
});
}, 1000);
});
});
Engines.php:
function runEngine($version){
$username = $_SESSION['username'];
$db_server_name = "DB_SERVER_NAME";
$remote_db_name = "DATABASE_NAME";
$conn2 = dbconn2($db_server_name,$remote_db_name);
$query="DELETE FROM XXX WHERE VERSION = '$version' AND UPD_TYPE = 'YYY' AND USERNAME = '$username'";
if($conn2){
$handle = sqlsrv_query($conn2, $query) or die( print_r( sqlsrv_errors(), true));
}
$psPath = "C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe";
$psDIR = "\\\\SERVER_NAME\\XXX\\XXX\\";
$psScript = "SCRIPT_NAME.ps1 $version $username";
$runScript = $psDIR. $psScript;
$runCMD = $psPath." ".$runScript." 2>&1";
$output = shell_exec($runCMD);
}
if(isset($_POST["runEngine"]) && $_POST["runEngine"]=='1'){
runEngine($_POST["version"]);
}
engines515data.php:
$username = $_SESSION['username'];
$server_name = "DB_SERVER_NAME";
$remote_db_name = "DB_NAME";
$conn2 = dbconn($server_name,$remote_db_name);
$query="SELECT Message FROM XXX WHERE (Version = 515) AND (UPD_TYPE = 'YYY') AND (USERNAME = '$username')";
if($conn2){
$handle = sqlsrv_query($conn2, $query) or die( print_r( sqlsrv_errors(), true));
}
while ($row = sqlsrv_fetch_array($handle, SQLSRV_FETCH_ASSOC)) {
if((strpos($row['Message'], "AAA"))!== false ||
(strpos($row['Message'], "BBB"))!== false ||
(strpos($row['Message'], "CCC"))!== false)
echo '<font color="yellow">' . $row['Message'] . "</font>" . '<br>';
else
echo $row['Message'] . '<br>';
}
It worked with no problems until monday, then i suddently faced long response time and no more "live" records into my div.
The POST method to engines.php now take 90376ms (TTFB) to run and returns
500 - Internal server error
(after ajax call end i see what i expect into my div) but looking on SQL the .ps1 script runs smoothly, i see records i'm expecting.
I've tried to run the script directly from Powershell console while the div was refreshing and all runs smoothly with "live" records and no latency on respose time...
If i try to load the page that should retrieve the data from my DB (engines515data.php) while the ajax call is waiting the page continuously load showing nothing until the call ends and only then the div is filled with records and the page is loaded.
If i try to run, instead, a really light script (for loop writing "Test" 10 times) all runs with no problems.
I've also tried to remove some SQL queries and the while loop inside "engine515data.php" and to switch to an async ajax call but nothing changed.
I googled a lot and i already tried to change some config into my ini.php like "max_execution_time" or "memory_limit" and checked my iis application pool configuration but i cannot figure out what's wrong with my webapp. All i know is that THE SAME CODE was working perfectly until last week...
How can i avoid this huge response time?
Sorry for my english.

After many search i found out that this problem is related to a php session lock, so i managed to solve it by adding session_write_close(); in Engines.php between $username = $_SESSION['username']; and $db_server_name = "DB_SERVER_NAME";.
Thank everyone for trying, your effort was appreciated.

Related

PHP MySQL Update after Seconds

I want to update a MySQL field after when the site was opened for X Seconds.
I get the Seconds/Time from MySQL and want to update in MySQL when the seconds are over.
I tried
sleep($adddisplaytime);
but then the site waits complete and does not run the things over first
Is there a way to run my update after some seconds when the site is opened?
$query1 = "UPDATE ads SET views = views+1, costs = costs+price WHERE id = '".$adid."'";
Can be in PHP or MySQL
NOTE: This will do what you want, but could be exploited by someone hitting the AJAX endpoint repeatedly, you would want to build in some protections for that.
You will need an additional PHP file, the job of that PHP is to only update the db. You will need to take that update OUT of your page loading script.
Your HTML / JS / PHP for initial load
<script>
setTimeout(function() {
$.ajax('/your/ajax/endpoint.php', {
data: {
'adid': 'your id'
/*
If this is in your PHP file, you can echo the ID straight there.
Not totally recommended, but that's one way An additional /
better way is to add it to a div with a data attribute and
use jQuery to select the data off of there
*/
}
}); // Probably lots more you can do here, but in this case, for simplicity, just sending and that's it
}, 2000); // This will do a 2 second wait
</script>
Your new additional PHP file that is at /your/ajax/endpoint.php
<?php
// THIS FILE DOES THE UPDATE
$adid = $_POST['adid'];
// As mentioned by tadman in his comment.. I would use prepared statements
$query1 = "UPDATE ads SET views = views+1, costs = costs+price WHERE id = ?";
try {
$dbh = new PDO($dsn, $user, $password);
$sth = $dbh->prepare($query1);
$sth->execute(array($adid));
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
NOTE:
Again, for security's sake, you really want to consider having your first PHP script generate a unique ID (and store it in the db), that is passed to the page, and having the AJAX send that unique ID with the adid, and if the unique ID you gave is in the database only THEN would you know it's a legitimate request. Remove the unique ID from the database and do the update.
If you want to wait for some seconds after a page is opened and then run the update statement , then write the following codes on the top of the page:-
echo "<script> setTimeout(function(){}, 2000) ; </script>" ;
$query1 = mysqli_query($con, "UPDATE ads SET views = views+1, costs = costs+price WHERE id = '".$adid."'");

Chat page using jQuery's $.ajax and PHP not updating in a timely manner

I'm building a chat page for members of one of my websites. Everything works properly for me, except for the chat's automatic updates. The chat page is supposed to check for new messages every 5 seconds, and manipulating the callbacks shows that this part is working correctly; however, the PHP file that $.ajax references is giving me two very different behaviors. Because the ajax is working correctly in every test I have performed, I will exclude it here, but I can add it if anyone feels it is necessary. This is my annotated PHP:
$new_chat = //new chat message, collected from $.ajax and sanitized
$new_sender = //username of sender, collected from $.ajax and sanitized
$new_time = date('m-d-y');
$most_recent_chat = //unique id# of most recent chat message, collected from $.ajax and sanitized
//This block makes sure that there is a most recent chat; if not, (i.e., the
//page was just loaded so there are no chats on the page) it manually sets one.
//I'm not having any problems with this block.
if (!isset($most_recent_chat)) {
$query = "SELECT MAX(id) AS 'Most Recent' FROM `chat_global`";
$check_last_chat = new mysqli($host,$user,$pass,$game_db);
$check_last_chat->query($query);
if(!$result = $check_last_chat->query($query)) {
die();
}
while ($row=$result->fetch_assoc()) {
$most_recent = $row['Most Recent'];
}
$most_recent_chat = $most_recent-100;
$result->free();
$check_last_chat->close();
}
//Send any new chats to DB
if(isset($new_chat)) {
//First query inserts new chats into the chat table
$query = "INSERT INTO `chat_global` (message,sender,time) VALUES ('".$new_chat."','".$new_sender."','".$new_time."');";
$add_new_chat = new mysqli($host,$user,$pass,$game_db);
$add_new_chat->query($query);
$add_new_chat->close();
//Second query returns all new chats in reference
//to the most recent chat on the user's browser page
$query2 = "SELECT * FROM `chat_global` WHERE id>'$most_recent_chat';";
$most_recent_chats = new mysqli($host,$user,$pass,$game_db);
if(!$result = $most_recent_chats->query($query2)) {
die();
}
while($row = $result->fetch_assoc()) {
echo '<div class="chat-item" data-chat-id="' . $row['id'] . '">';
echo '<p class="chat-message"><strong>' . $row['sender'] . ': </strong>' . $row['message'] . '</p>';
echo '<p class="chat-time">' . $row['time'] . '</p></div>';
}
$result->free();
$most_recent_chats->close();
} else {
//Query 2 from above is repeated; basically, skips adding new message
//and simply retrieves any other new messages
$query2 = "SELECT * FROM `chat_global` WHERE id>'$most_recent_chat';";
$most_recent_chats = new mysqli($host,$user,$pass,$game_db);
if(!$result = $most_recent_chats->query($query2)) {
die();
}
while($row = $result->fetch_assoc()) {
echo '<div class="chat-item" data-chat-id="' . $row['id'] . '">';
echo '<p class="chat-message"><strong>' . $row['sender'] . ': </strong>' . $row['message'] . '</p>';
echo '<p class="chat-time">' . $row['time'] . '</p></div>';
}
$result->free();
$most_recent_chats->close();
}
The if(isset($new_chat)) block is simple and it's not giving me problems. Basically, if there is a new message, it adds the new message to the chat database and then returns all messages with ID numbers higher than the most recent from the browser's point of view. This part works and returns its information to the browser within 1/4 second.
The else block in this code is where I seem to be having some problems. The else block is the same, line for line, as the second half of the if block (from $query2 down). It works, but very slowly; whereas the if block loads from the server in 1/4 second on average, the else block (which is less code) takes an average of 90 seconds to return data. The $.ajax call is the same function whether a user sent a message or not; the only difference is that the if block is referenced if a user sent a message (and the $.ajax call is therefore manual), but the else block is referenced automatically by a repeated setTimeout(function,5000) line in the browser.
I'm 99.9% certain that the setTimeout() is working properly, because if I manually set my $.ajax call to send a generic $new_chat (i.e., "This is a message.") the function works every time; every 5 seconds, it sends the chat, and 1/4 second later, I see it appear in my chat page as expected. (My chat page is populated fully by the above PHP; even messages sent from user A must be sent to the above file, processed, and sent back to user A, that way users can know that their message was sent.)
The bottom line is that I'm at a complete loss as to why this behavior is occurring. The $.ajax is in the same function whether it's automatic or manual; the PHP is the same code, and the slower block is also shorter to boot! The $.ajax call runs perfectly quickly when it's manual, and if a message is sent along with the automatic $.ajax it also runs perfectly quickly. I'm new to AJAX and jQuery so I would like to think that the problem lies with one of those technologies, but nothing makes sense at all from where I'm sitting.

PHP how to connect two players

I'm making a website. and one of the features i want it to have is to have a simple game that connects 2 players together. my problem is I don't know how to make it so both player are in the same "room" because on room holds only 2 players.
On way i approached this is once one player joined, he gets a "wait for next player" message and waits while sending to the database that one player have joined. how do i make it keep checking for the next 3 minutes if the next player joined?
UPDATE
First here is the code so far:
<html>
<title>SiteName (test)</title>
<head>
<?php
$servername = "localhost";
$u
sername =
$password =
$dbname =
try
{
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare('SELECT * FROM game');
$stmt->execute(array('gameID' => $gameID));
while($row = $stmt->fetch()) {
print_r($row);
echo "<br />\n";
}
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
?>
<button onclick="myFunction()" id="w">Look for Game</button><br>
<script>
function myFunction() {
var elem = document.getElementById("w").innerHTML = "Wait";
var counter = 10;
var label= document.getElementById("lbl");
var counter = 10;
var clabel= document.createElement("p");
clabel.innerHTML = "You can download the file in 10 seconds.";
var id;
label.parentNode.replaceChild(clabel, label);
id = setInterval(function() {
counter--;
if(counter < 0) {
clabel.parentNode.replaceChild(label, clabel);
clearInterval(id);
} else {
clabel.innerHTML = "You can download the file in " + counter.toString() + " seconds.";
}
}, 1000);
}
</script>
<?php
$conn = null;
?>
</body>
</html>
Am trying to make it so that if the first player joined, he will be waiting (i have it for 10 seconds here as a test) until the other joins. the way am trying to do it is to have a field in the database will know if the a player is in that page and await the next player. I read something about long polling but not sure how to implement it for my case.
Any feed back would be helpful, Thank you
PHP is not the best language to do this in, but if you still want to do it.
Look into using Ratchet (http://socketo.me/), which is a PHP websocket library. A websocket is full duplex, meaning that a connection between the server and client is kept open. Game state and player actions can then be communicated through this.
http://socketo.me/docs/hello-world is an example you can learn from.
first you will want javascript or some client side code to handle this. as php will execute on the server side then display to the user. if you use ajax with javascript you can get the client side and server side to work together.
you will want to use a while loop, in this loop you will set a timeout.
in the while loop you can call the ajax script you want untill you get your result you want. I'm assuming you plan on making this a turn by turn game for the players. you will want a table that sets "true" to if player 1 or player 2 are in the game. if both are turn then the game begins.
Hope this logic helps

Trying to reduce memory usage of script

I am a math teacher who has built an online testing site for my school to use (aka, not a pro). The site has worked well but as the amount of usage at my school increases I am starting to run into memory problems (I think). After I have about 50 to 60 users simultaneously using the site the whole website begins to crash, it will come back up after a few minutes. I never have this problem with low usage. The page where students take their quiz loads 10 questions on the page, each multiple choice with 4 radio options. (Not a lot of jquery going on). Each time the user clicks an answer I am using ajax to store their answer in the database. Below is the jquery code that sends their clicks as they take the quiz.
$('input:radio').click(function(){
var questionId = $(this).parent().parent().find('.qid').val();
var answer = $(this).val();
$.ajax({
type: "POST",
url: "insertqanswerajax.php",
data: {questionId: questionId, answer: answer},
});
});
When I load system process in my cpanel I see there are 5 different processes running, each around 80 megabytes. The maximum in my php.ini is set to 540MB. If I check the page with memory_get_peak_usage() it never reads above about half a megabyte, however in the console timeline I can see the memory usage is almost up to 10 megabytes for one user (images below). What do I need to check, or what is the best way to troubleshoot the discrepancy? What could be causing the problems? I can provide more information if needed, I am just not sure what all is relevant.
Thanks ahead of time for your help.
Here is the code for the php file accessed via ajax
<?php session_start();
include('../includes/startup.php');
$questionId = $_POST['questionId'];
$answer = $_POST['answer'];
insertQuizAnswer($questionId, $userId, $answer, 1);
?>
The function called in that file:
function insertQuizAnswer($questionId, $userId, $answer, $testId){
global $DB;
$standardsHandle = $DB->prepare("INSERT INTO quizanswers (questionid, userid,answer,testid)
VALUES (:questionId,:userId, :answer, :testId)
");
$standardsHandle->bindParam(':questionId', $questionId);
$standardsHandle->bindParam(':userId', $userId);
$standardsHandle->bindParam(':answer', $answer);
$standardsHandle->bindParam(':testId', $testId);
$standardsHandle->execute();
}
And the startup file loaded on both:
<?php
if(preg_match('/(?i)msie [2-7]/',$_SERVER['HTTP_USER_AGENT']))
{
// if IE < 8
echo "My Class Progress does not Work with this version of Internet Explorer</br>
<a href='https://www.google.com/intl/en/chrome/browser/'>Click Here to Download a more modern browser</a>";
exit;
}
else
{
}
if(isset($_POST['getGrade'])){
$_SESSION['gradeLevel'] = $_POST['getGrade'];
}
if(isset($_POST['getSubject'])){
$_SESSION['subject'] = $_POST['getSubject'];
}
include_once('../functions/userfunctions.php'); //all functions
include_once('../functions/goalfunctions.php'); //all functions
include_once('../functions/modulefunctions.php'); //all functions
include_once('../functions/globalfunctions.php'); //all functions
include_once('../functions/skillfunctions.php'); //all functions
include_once('../functions/quizfunctions.php'); //all functions
include_once('../functions/practicefunctions.php'); //all functions
include_once('../functions/benchmarkfunctions.php'); //all functions
include_once('../functions/dockfunctions.php'); //all functions
include_once('../functions/dashboardfunctions.php'); //all functions
include_once('../functions/notificationfunctions.php'); //all functions
include_once('../includes/connect.php'); //connect to database
$userSubject = $_SESSION['subject'];
$userGradeLevel = $_SESSION['gradeLevel'];
$userId = $_SESSION['userId'];
if ($_SESSION['loggedIn'] == 'true'){
}
else{
header('location: ../../index.php');
die();
}
?>
Here is the connect.php file that is accessed:
try {
$DB = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch(PDOException $e) {
echo $e->getMessage();
}
The amount memory used is dependent on ini_set('memory_limit'); This amoutn is reserved by Apache, it doesn't matter how much the script actually uses until it runs out of memory.

PHP script is still running on server, but the webpage display has stopped

I wrote a PHP script to push notifications using APNS. I added a PHP progress bar to monitor how many users that have been pushed. The progress bar is displayed in the PHP page. I also keep updating a MySOL database to record the number. This script is expected to run a very long time. After running for about 3 hours, the PHP page (with progress bar) is stopped, but when I check the database, the number of pushed users is still increasing. This means the script is still running in server's memory, but why has the page display stopped?
here is some code:
$count = 1;
while($row = mysql_fetch_array( $result )) {
$pushToken = $row['pushToken'];
$result2 = mysql_query("SELECT COUNT(*) FROM deactivated_pushtokens WHERE pushToken LIKE '$pushToken'");
list($token_deactivated) = mysql_fetch_row($result2);
if ($token_deactivated==0){
if ($row['pushToken']!=""){
if (strlen($row['pushToken']) == 64){//All valid push tokens will have a 32x2=64 length
//echo "<br>$count. Sending push to ".$row['deviceID']." Device token = ".$row['pushToken'];
//echo "<br><br>";
if($count > $sendThreshold)
{
$pushMessage->sendMessage($row['pushToken'],$count,$appVersion,$mode,$message, $push_id);
}
if($count >= $push_update_count * $push_update_interval)
{
$pushlog_update = mysql_query("UPDATE pushlogs SET num_push_sent = '".$count."' WHERE push_id = '".$push_id."'");
if(!$pushlog_update)
{
// echo "pushlog table update error: ".mysql_error."<br />";
}
/* if($count<=$maxBar) // if failed again commment out and use block bleow
{
$prb->moveStep($count);
}
*/
$push_update_count++;
}
if($count >= $update_progressbar_count * $update_progressbar_interval)
{
if($count<=$maxBar)
{
$prb->moveStep($count);
}
$update_progressbar_interval++;
}
$count++;
// move the Bar
Perhaps the page display stopped due to the configuration of apache in httpd.conf
KeepAliveTimeout 300
PHP still running due to the property max_execution_time on php.ini
Just to notice, you are not calling the mysql_error function at all, replace the line:
echo "pushlog table update error: ".mysql_error."";
with this one:
echo "pushlog table update error: ".mysql_error()."<br />";
Further more, what you are doing is very bad practice. Try making an updater, keep you position into a session, and update/refresh the page and continue from where you left the execution. And if you do not have a tim_out limit in your .htaccess doesn't mean anything. And sometimes you might just not set the time limit.
Try refreshing page first, to see if it helps you. You can use a html meta tag for that. or:
header('Location: thispage.php');
And make each step of you program into a request.

Categories