提交 c12c4dba 编写于 作者: K kohsuke

Added a probe for the running Maven process to obtain system properties,...

Added a probe for the running Maven process to obtain system properties, environment variables, thread dump, and the scripting console.


git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@6778 71c3de6d-444a-0410-be80-ed276b4c234a
上级 feaeb6e5
......@@ -262,10 +262,14 @@ public final class MavenModuleSetBuild extends AbstractBuild<MavenModuleSet,Mave
margs.addTokenized(project.getGoals());
Builder builder = new Builder(slistener, proxies, project.sortedActiveModules, margs.toList(), envVars);
MavenProbeAction mpa=null;
try {
mpa = new MavenProbeAction(project,process.channel);
addAction(mpa);
return process.channel.call(builder);
} finally {
builder.end(launcher);
getActions().remove(mpa);
process.discard();
}
}
......
package hudson.maven;
import hudson.EnvVars;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Hudson;
import hudson.remoting.Channel;
import hudson.util.RemotingDiagnostics;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Map;
/**
* UI for probing Maven process.
*
* <p>
* This action is added to a build when it's started, and removed
* when it's completed.
*
* @author Kohsuke Kawaguchi
* @since 1.175
*/
public final class MavenProbeAction implements Action {
private final transient Channel channel;
public final AbstractProject<?,?> owner;
MavenProbeAction(AbstractProject<?,?> owner, Channel channel) {
this.channel = channel;
this.owner = owner;
}
public String getIconFileName() {
if(channel==null) return null;
return "computer.gif";
}
public String getDisplayName() {
return Messages.MavenProbeAction_DisplayName();
}
public String getUrlName() {
if(channel==null) return null;
return "probe";
}
/**
* Gets the system properties of the JVM on this computer.
* If this is the master, it returns the system property of the master computer.
*/
public Map<Object,Object> getSystemProperties() throws IOException, InterruptedException {
return RemotingDiagnostics.getSystemProperties(channel);
}
/**
* Gets the environment variables of the JVM on this computer.
* If this is the master, it returns the system property of the master computer.
*/
public Map<String,String> getEnvVars() throws IOException, InterruptedException {
return EnvVars.getRemote(channel);
}
/**
* Gets the thread dump of the slave JVM.
* @return
* key is the thread name, and the value is the pre-formatted dump.
*/
public Map<String,String> getThreadDump() throws IOException, InterruptedException {
return RemotingDiagnostics.getThreadDump(channel);
}
public void doScript( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
// ability to run arbitrary script is dangerous,
// so tie it to the admin access
owner.checkPermission(Hudson.ADMINISTER);
String text = req.getParameter("script");
if(text!=null) {
try {
req.setAttribute("output",
RemotingDiagnostics.executeGroovy(text,channel));
} catch (InterruptedException e) {
throw new ServletException(e);
}
}
req.getView(this,"_script.jelly").forward(req,rsp);
}
}
package hudson.model;
import hudson.EnvVars;
import hudson.Functions;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
import hudson.tasks.Publisher;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Publisher;
import hudson.util.DaemonThreadFactory;
import hudson.util.RemotingDiagnostics;
import hudson.util.RunList;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -15,13 +14,9 @@ import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.management.ThreadInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
......@@ -257,14 +252,7 @@ public abstract class Computer extends AbstractModelObject {
* If this is the master, it returns the system property of the master computer.
*/
public Map<Object,Object> getSystemProperties() throws IOException, InterruptedException {
return getChannel().call(new GetSystemProperties());
}
private static final class GetSystemProperties implements Callable<Map<Object,Object>,RuntimeException> {
public Map<Object,Object> call() {
return new TreeMap<Object,Object>(System.getProperties());
}
private static final long serialVersionUID = 1L;
return RemotingDiagnostics.getSystemProperties(getChannel());
}
/**
......@@ -281,34 +269,9 @@ public abstract class Computer extends AbstractModelObject {
* key is the thread name, and the value is the pre-formatted dump.
*/
public Map<String,String> getThreadDump() throws IOException, InterruptedException {
VirtualChannel channel = getChannel();
if(channel==null)
return Collections.singletonMap("N/A","N/A");
return channel.call(new GetThreadDump());
return RemotingDiagnostics.getThreadDump(getChannel());
}
private static final class GetThreadDump implements Callable<Map<String,String>,RuntimeException> {
public Map<String,String> call() {
Map<String,String> r = new LinkedHashMap<String,String>();
try {
for (ThreadInfo ti : Functions.getThreadInfos())
r.put(ti.getThreadName(),Functions.dumpThreadInfo(ti));
} catch (LinkageError _) {
// not in JDK6. fall back to JDK5
r.clear();
for (Map.Entry<Thread,StackTraceElement[]> t : Thread.getAllStackTraces().entrySet()) {
StringBuffer buf = new StringBuffer();
for (StackTraceElement e : t.getValue())
buf.append(e).append('\n');
r.put(t.getKey().getName(),buf.toString());
}
}
return r;
}
private static final long serialVersionUID = 1L;
}
public static final ExecutorService threadPoolForRemoting = Executors.newCachedThreadPool(new DaemonThreadFactory());
//
......
......@@ -61,6 +61,7 @@ import hudson.util.HudsonIsLoading;
import hudson.util.MultipartFormDataParser;
import hudson.util.TextFile;
import hudson.util.XStream2;
import hudson.util.RemotingDiagnostics;
import hudson.widgets.Widget;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
......@@ -69,7 +70,6 @@ import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
import org.acegisecurity.ui.AbstractProcessingFilter;
import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
import static org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
......@@ -81,7 +81,6 @@ import org.kohsuke.stapler.StaplerProxy;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.springframework.util.StringUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
......@@ -1920,19 +1919,12 @@ public final class Hudson extends View implements ItemGroup<TopLevelItem>, Node,
String text = req.getParameter("script");
if(text!=null) {
GroovyShell shell = new GroovyShell();
StringWriter out = new StringWriter();
PrintWriter pw = new PrintWriter(out);
shell.setVariable("out", pw);
try {
Object output = shell.evaluate(text);
if(output!=null)
pw.println("Result: "+output);
} catch (Throwable t) {
t.printStackTrace(pw);
req.setAttribute("output",
RemotingDiagnostics.executeGroovy(text, MasterComputer.localChannel));
} catch (InterruptedException e) {
throw new ServletException(e);
}
req.setAttribute("output",out);
}
req.getView(this,"_script.jelly").forward(req,rsp);
......
package hudson.util;
import groovy.lang.GroovyShell;
import hudson.Functions;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ThreadInfo;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* Various remoting operations related to diagnostics.
*
* @author Kohsuke Kawaguchi
* @since 1.175
*/
public final class RemotingDiagnostics {
public static Map<Object,Object> getSystemProperties(VirtualChannel channel) throws IOException, InterruptedException {
if(channel==null)
return Collections.<Object,Object>singletonMap("N/A","N/A");
return channel.call(new GetSystemProperties());
}
private static final class GetSystemProperties implements Callable<Map<Object,Object>,RuntimeException> {
public Map<Object,Object> call() {
return new TreeMap<Object,Object>(System.getProperties());
}
private static final long serialVersionUID = 1L;
}
public static Map<String,String> getThreadDump(VirtualChannel channel) throws IOException, InterruptedException {
if(channel==null)
return Collections.singletonMap("N/A","N/A");
return channel.call(new GetThreadDump());
}
private static final class GetThreadDump implements Callable<Map<String,String>,RuntimeException> {
public Map<String,String> call() {
Map<String,String> r = new LinkedHashMap<String,String>();
try {
for (ThreadInfo ti : Functions.getThreadInfos())
r.put(ti.getThreadName(),Functions.dumpThreadInfo(ti));
} catch (LinkageError _) {
// not in JDK6. fall back to JDK5
r.clear();
for (Map.Entry<Thread,StackTraceElement[]> t : Thread.getAllStackTraces().entrySet()) {
StringBuffer buf = new StringBuffer();
for (StackTraceElement e : t.getValue())
buf.append(e).append('\n');
r.put(t.getKey().getName(),buf.toString());
}
}
return r;
}
private static final long serialVersionUID = 1L;
}
/**
* Executes Groovy script remotely.
*/
public static String executeGroovy(String script, VirtualChannel channel) throws IOException, InterruptedException {
return channel.call(new Script(script));
}
private static final class Script implements Callable<String,RuntimeException> {
private final String script;
private Script(String script) {
this.script = script;
}
public String call() throws RuntimeException {
GroovyShell shell = new GroovyShell();
StringWriter out = new StringWriter();
PrintWriter pw = new PrintWriter(out);
shell.setVariable("out", pw);
try {
Object output = shell.evaluate(script);
if(output!=null)
pw.println("Result: "+output);
} catch (Throwable t) {
t.printStackTrace(pw);
}
return out.toString();
}
}
}
<!--
Called from doScript() to display the execution result and the form.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<t:scriptConsole>
<pre>println System.getenv("PATH")</pre>
</t:scriptConsole>
</j:jelly>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:test="/lib/test">
<l:layout permission="${app.ADMINISTER}">
<st:include page="sidepanel.jelly" />
<l:main-panel>
<h1>${%Environment Variables}</h1>
<t:propertyTable items="${it.envVars}" />
</l:main-panel>
</l:layout>
</j:jelly>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:test="/lib/test">
<l:layout>
<st:include page="sidepanel.jelly" />
<l:main-panel>
<div>
Obtain information about the running Maven process by clicking
links from the left. Often useful for trouble-shooting problems.
</div>
</l:main-panel>
</l:layout>
</j:jelly>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
<l:header title="Maven Process for ${it.owner}" />
<l:side-panel>
<l:tasks>
<l:task icon="images/24x24/document.gif" href="systemProperties" title="${%System Properties}" />
<l:task icon="images/24x24/document.gif" href="envVars" title="${%Environment Variables}" />
<l:task icon="images/24x24/document.gif" href="threads" title="${%Thread Dump}" />
<l:task icon="images/24x24/notepad.gif" href="script" title="${%Script Console}" />
</l:tasks>
</l:side-panel>
</j:jelly>
\ No newline at end of file
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:test="/lib/test">
<l:layout permission="${app.ADMINISTER}">
<st:include page="sidepanel.jelly" />
<l:main-panel>
<h1>${%System Properties}</h1>
<t:propertyTable items="${it.systemProperties}" />
</l:main-panel>
</l:layout>
</j:jelly>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:test="/lib/test">
<l:layout permission="${app.ADMINISTER}">
<st:include page="sidepanel.jelly" />
<l:main-panel>
<h1>Thread Dump</h1>
<j:forEach var="t" items="${it.threadDump.entrySet()}">
<h2>${t.key}</h2>
<pre>${t.value}</pre>
</j:forEach>
</l:main-panel>
</l:layout>
</j:jelly>
MavenModuleSet.DiplayName=Build a maven2 project (beta)
MavenModule.Pronoun=Module
\ No newline at end of file
MavenModule.Pronoun=Module
MavenProbeAction.DisplayName=Monitor Maven Process
\ No newline at end of file
......@@ -2,33 +2,7 @@
Called from doScript() to display the execution result and the form.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout>
<st:include page="sidepanel.jelly" />
<l:main-panel>
<h1>Script Console</h1>
<p>
Type in an arbitrary <a href="http://groovy.codehaus.org/Home">Groovy script</a> and
execute it on the server. Useful for trouble-shooting and diagnostics.
Use the 'println' command to see the output (if you use <tt>System.out</tt>,
it will go to the server's stdout, which is harder to see.) Example:
</p>
<pre>
println(hudson.model.Hudson.instance.pluginManager.plugins)
</pre>
<form action="script" method="post">
<textarea id="script" name="script" style="width:100%; height:10em">${request.getParameter('script')}</textarea>
<div align="right">
<f:submit value="Run"/>
</div>
<script>
$('script').focus();
</script>
</form>
<j:if test="${output!=null}">
<h2>Result</h2>
<pre><st:out value="${output}"/></pre>
</j:if>
</l:main-panel>
</l:layout>
<t:scriptConsole>
<pre>println(hudson.model.Hudson.instance.pluginManager.plugins)</pre>
</t:scriptConsole>
</j:jelly>
<!--
Called from doScript() to display the execution result and the form.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout>
<st:include page="sidepanel.jelly" />
<l:main-panel>
<h1>${%Script Console}</h1>
<p>
Type in an arbitrary <a href="http://groovy.codehaus.org/Home">Groovy script</a> and
execute it on the server. Useful for trouble-shooting and diagnostics.
Use the 'println' command to see the output (if you use <tt>System.out</tt>,
it will go to the server's stdout, which is harder to see.) Example:
</p>
<!-- this is where the example goes -->
<d:invokeBody />
<form action="script" method="post">
<textarea id="script" name="script" style="width:100%; height:10em">${request.getParameter('script')}</textarea>
<div align="right">
<f:submit value="Run"/>
</div>
<script>
$('script').focus();
</script>
</form>
<j:if test="${output!=null}">
<h2>${%Result}</h2>
<pre><st:out value="${output}"/></pre>
</j:if>
</l:main-panel>
</l:layout>
</j:jelly>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册