前段時間加入性能測試組,並參與搭建基於locust的性能測試平台,我分到的任務相對獨立,開發locust的啟動接口和停止運行接口,現開發的差不多了,做一個總結
一、locust運行的相關內容
二、locust操作相關的linux命令
啟動locust:"locust -f /usr/fin/FinBomber/LF_"+taskCode+".py --host="+host+" -P "+port
殺掉所有在運行的locust進程:ps -ef |grep locust|grep -v grep | awk '{print $2}' | xargs kill -9
獲取所有在運行的locust進程:ps -ef |grep locust|grep -v grep | awk '{print $2}'
獲取指定port對應的pid:"/usr/sbin/lsof -i:"+port+"|grep -v grep | awk '{print $2}'|awk 'NR==2{print}'"
殺掉該pid:"kill -9 "+locustPid
三、接口編寫思路
1.編寫兩個接口,一個啟動,同時更新數據庫相關字段,另一個為停止運行,同時更新數據庫相關字段。如下圖
2.代碼敲着敲着問題就暴露了
問題:java連linux執行啟動locust命令(locust -f /usr/fin/FinBomber/LF_"+taskCode+".py --host="+host+" -P "+port),啟動是啟動了,但是會一直卡那,代碼不會繼續往下走(往下主要是執行更新數據庫操作,后續停止運行接口才能獲取到pid,從而殺掉進程),完全不知道咋整,一度覺得整不出來的時候,靈光一現
解決方法:既然啟動命令可以完成啟動,只是不能繼續往下走代碼,那就讓它別走了,再開一個接口來完成這件事不就好了,傻缺!瞬間覺得我真是天才
最終方案:啟動編寫兩個接口,一個啟動,一個更新數據庫
-------------------------------解決方法更新---------------------------------
用多線程!!!!瞬間覺得自己之前真是井底之蛙
四、上代碼
java連接linux執行命令代碼如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class LinuxCommandUtil {
private static final Logger log = LoggerFactory.getLogger(LinuxCommandUtil.class);
private static String DEFAULTCHART="UTF-8";
/**
* 登錄主機
* @return
* 登錄成功返回true,否則返回false
*/
public static Connection login(String ip,
String userName,
String userPwd){
boolean flg=false;
Connection conn = null;
try {
conn = new Connection(ip);
conn.connect();//連接
flg=conn.authenticateWithPassword(userName, userPwd);//認證
if(flg){
log.info("=========登錄成功========="+conn);
return conn;
}
} catch (IOException e) {
log.error("=========登錄失敗========="+e.getMessage());
e.printStackTrace();
}
return conn;
}
/**
* 遠程執行shll腳本或者命令
* @param cmd
* 即將執行的命令
* @return
* 命令執行完后返回的結果值
*/
public static String execute(Connection conn,String cmd){
String result="";
try {
if(conn !=null){
Session session= conn.openSession();//打開一個會話
session.execCommand(String.valueOf(cmd));//執行命令
result=processStdout(session.getStdout(),DEFAULTCHART);
//如果為得到標准輸出為空,說明腳本執行出錯了
if(StringUtils.isBlank(result)){
log.info("得到標准輸出為空,鏈接conn:"+conn+",執行的命令:"+cmd);
result=processStdout(session.getStderr(),DEFAULTCHART);
}else{
log.info("執行命令成功,鏈接conn:"+conn+",執行的命令:"+cmd);
}
conn.close();
session.close();
}
} catch (IOException e) {
log.info("執行命令失敗,鏈接conn:"+conn+",執行的命令:"+cmd+" "+e.getMessage());
e.printStackTrace();
}
return result;
}
/**
* 解析腳本執行返回的結果集
* @param in 輸入流對象
* @param charset 編碼
* @return
* 以純文本的格式返回
*/
public static String processStdout(InputStream in, String charset){
InputStream stdout = new StreamGobbler(in);
StringBuffer buffer = new StringBuffer();;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(stdout,charset));
String line=null;
while((line=br.readLine()) != null){
buffer.append(line+"\n");
}
} catch (UnsupportedEncodingException e) {
log.error("解析腳本出錯:"+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
log.error("解析腳本出錯:"+e.getMessage());
e.printStackTrace();
}
return buffer.toString();
}
//獲取未占用的端口號
public static String getFreePort(){
ServerSocket serverSocket = null; //讀取空閑的可用端口
String localIp = null;
try {
serverSocket = new ServerSocket(0);
localIp = serverSocket.getInetAddress().getLocalHost().getHostAddress();
} catch (IOException e) {
e.printStackTrace();
}
String port = String.valueOf(serverSocket.getLocalPort());
System.out.println("系統分配的端口號 port="+port);
System.out.println("當前本機ip:"+localIp);
//獲取當前進程ID
String processName =
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
System.out.println("當前進程ID:"+Long.parseLong(processName.split("@")[0]));
return port;
}
public static String execLocalCmd(String cmd){
String line="";
try{
Runtime rt = Runtime.getRuntime();
//執行命令, 最后一個參數,可以使用new File("path")指定運行的命令的位置
Process proc = rt.exec(cmd,null,null);
InputStream stderr = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr,"GBK");
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) { // 打印出命令執行的結果
System.out.println(line);
}
}catch (Exception e){
e.printStackTrace();
}
return line;
}
public static void main(String[] args) {
// long currentTimeMillis = System.currentTimeMillis();
String ip = "X.X.X.X";
String username = "XXX";
String password = "XXXXXX";
// String cmd = "sh runLocust.sh";
String cmd = "ps -ef |grep locust|grep -v grep | awk '{print $2}' | xargs kill -9";
Connection connection = login(ip, username, password);
String execmd = execute(connection, cmd);
// System.out.println(execmd);
// long currentTimeMillis1 = System.currentTimeMillis();
// System.out.println("ganymed-ssh2方式"+(currentTimeMillis1-currentTimeMillis));
getFreePort();
}
}