I have two php pages. 1st page will load at client browser and display buttons. If clicked it will use ajax call to execute my second php page. The 2nd php page connects to a server using ssh2_exec, execute some shell scripting and display the output on the same loaded page without refresh. I am able to achieve this with my existing pages. But it displays complete output at once after 2nd page completes its execution. I want as the 2nd php page start execution the output should start displaying line by line on client browser.
Below are my 2 pages:
php page1:
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="../css/new_style.css" />
</head>
<script>
function disable()
{
document.getElementById("save").disabled = true;
}
function enable_button()
{
document.getElementById("save").disabled = false;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById('output').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open('GET', 'arg0_orgcmd_exec.php?id=118' , true);
xmlhttp.send();
}
function disable_button()
{
document.getElementById("execute").disabled = true;
}
</script>
<body>
<div class="main_body">
<form action=" " method="" name="output_frame">
<center>
<input class=" " id="execute" onclick="enable_button();" type="button" name="submit" value="Execute" />
<input class=" " disabled name="save" id="save" type="submit" onclick="disable_button();" value="Save In File" />
<input class=" btn btn-danger back-btn" type=button onclick="location.href='main_menu.php'" value='Close' />
</center>
</form>
</div>
<div id="output" class="output">
</div>
<iframe name="iframe_output"></iframe>
</body>
</html>
arg0_orgcmd_exec.php :
<?php
$page_id = $_GET['id'];
$conn = ssh2_connect($server_ip,$server_port);
ssh2_auth_password($conn, $server_id, $server_pass);
//Checking web.lock file
$stream_lock = ssh2_exec($conn, "ls /tmp/web.lock" );
stream_set_blocking($stream_lock, true);
$check_lock = stream_get_contents($stream_lock);
if(empty($check_lock)) {
$script_output1 = ssh2_exec($conn, "touch /tmp/web.lock ; my_script.sh ; rm -rf /tmp/web.lock" );
stream_set_blocking($script_output1, true);
echo "<pre>";
while($line1 = fgets($script_output1)) {
echo $line1;
ob_flush();
flush();
}
echo "</pre>";
echo "<br />";
echo "<h2>Script Output Finished!!!!<h2>";
echo "<br />";
}else {echo "Already one pending script running in selected server. Kindly wait!!!"; }
fclose($script_output1);
ssh2_exec($conn, 'exit');
unset($conn);
?>
The problem with your code is that with AJAX you can't get the data as it is available, only the complete response after the server side script closes the connection.
One solution is to use Server Sent Events
var evtSource = new EventSource("arg0_orgcmd_exec.php?id=118");
evtSource.onmessage = function(e) {
var newElement = document.createElement("div");
newElement.innerHTML = "<br />message: " + e.data;
document.getElementById('output').appendChild(newElement);
}
Your PHP script needs modifications also:
header("Content-Type: text/event-stream
");
$page_id = $_GET['id'];
$conn = ssh2_connect($server_ip,$server_port);
ssh2_auth_password($conn, $server_id, $server_pass);
//Checking web.lock file
$stream_lock = ssh2_exec($conn, "ls /tmp/web.lock" );
stream_set_blocking($stream_lock, true);
$check_lock = stream_get_contents($stream_lock);
if(empty($check_lock)) {
$script_output1 = ssh2_exec($conn, "touch /tmp/web.lock ; my_script.sh ; rm -rf /tmp/web.lock" );
stream_set_blocking($script_output1, true);
echo "event: commandStarted
";
while($line1 = fgets($script_output1)) {
echo 'data: ' . json_encode($line1) . "
";
ob_flush();
flush();
}
echo "event: commandEnded
";
} else {
echo 'data: "Already one pending script running in selected server. Kindly wait!!!"' . "
";
}
fclose($script_output1);
ssh2_exec($conn, 'exit');
unset($conn);