打印我的Mac';使用Unix命令在java中创建的s序列号

打印我的Mac';使用Unix命令在java中创建的s序列号,java,macos,unix,io,Java,Macos,Unix,Io,我正在用java程序打印我的mac电脑的[edit:Apple computer]序列号。我熟悉Unix命令 ioreg -l | awk '/IOPlatformSerialNumber/ { print $4;}' 它在终端中完成此任务。 当我尝试 String command = "ioreg -l | awk '/IOPlatformSerialNumber/ { print $4; }'" Runtime terminal = Runtime.getRuntime(); Strin

我正在用java程序打印我的mac电脑的[edit:Apple computer]序列号。我熟悉Unix命令

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()
并不意味着接受整个命令字符串。java中是否有类似于python的Popen(command,stdout=PIPE,shell=True)中的参数
shell=True
的东西,允许我传递整个命令字符串?

要通过java获得MAC地址,可以使用
java.net.NetworkInterface

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

如果您不知道网络接口的名称(我假设它在linux上是'eth0'),您甚至可以使用
NetworkInterface.getNetworkInterfaces()
遍历所有网络接口

我认为有两种可能性:

  • 使用,比如,解析
    ioreg-l
    的输出

  • 将命令包装在shell脚本中,然后
    exec()
    it:


  • 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();
    

    或者,您当然可以将shell作为进程运行,例如Runtime.exec(“bash”),并通过读取和写入其IO流与之交互。不过,与进程交互有点棘手,需要一些技巧,让它执行您的命令(请参阅注释)

    谢谢您的快速回答,但我想我还不是很清楚。我正在打印我的苹果电脑的序列号,而不是我的MAC地址。也许我把帖子贴错了。啊,好吧。在这种情况下,使用Runtime.exec可能是最简单的事情。您唯一需要更改的是将所有参数和命令分开,并将它们放入字符串[]中,该字符串作为数组传递到Runtime.exec中。但是,我不确定是否可以使用Runtime.exec将一个comand的输出传输到另一个命令,因为这是一个shell功能,实际上需要启动两个进程,而不是一个进程。但是,您可以只在java中执行
    ioreg-l
    ,并通过迭代输出行和使用字符串读取完整的输出,而不必在java中进行过滤。indexOfI应该补充说,这是
    exec()
    的最新替代方法。不需要在java中模拟管道,也不需要与shell的stdin/out交互。当然,您可以使用exec(“bash-c'ioreg-l | awk…”)@Paul true。我的主要观点是要说明管道不能与Runtime.exec(..)一起工作(除非它用于运行shell)@Paul Cager:好主意!我已经使用
    ProcessBuilder
    将其合并到了一个应用程序中@sfussenegger+1是一个有用的替代方案。
    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();
            }
        }
    }
    
    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();