【问题标题】:Runtime.exec() from tomcat6 succeeds, but cannot access any files来自 tomcat6 的 Runtime.exec() 成功,但无法访问任何文件
【发布时间】:2011-03-02 14:25:43
【问题描述】:

我正在将我们的 servlet(纯 Java,在 Tomcat 6 中运行)从 CentOS 迁移到 Debian,并且遇到了使用 Runtime.exec() 执行命令的问题。
(该命令在生产中应该是 ImageMagick 的 convert,但我已经简化了查找问题根源的调用,因此以下所有带有 echo 的代码都经过测试,并且不能正常工作)。

String command = "echo test123 > /tmp/tomcat6-tmp/1";
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
int exitVal = process.waitFor();

似乎是调用外部程序的一种很常见的方式。它确实运行,在 exitVal 中返回 0,但无法创建文件并将文本放入其中。
低级方法也是如此:

ProcessBuilder pb = new ProcessBuilder("echo", "test123 > /tmp/tomcat6-tmp/3");
Process process = pb.start();
int resInt = process.waitFor();

但是可以使用放置在同一方法中的 Java 代码创建一个文件并将一些文本放入其中:

String fname = "/tmp/tomcat6-tmp/2";
File file = new File(fname);
file.createNewFile();
FileWriter fileWriter = new FileWriter(file);
fileWriter.write("test123");
fileWriter.close();

Runtime.exec("whoami")成功返回tomcat6,文件夹/tmp/tomcat6-tmp/确实存在,所有权限设置正确。

$ ls -al /tmp/tomcat6-tmp/
total 60
drwxr-xr-x 2 tomcat6 root     4096 Mar  2 15:26 .
drwxrwxrwt 6 root    root     4096 Mar  2 15:25 ..
-rw-r--r-- 1 tomcat6 tomcat6     7 Mar  2 15:26 2

所有不需要访问系统文件的命令似乎在同一上下文中使用Runtime.exec() 正常执行。

我使用全新安装的 debian Squeeze 和从软件包中安装的 tomcat6,没有对配置进行任何修改:

$ aptitude show tomcat6
Package: tomcat6                         
State: installed
Version: 6.0.28-9+squeeze1
.....
$ cat /etc/issue
Debian GNU/Linux 6.0 \n \l

我该如何解决这个问题? 或者至少我应该去哪里看?我已经用谷歌搜索了 Java 以这种方式行为不端的所有可以想象的原因,但未能找到线索。

P.S.因为这是默认安装,Java 安全管理器在/etc/init.d/tomcat6 中被禁用

# Use the Java security manager? (yes/no)
TOMCAT6_SECURITY=no

【问题讨论】:

  • Rails 和 CentOS 也有类似的问题。问题出在 SELinux 上,因此运行 tomcat 的用户可能没有打开 shell 或运行该命令的权限。我必须完全禁用 SELinux 才能使其工作(这通常不是一个好主意,但它是在我正在做一些测试的本地 VM 中,所以这并不重要)。 SELinux也捆绑在Debian中,但我不知道它是否默认处于活动状态。
  • 不,SELinux 已禁用。问题在于在 Runtime.exec() 和 bash 中解析命令行的方式不同。

标签: java permissions debian tomcat6 runtime.exec


【解决方案1】:

将您想要的操作放入一个可执行的 shell 脚本中,然后 exec shell 脚本。

Java 的Runtime.exec()exec 系统调用的包装器,它将直接运行进程,而不是在子shell 下。 > 重定向由 shell 执行,不能作为直接 execed 进程的参数。

【讨论】:

  • 谢谢。我在测试过程中注意力不集中,并且在 Runtime.exec() 的参数中混合了两个问题,感谢您的提示,我已经将它们分开,并解决了这两个问题。
  • @kirushik 你能写出解决你问题的Java代码吗?我有同样的问题,我真的需要解决它。谢谢!
  • @Jairo 只需使用没有保护符号的 Runtime.exec(你不会有任何管道、重定向和所有特定于 shell 的东西)。并使用download.oracle.com/javase/6/docs/api/java/lang/… 将参数传递给命令(一个接一个,在字符串数组中)
【解决方案2】:

不知道这个“echo test123 > /tmp/tomcat6-tmp/1”是否可以作为一个命令运行。我记得我有类似的问题,我不得不拆分它,所以尝试运行“echo test123”,然后使用命令的输出获取输入流。如果你有一个流,你可以轻松地写入文件。

另外,你执行的命令是带参数的,所以尽量使用以数组为参数的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2016-04-06
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多