2011-04-21 51 views
5

我试图在java程序中打印我的Mac的[编辑:Apple计算机]序列号。我熟悉Unix命令使用Unix命令在java中打印我的Mac序列号

ioreg -l | awk '/IOPlatformSerialNumber/ { print $4;}' 

它在终端上完成这个任务。
当我尝试

String command = "ioreg -l | awk '/IOPlatformSerialNumber/ { print $4; }'" 
Runtime terminal = Runtime.getRuntime(); 
String input = new BufferedReader(
    new InputStreamReader(
     terminal.exec(commands).getInputStream())).readLine(); 
System.out.println(new BufferedReader(
    new InputStreamReader(
     terminal.exec(command, args).getInputStream())).readLine()); 

不打印我的序列号。相反,它打印:

<+-o Root class IORegistryEntry, id 0x100000100, retain 10> 

我认为这个问题是terminal.exec()并不意味着把整个命令字符串。有没有类似于python的Popen(command, stdout=PIPE, shell=True)中的参数shell = True的Java中的东西,这将允许我传递整个命令字符串?

回答

1

通过Java获得MAC ADDRES你可以使用java.net.NetworkInterface

NetworkInterface.getByName("xxx").getHardwareAddress() 

如果你不知道这个名字(我假设它是在Linux上“eth0”网络)网络接口,你可以甚至可以使用NetworkInterface.getNetworkInterfaces()遍历所有网络接口。

+0

谢谢你的快速答案,但我认为我不是很清楚。我试图打印我的苹果电脑的序列号,而不是我的MAC地址。也许我错误地贴了帖子。 – 2011-04-21 06:56:20

+0

啊,好的。在这种情况下,使用Runtime.exec可能是最简单的事情。唯一需要改变的是将所有参数和命令分开,并将它们全部放入一个作为数组传递给Runtime.exec的String []。但我不确定一个命令输出到另一个命令的管道是否可以使用Runtime.exec实际完成,因为这是一个shell功能,实际上涉及启动两个进程,而不是一个进程。你可以,但是在java中只执行'ioreg -l'并读取完整的输出,通过迭代输出行并使用String.indexOf – BertNase 2011-04-21 07:01:12

8

我看到两种可能性:

  1. 解析的ioreg -l使用,比如输出,Scanner

  2. 裹在shell脚本的命令和exec()它:

 
#!/bin/sh 
ioreg -l | awk '/IOPlatformSerialNumber/ { print $4;}' 

附录:由于使用ProcessBuilder,并通过Paul Cager结合了有益的建议的一个例子,这里有一个第三种选择:

import java.io.BufferedReader; 
import java.io.InputStreamReader; 

public class PBTest { 

    public static void main(String[] args) { 
     ProcessBuilder pb = new ProcessBuilder("bash", "-c", 
      "ioreg -l | awk '/IOPlatformSerialNumber/ { print $4;}'"); 
     pb.redirectErrorStream(true); 
     try { 
      Process p = pb.start(); 
      String s; 
      // read from the process's combined stdout & stderr 
      BufferedReader stdout = new BufferedReader(
       new InputStreamReader(p.getInputStream())); 
      while ((s = stdout.readLine()) != null) { 
       System.out.println(s); 
      } 
      System.out.println("Exit value: " + p.waitFor()); 
      p.getInputStream().close(); 
      p.getOutputStream().close(); 
      p.getErrorStream().close(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 
+0

来完成java中的过滤。我应该添加[ProcessBuilder](http://download.oracle的.com/JavaSE的/ 6 /文档/ API /爪哇/郎/的ProcessBuilder。html),讨论[这里](http://stackoverflow.com/questions/5696404),是'exec()'的更新选择。 – trashgod 2011-04-21 07:15:41

3

Runtime.exec(..)不支持管道,因为它们是shell的一个功能。相反,你必须自己模拟管道,例如

String ioreg = toString(Runtime.exec("ioreg -l ").getInputStream()); 

Process awk = Runtime.exec("awk '/IOPlatformSerialNumber/ { print $4;}'"); 
write(awk.getOutputStream(), ioreg); 

String input = new BufferedReader(new InputStreamReader(awk.getInputStream())).readLine(); 

或者,也当然可以运行一个壳作为一个过程, 例如Runtime.exec(“bash”),并通过读取和写入其IO流与它进行交互。与进程交互虽然有点棘手,但有一些陷阱 ,让它执行你的命令(看评论)

+2

不需要模拟Java中的管道,也不需要与shell的stdin/out进行交互。你可以使用exec(“bash -c'ioreg -l | awk ...'”) – 2011-04-21 10:10:57

+0

@Paul true,当然。我的主要观点是要明确,管道不能与Runtime.exec(..)一起工作(除非它用于运行shell) – sfussenegger 2011-04-21 14:32:44

+0

@Paul Cager:好主意!我已经使用'ProcessBuilder'将它并入了[示例](http://stackoverflow.com/questions/5740673)。 @sfussenegger +1作为一个有用的选择。 – trashgod 2011-04-21 14:48:22