2011-01-14 10 views
11

मुझे अपाचे कॉमन्स एक्सेक के साथ लॉन्च किए गए कमांड के stdin पर एक टेक्स्ट तर्क पाइप करने की आवश्यकता है (उत्सुकता के लिए, आदेश gpg है और तर्क कुंजीस्टोर के लिए पासफ्रेज है; gpg के पास पासफ्रेज स्पष्ट रूप से प्रदान करने का कोई तर्क नहीं है , केवल stdin से इसे स्वीकार करने के लिए)।Apache Commons Exec के साथ लॉन्च किए गए निष्पादन योग्य को स्ट्रिंग तर्क कैसे पाइप करें?

इसके अतिरिक्त, मुझे लिनक्स और विंडोज दोनों का समर्थन करने की आवश्यकता है।

एक खोल स्क्रिप्ट में मुझे क्या करना चाहते हैं

cat mypassphrase|gpg --passphrase-fd 

या

type mypassphrase|gpg --passphrase-fd 

लेकिन प्रकार विंडोज पर काम नहीं करता है के रूप में यह एक निष्पादन लेकिन एक आदेश आदेश में बनाया व्याख्या नहीं है (cmd ।प्रोग्राम फ़ाइल)।

कोड काम नहीं कर रहा है (उपर्युक्त कारण के लिए) नीचे है। इसके लिए एक संपूर्ण खोल बनाने के लिए बहुत बदसूरत है, मैं एक और अधिक सुरुचिपूर्ण समाधान की तलाश में था। दुर्भाग्यवश, बाउंसीकास्ट लाइब्रेरी और पीजीपी के बीच कुछ असंगतताएं हैं इसलिए मैं अपने (बहुत कम) समय में पूरी तरह से प्रोग्रामेटिक समाधान का उपयोग नहीं कर सकता।

अग्रिम धन्यवाद।

CommandLine cmdLine = new CommandLine("type"); 
cmdLine.addArgument(passphrase); 
cmdLine.addArgument("|"); 
cmdLine.addArgument("gpg"); 
cmdLine.addArgument("--passphrase-fd"); 
cmdLine.addArgument("0"); 
cmdLine.addArgument("--no-default-keyring"); 
cmdLine.addArgument("--keyring"); 
cmdLine.addArgument("${publicRingPath}"); 
cmdLine.addArgument("--secret-keyring"); 
cmdLine.addArgument("${secretRingPath}"); 
cmdLine.addArgument("--sign"); 
cmdLine.addArgument("--encrypt"); 
cmdLine.addArgument("-r"); 
cmdLine.addArgument("recipientName"); 
cmdLine.setSubstitutionMap(map); 
DefaultExecutor executor = new DefaultExecutor(); 
int exitValue = executor.execute(cmdLine); 

उत्तर

17

आप एक पाइप तर्क (|) gpg आदेश को स्वीकार नहीं करेगा क्योंकि नहीं जोड़ सकते। यह खोल है (उदा। bash) जो पाइप का अर्थ देता है और जब आप उस कमांडलाइन को खोल में टाइप करते हैं तो विशेष प्रसंस्करण करता है।

आप ByteArrayInputStream का उपयोग मैन्युअल रूप से कमांड के मानक इनपुट में डेटा भेजने के लिए कर सकते हैं (जैसे bash| देखता है)।

Executor exec = new DefaultExecutor(); 

    CommandLine cl = new CommandLine("sed"); 
      cl.addArgument("s/hello/goodbye/"); 

    String text = "hello"; 
    ByteArrayInputStream input = 
     new ByteArrayInputStream(text.getBytes("ISO-8859-1")); 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    exec.setStreamHandler(new PumpStreamHandler(output, null, input)); 
    exec.execute(cl); 

    System.out.println("result: " + output.toString("ISO-8859-1")); 

यह एक (bash) खोल में echo "hello" | sed s/hello/goodbye/ टाइपिंग (हालांकि UTF-8 एक और अधिक उचित एन्कोडिंग हो सकता है) के बराबर होना चाहिए।

+0

बहुत अच्छा जवाब: बैश पहले से बुला के बिना https://github.com/Macilias/Utils/blob/master/ShellUtils.java

मूल रूप से आप की तुलना में यहां से पहले दिखाया की तरह पाइप उपयोग अनुकरण कर सकते हैं ! मेरा दिन बचाया! – BetaRide

0

हाय यह करने के लिए मैं इस तरह एक छोटे से सहायक वर्ग का उपयोग करेगा:

public static String runCommand(String command, Optional<File> dir) throws IOException { 
    String[] commands = command.split("\\|"); 
    ByteArrayOutputStream output = null; 
    for (String cmd : commands) { 
     output = runSubCommand(output != null ? new ByteArrayInputStream(output.toByteArray()) : null, cmd.trim(), dir); 
    } 
    return output != null ? output.toString() : null; 
} 

private static ByteArrayOutputStream runSubCommand(ByteArrayInputStream input, String command, Optional<File> dir) throws IOException { 
    final ByteArrayOutputStream output = new ByteArrayOutputStream(); 
    CommandLine cmd = CommandLine.parse(command); 
    DefaultExecutor exec = new DefaultExecutor(); 
    if (dir.isPresent()) { 
     exec.setWorkingDirectory(dir.get()); 
    } 
    PumpStreamHandler streamHandler = new PumpStreamHandler(output, output, input); 
    exec.setStreamHandler(streamHandler); 
    exec.execute(cmd); 
    return output; 
} 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^