【问题标题】:What is JAVA exec()uting?什么是 JAVA exec()uting?
【发布时间】:2016-11-08 12:02:15
【问题描述】:

我在 Linux 上,我有一个 Java 应用程序(JAR 存档),它使用 exec() 来完成它的工作。我需要找出应用程序 exec()uting 是哪些命令...我尝试了 strace 和 jstack 但没有任何结果。假设应用程序正在调用 exec("ls"),我可以通过 grepping 上述程序的输出找到该 ls 命令吗?

所以问题是: 有没有一种简单的方法来观察 Java 应用程序使用 exec() 执行了什么?

编辑以获得更好的情况概述:

假设在 Java 应用程序中,我有一个带有 onclick 侦听器的按钮,该按钮从另一个类调用静态函数。在该函数中调用了 exec("ls");。 当我单击该按钮时,我会在 strace 中看到:

futex(0x7f14a6f799d0, FUTEX_WAIT, 4968, NULLDownload button clicked ! Trying SCP FROM... <unfinished ...>

在调用 exec() 之前尝试 SCP FROM.. 只是我对该按钮处理程序的不满。

另一个编辑: 谢谢你们,但我是从操作系统的角度说的......假设我是系统管理员并且我下载了 JAR。我想(从外部)知道那个 JAR 在做什么 - 我只对从 exec() 开始的程序感兴趣

所以我尝试了strace,但它没有显示任何关于从 exec 调用该命令...也许它为此记录了太多低级调用...

然后我尝试了jstack -m,但我找不到任何看起来像来自 exec 的命令的东西。我试过 grepping 字符串但没有运气。

【问题讨论】:

  • ls 进程是否应该将 Java 进程作为其父进程,例如查看ps 等的输出时?
  • @Thomas:但是这个进程只会存活几毫秒。
  • 嗯,好主意...但只有当我在 ls 命令执行时及时运行ps 时才会显示。我会更喜欢日志或跟踪之类的东西......
  • 它必须出现在strace,对吧?
  • @Thilo 拜托,你能看看我更新的问题吗?我在 strace 中看到的唯一东西是

标签: java linux exec trace


【解决方案1】:

好的,我要提出的是一种 veeeeeeeeeery 基本的做事方式,但它可能正是您想要的。

您可能知道,.jar 文件只是由 Java .class 文件组成的 ZIP 存档。如果您只需要查看将要执行的命令,并且如果您知道应该执行它们的类,则可以提取该类使用gzip 从jar 文件中提取文件,然后在它们上使用strings 来查找命令。

例如,这是我能想到的最简单的类,它使用了exec()

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("/bin/ls");
        } catch (IOException ignored) {}
    }
}

如果你这样做strings Main.class,你应该得到这样的东西:

[...]$ strings Main.class
<init>
Code
LineNumberTable
LocalVariableTable
this
LMain;
main
([Ljava/lang/String;)V
args
[Ljava/lang/String;
StackMapTable
SourceFile
        Main.java
/bin/ls
java/io/IOException
Main
java/lang/Object
java/lang/Runtime
getRuntime
()Ljava/lang/Runtime;
exec
'(Ljava/lang/String;)Ljava/lang/Process;

如您所见,/bin/ls 可以识别为字符串。这在大多数情况下应该可以工作,除非你的 Java 程序以一种奇怪的方式构造命令,比如在运行时使用 char 数组创建命令字符串只是为了掩盖正在执行的命令(在这种情况下,我会高度怀疑这样的程序)。

但是,如果您想查看实时执行的命令,恐怕您需要借助一些监控实用程序,因为大多数命令的生命周期太短,甚至无法出现在 top 和喜欢。

编辑:关于strace:我查看了Java's native C code for UNIX systems,似乎它实际上使用execvpe() 系统调用来运行使用Runtime.exec() 启动的所有命令:

    execvpe(argv[0], argv, envv);

因此,理论上,您应该能够运行 strace -e execvpe &lt;java command...&gt; 来列出执行的每个命令(以及对 execvpe() 的所有其他调用——您需要进行更多过滤,这是真的)。​​

【讨论】:

  • 嗯,谢谢。这很有趣...您至少知道该实用程序的名称吗?我试过stracejstack -m...
  • 我环顾四周发现了这个:superuser.com/questions/222912/…。或者,现在我只是大声思考,您可以:创建一个用户new_user,在一个终端中编写一个在循环中运行ps -U new_user &gt; output.txt 的脚本,然后在另一个终端中以new_user 的身份运行jar。 jar 中的每个命令exec()d 也应该以new_user 运行,因此当Java 程序完成时,只需终止ps 脚本并检查output.txt 文件。
  • 看,jstack 的问题在于它只打印堆栈跟踪信息,不包括参数值。因此,您可能会看到对 Runtime.exec() 的调用,但不会看到它作为参数接收到的字符串,即它正在执行的命令。关于 strace,我正在编辑我的答案以使其更好,并可能进一步帮助您。无论如何,如果你想要一个面向工具的解决方案,你最好在SuperUser 而不是这里询问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多