2010-01-19 10 views
3

J'ai des scénarios où j'ai un "agent" Java qui fonctionne sur plusieurs plates-formes (en particulier Windows, Solaris & AIX). Je voudrais factoriser les différences dans la structure du système de fichiers en utilisant des variables d'environnement dans la ligne de commande que j'exécute. Pour autant que je sache, il n'existe aucun moyen d'obtenir la méthode Runtime.exec() pour résoudre/évaluer les variables d'environnement référencées dans la commande Chaîne (ou tableau de chaînes).Évaluation des variables d'environnement dans la commande exécutée par Java Runtime.exec()

Je sais que si le push vient à pousser, je peux écrire du code pour prétraiter la ou les chaînes de commande et résoudre les variables d'environnement à la main (en utilisant getEnv() etc). Cependant, je me demande s'il y a une façon plus intelligente de le faire, car je suis sûr que je ne suis pas la seule personne à vouloir faire cela et je suis sûr qu'il y a des pièges dans la «mise en place» de ma propre implémentation.

Vos conseils et suggestions sont les bienvenus.

modifier: Je voudrais faire référence à des variables d'environnement dans la chaîne de commande en utilisant une notation cohérente telle que $ VAR et/ou% VAR%. Pas agité qui.

modifier: Pour être clair, je voudrais être en mesure d'exécuter une commande telle que:

perl $SCRIPT_ROOT/somePerlScript.pl args

sur les hôtes Windows et Unix en utilisant Runtime.exec(). Je spécifie la commande dans le fichier de configuration qui décrit une liste de tâches à exécuter et il doit être capable de travailler sur plusieurs plates-formes, d'où ma pensée qu'une variable d'environnement serait utile pour factoriser les différences de système de fichiers. J'espère que ça aide à le clarifier.

Merci. Tom

+0

Comment essayez-vous de les résoudre? En utilisant le shell shell Unix de '$ VAR' dans la chaîne de commande que vous passez à' Runtime.exec() '? –

+0

@Kevin - oui. Idéalement. –

Répondre

6

Je pense avoir mal compris votre question avec ma réponse originale. Si vous essayez de résoudre les références de variable d'environnement sur les lignes de commande que vous avez générées à partir de Java, je pense que vous devrez peut-être "rouler le vôtre".

Selon le système d'exploitation, il existe de nombreuses normes différentes quant à leur extension. De plus, c'est typiquement une fonction du shell, donc même sur le même OS il peut y avoir différentes manières. En fait, les fonctions d'activation de processus de système d'exploitation standard (par exemple, exec dans Unix) n'effectuent pas d'expansion de ligne de commande.

Ce n'est vraiment pas si difficile, avec Java 5 et plus tard. Définissez une norme pour vous-même, j'utilise généralement la norme Java que vous voyez dans les fichiers de règles de sécurité et certaines définitions de fichiers de propriétés améliorées - ${var} se développe dans la référence de nom de variable/propriété. Quelque chose comme:

private static String expandCommandLine(final String cmd) { 
     final Pattern vars = Pattern.compile("[$]\\{(\\S+)\\}"); 
     final Matcher m = vars.matcher(cmd); 

     final StringBuffer sb = new StringBuffer(cmd.length()); 
     int lastMatchEnd = 0; 
     while (m.find()) { 
      sb.append(cmd.substring(lastMatchEnd, m.start())); 
      final String envVar = m.group(1); 
      final String envVal = System.getenv(envVar); 
      if (envVal == null) 
       sb.append(cmd.substring(m.start(), m.end())); 
      else 
       sb.append(envVal); 
      lastMatchEnd = m.end(); 
     } 
     sb.append(cmd.substring(lastMatchEnd)); 

     return sb.toString(); 
    } 
+0

Cheers - Je soupçonne que ce sera ce que je finis par faire. Je suis sûr que je ne suis pas le premier à l'essayer. Peut-être que j'utilise la mauvaise terminologie pour chercher avec. Merci pour le code aussi. –

+0

Je remplacerait 'sb.append (cmd.substring (lastMatchEnd, m.start()))' avec 'sb.append (cmd, lastMatchEnd, m.start())' pour éviter une copie de chaîne. De même avec les deux autres appels à 'sb.append (... substring (...))'. –

1

Y at-il une raison pour laquelle les propriétés du système ne fonctionneront pas? Utilisez l'indicateur -D sur la ligne de commande, vous pouvez ensuite le récupérer via System.getProperty

+0

Hey Steve - Je ne suis pas sûr de savoir comment cela aiderait? Peut-être que ma question n'est pas claire. Je vais essayer de le clarifier. –

0

Juste parce que j'ai le code de résolution variable d'environnement Windows dans mon presse-papiers (codé par votre serviteur) qui travaille sur une chaîne, je vais juste poster ici. C'est peut-être la méthode la plus efficace (peut-être que regex est beaucoup moins efficace, je ne suis pas sûr).

int from  = 0; 
int startperc = -1; 
int endperc = -1; 

while (true) { 
    int index = tok.indexOf("%", from); 
    if (index == -1) break; 
    if (startperc == -1) { 
     startperc = index; 
    } else if (endperc == -1) { 
     endperc = index; 
    } 
    from = index + 1; 

    if (startperc >= 0 && endperc > startperc) { 
     String startbit = tok.substring(0, startperc); 
     String middlebit = System.getenv(tok.substring(startperc + 1, endperc)); 
     String endbit = endperc <= tok.length() ? tok.substring(endperc + 1) : ""; // substr up to end 

     // integrate 
     tok = startbit + middlebit + endbit; 

     // reset 
     startperc = -1; 
     endperc = -1; 
    } 
} 
1

Le regex

[$]\\{(\\S+)\\} 

est gourmand (S+) et en cas de xx ${a} xx ${b} xx il correspondra A} xx ${B au lieu de A et séparement B. Avez-vous déjà testé avec plusieurs vars dans le cmd? Donc, s'il y a plusieurs variables à remplacer.

Il devrait être

[$]\\{(\\S+?)\\}