Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Reboot remote Linux server from PHP PowerShell web server

This web portal is part of Executing a Linux programs from PHP web server. In earlier part I used only PHP to remotely execute commands on Linux server. In this it is a combination of PHP and PowerShell. Once you launch portal you will need to provide Domain username and password to authenticate and Linux server IP/Hostname to reboot Server.

To run command on Linux from windows it uses plink.exe tool utility to connect through SSH. I have provided the plink.exe in the zip file that you will need to copy it on PHP Web server under C:\Windows. To host PHP Web server I am using  XAMPP application for windows. I have downloaded it and installed. run XAMPP controller and start Apache services as shown in Executing a Linux programs from PHP web server. Copy complete project under C:\xampp\htdocs. And load the URL in browser.

Microsoft IIS xampp PHP web server linux server reboot from html web server php submission of reboot scheduled shutdown -c reboot -f reset lorem ipsum devops automation.png

Whether user able to restart Linux server remotely, success or failure, it will register a log in the file under /log/reboot.log.

xampp php web server iis information internet services web services php remotely execute commands program on linux ubuntu system server logs who rebooted.png

Download this complete project PHP_reboot_linux_PowerShell.zip here or it is also available on github.com.

How to Setup this project?

On the Windows server where you installed XAMPP / PHP webserver. Configure and add Domain Users to Remote Management Users in Local groups from Computer Management. (Members of this Remote Management Users group can access WMI resources over management protocols (such as WS-Management via the Windows Remote Management service). This applies only to WMI namespaces that grant access to the user.). For lab purpose I have added large group such as Domain Users. You can tweak it with your custom group. With custom group you can achieve time based access to users on the group to perform reboot action.

IIS PHP web server php cgi xampp local users and groups computer management remote management users execute remote command on windows microsoft and linux programs php web internet devops automation.png

Below is the file code used in this project.

Index.html - This is landing page where you put credentials and Linux server information.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<!doctype html>
<html lang=en>
	<head>
		<meta charset=utf-8>
		<title>Linux Reboot Tool</title>
		<link rel="icon" type="image/x-icon" href="favicon.ico">
		<style>
			body {
				font-family: Calibri, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
				text-align: center;	
				font-weight: lighter;
			}
			 
			div {
				margin: auto;
				width: 50%;
				border: 3px solid coral;				
				padding: 10px;
				border-radius: 0.3cm;
			}
			table {
				margin: 0 auto; /* or margin: 0 auto 0 auto */
				/* color: #606060; */
			}
			.toolheader {
				font-size: x-large;
				font-weight: 600;
			}
			
			input[type=text] {
				width: 100%;
				padding: 12px 20px;
				margin: 8px 0;
				box-sizing: border-box;
				border: 1px solid gray;
				outline: none;
				color: #606060;
			}
			
			input[type=text]:focus {
				background-color: coral;
				color: white;
				border: 1px solid gray;
			}
			
			input[type=password] {
				width: 100%;
				padding: 12px 20px;
				margin: 8px 0;
				box-sizing: border-box;
				border: 1px solid gray;
				outline: none;
				color: #606060;
			}		

			input[type=password]:focus {
				background-color: coral;
				color: white;
				border: 1px solid gray;
			}			

			.button {
				background-color: coral; /* Green */
				border: none;
				color: white;
				padding: 15px 32px;
				text-align: center;
				text-decoration: none;
				display: inline-block;
				font-size: 16px;
				margin: 4px 2px;
				cursor: pointer;
				-webkit-transition-duration: 0.4s; /* Safari */
				transition-duration: 0.4s;
			}

			.button:hover {
				box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
			}

			.loading {
				margin-left: auto;
				margin-right: auto;
				width: 128px;
				height: 128px;
				display: none;
			}
			
			/* .toolbox {
				display: none;
			} */
		</style>
		<script>
			function ClearFields() {
				// document.getElementById("searchBox").value = '';
				document.getElementById("user").value = "";
				document.getElementById("pass").value = "";
				document.getElementById("ip").value = "";
			}
		</script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
	</head>
	<body>
		<div>
			<table class="toolheader toolbox" id="toolbox">
				<tr>
					<td colspan="2">
						<img src="loremipsumlogo.png" alt="loremipsumlogo" width="256px">
					</td>
				</tr>
				<tr>
					<td style="text-align: center; vertical-align: middle;">Linux Server Reboot</td>
					<td><img src="reboot.png" alt="reboot.icon" width="48" height="48"></td>
					<td style="text-align: center; vertical-align: middle;">tool</td>
				</tr>
			</table>
			<table class="toolbox">
				<tr>
					<th>UserName &nbsp &nbsp</th>
					<td><input id="user" type="text" name="username" value="UserName" autocomplete="UserName"></td>
				</tr>
				<tr>
					<th>Password &nbsp &nbsp</th>
					<td><input id="pass" type="password" name="password" value="Password"></td>
				</tr>
				<tr>
					<th>Server &nbsp &nbsp</th>
					<td><input id="ip" type="text" name="servername" value="Type server hostname or IP"></td>
				</tr>
				<!-- <tr>
					<th></th>
					<td><button class="button searchButton" id="login">Log In</button></td>
				</tr> -->
			</table>
			<button class="button searchButton toolbox" id="rebootserverbutton">Reboot Server</button> <!-- //instead of Class if id is used use #searchButton -->
			<input class="button clearButton toolbox" type="reset" name="Clear" value="Clear" onclick="ClearFields();"><br>
			<br>
			<br>			
			<img class="loading" id="loading" src="loading.gif" alt="Loading, Waiting, Spinner">
		</div>
		<p class="showData"></p>  <!--Show data from php here -->

		<script>
			$(document).ready(function(){
				$("#rebootserverbutton").click(function(){	//instead of Class if id is used use #searchButton
					//document.getElementById("loading").style.display = 'block';
					$("#loading").css("display", "block")
					$("p.showData").html('')
					//document.getElementClassNyName("showData").innerHTML = "";
					$.ajax({
						method: "POST",
						url: "wrap.php",
						data: { 
							//text: $("p.unbroken").text(), //keep adding parameters here with comma
							// servername: $("input:text").val(), //keep adding parameters here with comma
							servername: $("input[name=servername]").val(), //keep adding parameters here with comma
							username: $("input[name=username]").val(),
							password: $("input[name=password]").val(),
						}
					})
					.done(function( response ) {
						$("p.showData").html(response); //class showData reference
						//document.getElementById("loading").style.display = "none";
						$("#loading").css("display", "none")
					});
				});
			});	
		</script>
	</body>
</html>

wrap.php - Information fed into landing page will be passed to this PHP code and it will execute PowerShell script to reboot Linux server.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
	    $username = isset($_POST['username']) ? $_POST['username'] : '';
		$password = isset($_POST['password']) ? $_POST['password'] : '';
		$servername = isset($_POST['servername']) ? $_POST['servername'] : '';
	
	    echo "<div id='phpBox' class='phpData' style='background-color: coral; color: white'>";
	    #$userName = shell_exec('powershell -ExecutionPolicy Unrestricted -Command $env:USERNAME');
	    echo "<h3 class='maintext' style='display: block;'>'<strong>$username</strong>' trying to submit reboot request for server '<strong>$servername</strong>'</h3>"; 
	
	    $psfileoutput = shell_exec("PowerShell -ExecutionPolicy Unrestricted -NonInteractive -File Reboot-LinuxServer.ps1 -Server $servername -UserName $username -Password $password"  );
	    echo '<div>' . $psfileoutput . '</div>';
	echo "</div>";

Reboot-LinuxServer.ps1 - In the background below PowerShell script will be executed. Change Linux user credentials on line 27 and 28. You can make addition to this ps1 such a way that only allowed users on allowed servers from database can run this Web tool.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
param(
    [string]$Server,
	[string]$UserName,
	[string]$Password
)

$cimsession = $null

try {
	$secureString = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
	$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, ($secureString | ConvertTo-SecureString)
	$cimsession = New-CimSession -ComputerName $env:COMPUTERNAME -Credential $credential -ErrorAction Stop
}
catch 
{
	$error.exception.message > c:\temp\command_output.txt
	"<h3>
		Reboot job submission failed $Server `n
		The user name or password is incorrect. `n
	</h3>"
    #$htmlReport | Out-File c:\temp\logs.txt -Append
	"$server,$UserName,WrongPassword,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append
}

if ($null -ne $cimsession)
{
	echo y | plink -ssh -no-antispoof -pw ubuntu ubuntu@$server 'sudo whoami' > 'C:\xampp\htdocs\reboot\log\first_command_output.txt' 2>&1
	echo y | plink -ssh -no-antispoof -pw ubuntu ubuntu@$server 'sudo shutdown -r' > 'C:\xampp\htdocs\reboot\log\second_command_output.txt' 2>&1
	$log = Get-Content C:\xampp\htdocs\reboot\log\second_command_output.txt
	$mainMessage = $log[0].trim('plink : ') -creplace ('Shutdown','Reboot')
	$htmlReport = "<h4>Server reboot job submitted for '$Server'</h4>"
	$htmlReport += "<h3>$mainMessage</h3>"	
	if ($mainMessage -match 'scheduled')
	{
		"$server,$UserName,Scheduled,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append
	}
	elseif ($mainMessage -match 'fatal')
	{
		"$server,$UserName,Error,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append
	}
	else {
		"$server,$UserName,unknown,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append
	}
	
	$htmlReport
}

Useful Articles
Executing PowerShell script from PHP HTML web server
Send system disk space utilization HTML report Email using PowerShell
Send Email using PowerShell with .net object System.Net.Mail.MailMessage
PowerShell XML OperationStopped: No coercion operator is defined between types 'System.Object&' and 'System.Object'
Powershell Create new file if not exist, if exist Rename file
PowerShell Create XML document with XmlWriter .net object
PowerShell save export data to XML file
Bulk change multiple file names with OneLiner PowerShell command
Resolved PowerShell Visual studio code stuck with 'Starting up PowerShell' in status bar
Building basic simple Web Server using PowerShell
Running Your First PowerShell Scripts With Jenkins and Git
Git clone or push Missing or invalid credentials fatal authentication failed
PowerShell How to find file and folders in Azure Storage Account Blobs and Containers

Go Back

Comment

Blog Search

Page Views

12063589

Follow me on Blogarama