2011-04-21 18 views
5

Estoy intentando imprimir el número de serie de mi mac [edit: Apple computer] en un programa java. Estoy familiarizado con el comando de UnixImprimir el número de serie de mi Mac en java con los comandos de Unix

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

que realiza esta tarea en la terminal.
cuando intento

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

no se imprime el número de serie. En su lugar se imprime:

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

Creo que el problema es que terminal.exec() no pretende llevar a toda la cadena de comando. ¿Hay algo en Java similar al argumento shell = True en Python's Popen(command, stdout=PIPE, shell=True) que me permita pasar toda la cadena de comandos?

Respuesta

1

Para obtener los Addres MAC a través de Java puede utilizar java.net.NetworkInterface:

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

Si no conoce el nombre (supongo que sea 'eth0' en Linux) de su interfaz de red, puede incluso iterar a través de todas sus interfaces de red usando NetworkInterface.getNetworkInterfaces().

+0

Gracias por la respuesta rápida, pero creo que no estaba perfectamente claro. Estoy tratando de imprimir el número de serie de mi computadora Apple, no mi dirección MAC. Tal vez me equivoqué con la publicación. –

+0

ah, vale. En este caso, su uso de Runtime.exec podría ser lo más simple. Lo único que necesita cambiar es separar todos los argumentos y el comando y ponerlos todos en una cadena [] que se pasa a Runtime.exec como matriz. Sin embargo, no estoy seguro de si la canalización de la salida de un comando en otro comando realmente se puede hacer usando Runtime.exec, ya que esta es una función de shell y en realidad implica iniciar dos procesos, no uno. Sin embargo, podría ejecutar solo 'ioreg -l' en java y leer la salida completa, hacer el filtrado en java al iterar las líneas de salida y usar String.indexOf – BertNase

8

veo dos posibilidades:

  1. analizar la salida de ioreg -l usando, por ejemplo, Scanner.

  2. Wrap el comando en un script de shell y exec() que:

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

Adición: Como un ejemplo del uso ProcessBuilder, y la incorporación de una sugerencia útiles por Paul Cager, aquí hay una tercera alternativa:

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

. Debo agregar que [ProcessBuilder] (http://download.oracle) .com/javase/6/docs/api/java/lang/ProcessBuilder.html), discutido [aquí] (http://stackoverflow.com/questions/5696404), es una alternativa más reciente a 'exec()'. – trashgod

3

Las tuberías no son compatibles con Runtime.exec (..) ya que son una característica de las shells. En cambio, tendría que emular la tubería usted mismo, p.

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

alternativa, podría, por supuesto, ejecutar un shell como un proceso, por ejemplo Runtime.exec ("bash") e interactúa con él leyendo y escribiendo sus flujos de IO. Sin embargo, interactuar con los procesos es un poco complicado y tiene algunos problemas y deja que ejecute tu comando (ver comentarios)

+2

No es necesario emular la tubería en Java, o interactuar con el stdin/out del shell. Simplemente podría usar exec ("bash -c 'ioreg -l | awk ...'") –

+0

@Paul cierto, por supuesto. Mi punto principal era aclarar que las tuberías no funcionan con Runtime.exec (..) (a menos que se use para ejecutar un shell) – sfussenegger

+0

@Paul Cager: ¡Excelente idea! Lo he incorporado en un [ejemplo] (http://stackoverflow.com/questions/5740673) usando 'ProcessBuilder'. @sfussenegger +1 para una alternativa útil. – trashgod

Cuestiones relacionadas