最近在一家外企实习,主要做测试的工作,接触了很多类Unix平台,像Linux,Solaris,Hpia,Aix,Lps等,经常要清理环境,比如kill进程,kill内存等,但是这个手打很繁琐。在网上搜了下,没有找到能实现可视化的杀进程的程序。正好最近在学习php,技术也比较菜,就打算献丑用php写一个基于SSH2远程登录的kill进程和清理内存的程序,同样支持以上所有的类Unix平台。
其实这个说白了,就是进行SSH2远程登录后,利用ps -ef|grep XXXX来获取自己的进程信息和ipcs |grep XXXX获取自己的内存信息,然后调用ssh2.php的函数执行$ssh->exec()执行command,就可以实现。不过为了实现可视化,可以通过鼠标点击,就能杀掉对应的进程和内存,还是需要一些前后端的配合。
前台的tools.html,用到了jquery,简单的收集host信息,并且利用2次ajax,在两个div中加载tool.php返回的信息,第一次加载Show的信息,第二次加载Kill后的信息。
<h2><font size="6" face="Times" color= 0000CC >Tools </font></h2>
<hr>
<br>
<label for=""><font color="#4B0082" size="3"><b>You Can Do :</b></font></label>
<select id="task_type_kill">
<option value ="killProcess" >Kill Process</option>
<option value ="killIpcs" >Kill Ipcs</option>
</select>
<p>
<label for=""><font color="#4B0082" size="3"><b>HOST :</b></font></label>
<input id="host_kill" type="text" size="20"">
<br>
<div>
<div id="kill_process" align="left" >
<button id="show_process_btn" type="submit"><b>Show Process</b></button>
<button id="kill_process_btn" style="display:none"><b>Kill Selected Process</b></button>
</div>
<div id="kill_ipcs" align="left" style="display:none">
<button id="show_ipcs_btn" type="submit"><b>Show ipcs</b></button>
<button id="ipcrm_btn" style="display:none"><b>Kill Selected Ipcs</b></button>
</div>
</div>
<br>
<div id="showResult"></div>
<div id="actionResult"></div>
<hr>
<br>
<script src="jquery-1.11.3.min.js"></script>
<script>
$(function() {
var map={"killProcess":"kill_process","killIpcs":"kill_ipcs"};
$("#task_type_kill").bind("change",function(){
var divId=map[this.value];
$("#"+divId).show().siblings().hide();
});
///show processes
$("button#show_process_btn").click(function(){
if($("#host_kill")[0].value==""){alert("Empty Host!");return;}
$("#actionResult").html("");
var host=$("#host_kill")[0].value;
$("#kill_process_btn").show();
$("#showResult").load("tools_action.php?action=showprocess",{host:host},function(){
});
});
kill processes
$("button#kill_process_btn").click(function(){
var checkedArray=new Array();
var host=$("#host_kill")[0].value;
var subChecked=$("input[name='sub']:checked");
if(subChecked.length==0){alert("No process selected!");return;}
for(i=0;i<subChecked.length;i++){
line=subChecked.eq(i).parent().next().text();
checkedArray.push(line);
}
//alert(subChecked.length);
$("#actionResult").load("tools_action.php?action=killprocess",{host:host,processLines:checkedArray},function(){//向tools_action.php传递选取的所有进程记录
});
});
show ipcs
$("button#show_ipcs_btn").click(function(){
if($("#host_kill")[0].value==""){alert("Empty Host!");return;}
$("#actionResult").html("");
var host=$("#host_kill")[0].value;
$("#ipcrm_btn").show();
$("#showResult").load("tools_action.php?action=showipcs",{host:host},function(){
});
});
//kill ipcs
$("button#ipcrm_btn").click(function(){
var checkedArray=new Array();
var host=$("#host_kill")[0].value;
var subChecked=$("input[name='sub']:checked");
if(subChecked.length==0){alert("No ipcs selected!");return;}
for(i=0;i<subChecked.length;i++){
line=subChecked.eq(i).parent().next().text();
checkedArray.push(line);
}
//alert(subChecked.length);
$("#actionResult").load("tools_action.php?action=killipcs",{host:host,ipcsLines:checkedArray},function(){<span style="font-family: Arial, Helvetica, sans-serif;">//向tools_action.php传递选取的所有ipcs记录</span>
});
});
});
</script>
在后台的tools_action.php中,首先要引入SSH2.php文件,include('Net/SSH2.php'),然后会发现在class Net_SSH2中,有一些要用到的函数。
function Net_SSH2($host, $port = 22, $timeout = 10)//建立SSH2连接
function login($username,$password)//登录
function exec($command, $callback = null)//执行command
在tools_action.php中,使用前两个函数进行登录,$username和$password可以从前台获取的$_SESSION中取得,$host从前台tool.html取得。
<?php
if (! $ssh = new Net_SSH2($server, '22')) {
echo "Can't create SSH session to host :".$server;
return false;
}
//if you can't log on...
if (@!$ssh->login($username, $password)) {
echo "Login Failed! Host name or service not known!";
return false;
}
if($_GET["action"]=="showprocess"){
$command="ps -ef|grep -v grep|grep -v ssh|grep -v pts| grep $username";
$output=$ssh->exec($command);
echo "<b>$command</b> on <b>$server</b>. <br><br>";
$lines = explode("\n", $output);//分行
array_pop($lines);//收集的ps后的信息,最后一行为空,需要pop掉
echo "<table border='1' class='bordered'><th><input type=\"checkbox\" id=\"ckAll\" value=\"cc\"></th><th>Process Result Lines</th>";
for ($i=0;$i<count($lines);$i++){
echo "<tr><td><input type=\"checkbox\" name=\"sub\" value=\"cc\"></td><td>$lines[$i]</td>";
}
echo "</table>";
}
else if($_GET["action"]=="killprocess"){
$processLines=$_POST["processLines"];
//print_r($processLines);
$resultArray=array();
foreach ($processLines as $line){
$pid=getPidFromLine($line);
//$output=$ssh->exec("/remote/repqa11/users/junjiewu/git_rqca/RQCA/scripts/kill_pro.sh $pid");
$output=$ssh->exec("kill -9 $pid");//执行kill -9杀死进程
if($output==""){
echo "<font color='green'><b>SUCCESS: </b></font>kill -9 $pid. <br>";
}
else{
echo "<font color='red'><b>FAIL:</b></font>kill -9 $pid : $output <br>";
}
}
}
else if($_GET["action"]=="showipcs"){
$command="ipcs| grep $username";
$output=$ssh->exec($command);
echo "<b>$command</b> on <b>$server</b>.<br><br>";
if($output==null){
echo "No ipcs on $server !";
}
else {
$lines = explode("\n", $output);
array_pop($lines);
//echo "<pre>".$output."</pre>";
echo "<table border='1' class='bordered'><th><input type=\"checkbox\" id=\"ckAll\" value=\"cc\"></th><th>IPCS Result Lines</th>";
for ($i=0;$i<count($lines);$i++){
echo "<tr><td><input type=\"checkbox\" name=\"sub\" value=\"cc\"></td><td>$lines[$i]</td>";
}
echo "</table>";
}
}
else if($_GET["action"]=="killipcs"){
$ipcsLines=$_POST["ipcsLines"];
if (trim($ssh->exec("uname"))!="Linux"){//除linux外的其他类unix平台,ipcs后第一列显示的是所属的进程间通信类型,如m,s,q,故可以直接获取ipcs后 //第一列信息,进行ipcrm -method 进行清理
foreach ($ipcsLines as $line){
$shid=getShidFromLine($line);
$method=$line[0];
//$output=$ssh->exec("/remote/repqa11/users/junjiewu/git_rqca/RQCA/scripts/kill_pro.sh $pid");
$output=$ssh->exec("ipcrm -$method $shid");
if($output==""){
echo "<font color='green'><b>SUCCESS: </b></font>ipcrm -$method $shid . <br>";
}
else{
echo "<font color='red'><b>FAIL:</b></font>ipcrm -$method $shid : $output <br>";
}
}
}
else {
foreach ($ipcsLines as $line){//linux和其他类unix平台不同,ipcs后第一列显示不是m,s,q,所以需做特殊处理。
$shid=getShidFromLine($line);
//$output=$ssh->exec("/remote/repqa11/users/junjiewu/git_rqca/RQCA/scripts/kill_pro.sh $pid");
$output_m=$ssh->exec("ipcrm -m $shid");//这种方法。。。很暴力,但是我也没有更好的办法了,Linux为什么和其他平台不一样。。。
$output_s=$ssh->exec("ipcrm -s $shid");
$output_q=$ssh->exec("ipcrm -q $shid");
if($output_m==""||$output_s==""||$output_q==""){
echo "<font color='green'><b>SUCCESS: </b></font>ipcrm -m|-s|-q $shid.<br>";
}
else{
echo "<font color='red'><b>FAIL:</b></font>ipcrm -m|-s|-q $shid : $output <br>";
}
}
}
}
function getPidFromLine($line){//从每行记录里获取进程的id
$line=trim($line);
$pid_start=strpos($line, " ");
$sub=substr($line, $pid_start+1);
$sub=trim($sub);
$pid_end=strpos($sub, " ");
$pid=substr($sub,0,$pid_end);
return $pid;
}
function getShidFromLine($line){//从每行记录里获取ipcs的id
$line=trim($line);
$shid_start=strpos($line, " ");
$sub=substr($line, $shid_start+1);
$sub=trim($sub);
$shid_end=strpos($sub, " ");
$shid=substr($sub,0,$shid_end);
return $shid;
}
?>
顺便在tools.php中,把前台的控制全选checkbox的js代码返回:(大概是因为两次ajax,如果把这段代码写在tools.html中的话,全选不会生效,具体我也不知道,望有大神能告知)。
<script>
$("#ckAll").click(function() {
$("input[name='sub']").prop("checked", this.checked);
});
$("input[name='sub']").click(function() {
var $subs = $("input[name='sub']");
$("#ckAll").prop("checked" , $subs.length == $subs.filter(":checked").length ? true :false);
});
</script>
然后就可以通过简单的输入host之后(前提是有username和password的session),点击ShowProcess或者ShowIpcs,进行显示,对返回的结果进行筛选,然后点击kill,之后就能看到kill的结果了。每次执行的时间大概1s-2s,要比人工kill -9快很多吧!
kill process:
kill process result:
kill ipcs:
kill ipcs result:
End
PS:1.本人小菜鸟,第一次写博文,如果有什么地方写的不对,希望能和大家广泛的交流,恳请大家指正。
2.可能这个程序很简单,不过对于清理环境来讲,还是比较迅捷的。
3.因为有一些公司的敏感信息,所以某些地方打了码。