diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java index 44a773a8f6..355a673837 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java @@ -1,16 +1,28 @@ package com.taobao.arthas.core.command.basic1000; +import com.taobao.arthas.core.command.Constants; import com.taobao.arthas.core.command.model.SessionModel; import com.taobao.arthas.core.server.ArthasBootstrap; import com.taobao.arthas.core.shell.command.AnnotatedCommand; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.shell.session.Session; import com.taobao.arthas.core.util.UserStatUtil; +import com.taobao.middleware.cli.annotations.DefaultValue; +import com.taobao.middleware.cli.annotations.Description; import com.taobao.middleware.cli.annotations.Name; +import com.taobao.middleware.cli.annotations.Option; import com.taobao.middleware.cli.annotations.Summary; import com.alibaba.arthas.tunnel.client.TunnelClient; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * 查看会话状态命令 * @@ -18,15 +30,89 @@ */ @Name("session") @Summary("Display current session information") +@Description(value =Constants.EXAMPLE + + " session -s\n" + + " session -I *\n" + + " session -I '${arthas-cmd}-args=10'\n" + + " session -I 'history-args=10'\n" + + " session -I 'trace-args=-n 3 -v'\n" + + Constants.WIKI + Constants.WIKI_HOME + "session") public class SessionCommand extends AnnotatedCommand { + private static List RESERVED_WORDS = Arrays.asList( "id", "tty","pid","server","lastAccessedTime", + "createTime","subject", "instrumentation", "arthas-command-manager"); + + private boolean showSessionData = true; + + private boolean showAll = false; + + private List customSesionData; + + @Option(shortName = "H", longName = "hiddenSessionData", flag = true) + @Description("Hidden artahs session data") + public void setHiddenSessionData(final boolean hiddenSessionData) { + this.showSessionData = !hiddenSessionData; + } + + @Option(shortName = "A", longName = "showAll", flag = true) + @Description("Show all session data") + public void setShowAll(final boolean showReservedNames) { + this.showAll = showReservedNames; + } + + @Option(shortName = "I", longName = "input") + @Description("Input cutom session data, ie: 'trace-args=-n 3' or * for cleanup") + public void setCustomSessionData(final List customSesionData) { + this.customSesionData = customSesionData; + } + @Override public void process(CommandProcess process) { SessionModel result = new SessionModel(); Session session = process.session(); result.setJavaPid(session.getPid()); result.setSessionId(session.getSessionId()); - + if (customSesionData != null) { + process.echoTips("customSesionData: " + customSesionData + "\n"); + if (customSesionData.size() == 1 && "*".equals(customSesionData.get(0))) { + final Map sessionData = session.cloneSessionData(); + for (final Map.Entry entry : sessionData.entrySet()) { + if (!RESERVED_WORDS.contains(entry.getKey())) { + session.remove(entry.getKey()); + } + } + } else { + final Pattern pattern = Pattern.compile("\\s*([^:=]+)\\s*[:=]\\s*(.+)"); + for (final String pv : customSesionData) { + final Matcher matcher = pattern.matcher(pv); + if (matcher.find()) { + final int groupCount = matcher.groupCount(); + if (groupCount >= 2) { + final String name = matcher.group(1); + if (RESERVED_WORDS.contains(name)){ + process.echoTips("ignore: " + name); + return; + } + session.put(name, matcher.group(2)); + } + } + } + } + showSessionData = true; + } + if (showSessionData) { + final Map sessionData = session.cloneSessionData(); + if (!this.showAll) { + final Iterator> iter = sessionData.entrySet().iterator(); + while(iter.hasNext()) { + if (RESERVED_WORDS.contains(iter.next().getKey())) { + iter.remove(); + continue; + } + } + } + result.setSessionData(sessionData); + } //tunnel TunnelClient tunnelClient = ArthasBootstrap.getInstance().getTunnelClient(); if (tunnelClient != null) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/SessionModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/SessionModel.java index aede0262ab..28cf1065d8 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/SessionModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/SessionModel.java @@ -1,5 +1,7 @@ package com.taobao.arthas.core.command.model; +import java.util.Map; + /** * Session command result model * @@ -15,6 +17,8 @@ public class SessionModel extends ResultModel { private boolean tunnelConnected; + private Map sessionData; + @Override public String getType() { return "session"; @@ -67,4 +71,12 @@ public boolean isTunnelConnected() { public void setTunnelConnected(boolean tunnelConnected) { this.tunnelConnected = tunnelConnected; } + + public Map getSessionData() { + return this.sessionData; + } + + public void setSessionData(Map env) { + this.sessionData = env; + } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/SessionView.java b/core/src/main/java/com/taobao/arthas/core/command/view/SessionView.java index c496df9d72..1a7a22bd7e 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/SessionView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/SessionView.java @@ -31,6 +31,9 @@ public void draw(CommandProcess process, SessionModel result) { if (result.getStatUrl() != null) { table.row("STAT_URL", result.getStatUrl()); } + if (result.getSessionData() != null) { + table.row("SESION_DATA", result.getSessionData().toString()); + } process.write(RenderUtil.render(table, process.width())); } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/session/Session.java b/core/src/main/java/com/taobao/arthas/core/shell/session/Session.java index 8ca1c902e2..3c58faa4d2 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/session/Session.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/session/Session.java @@ -6,6 +6,7 @@ import java.lang.instrument.Instrumentation; import java.util.List; +import java.util.Map; /** * A shell session. @@ -168,4 +169,9 @@ public interface Session { * Whether the session is tty term */ boolean isTty(); + + /** + * @return Clone the session data. + */ + Map cloneSessionData(); } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionImpl.java b/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionImpl.java index 2bf8bca6fa..1b5e15ad87 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionImpl.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionImpl.java @@ -28,6 +28,11 @@ public SessionImpl() { this.setLastAccessTime(now); } + @Override + public Map cloneSessionData() { + return new HashMap(data); + } + @Override public Session put(String key, Object obj) { if (obj == null) { diff --git a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java index 74adfd1bdb..137bf0d04b 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java @@ -23,6 +23,7 @@ import com.taobao.arthas.core.shell.term.Tty; import com.taobao.middleware.cli.CLIException; import com.taobao.middleware.cli.CommandLine; + import io.termd.core.function.Function; import java.lang.instrument.ClassFileTransformer; @@ -344,10 +345,25 @@ public synchronized void run(boolean fg) { args2.add(arg.value()); } } - CommandLine cl = null; try { if (commandContext.cli() != null) { + final String appCmdArgs = commandContext.name() +"-args"; + final Object cmdArgs = process.session().get(appCmdArgs); + if (cmdArgs != null) { + process.echoTips("appendCmdArgs: " + cmdArgs + "\n"); + final String cmdArgs1 = cmdArgs.toString(); + final String[] arr = cmdArgs1.contains("##") ? cmdArgs1.split("##") + : cmdArgs1.split("[; ,:#]+"); + for (final String arg : arr) { + if (arg.isEmpty()) { + break; + } + args2.add(arg); + } + process.echoTips("appendCmdArgs done: " + args2 + "\n"); + } + if (commandContext.cli().parse(args2, false).isAskingForHelp()) { appendResult(new HelpCommand().createHelpDetailModel(commandContext)); terminate();