简体   繁体   English

从 java 程序运行多个 unix 命令

[英]Run multiple unix commands from a java program

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

public class Main {
  public static void main(String[] args) throws IOException, InterruptedException {
    // Set the key and iv values
    String key = "1234567812345678";
    String iv = "1234567812345678";

    // Set the string to encrypt
    String string = "passwordToBeEncrypted";

    // Create the ProcessBuilder object and specify the command and its arguments
    ProcessBuilder pb = new ProcessBuilder("echo", string, "|", "openssl enc -aes-256-cbc -k", key, "-iv", iv, "-base64");

    // Start the process and get the Process object
    Process p = pb.start();

    // Wait for the process to finish and get the exit code
    int exitCode = p.waitFor();
    System.out.println("Exit code: " + exitCode);

    // Read the output from the process
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String encryptedString = reader.readLine();

    // Print the encrypted string
    System.out.println("Encrypted string: " + encryptedString);
  }
}

I am expecting the output to be a encrypted string whereas the actual output is command itself ie its printing the command " Encrypted string: passwordToBeEncrypted | openssl enc -aes-256-cbc -k 1234567812345678 -iv 1234567812345678 -base64 " Please point the issue with the above code.我期待 output 是一个加密的字符串,而实际的 output 是命令本身,即它打印命令“加密字符串:passwordToBeEncrypted | openssl enc -aes-256-cbc -k 1234567812345678 -iv 1234567812346上面的代码。

I am trying to execute the below shell commands from java code -我正在尝试从 java 代码执行以下 shell 命令 -

key="1234567812345678" iv="1234567812345678"关键=“1234567812345678”四=“1234567812345678”

string="passwordToBeEncrypted " string="passwordToBeEncrypted"

encrypted_string=$(echo "$string" | openssl enc -aes-256-cbc -k "$key" -iv "$iv" -base64) encrypted_string=$(echo "$string" | openssl enc -aes-256-cbc -k "$key" -iv "$iv" -base64)

echo "$encrypted_string"回声“$encrypted_string”

As our deceased chief executive commented, Java ProcessBuilder (and also Runtime.exec ) is not a shell -- and it does not run Unix 'commands' but rather programs .正如我们已故首席执行官评论的那样,Java ProcessBuilder (以及Runtime.exec )不是 shell - 它不运行 Unix '命令',而是运行程序 Many of the commands you give to a Unix shell actually run a program, but they can do other things as well such as piping or otherwise redirecting I/O, and substituting variables as in the commands you posted, and ProcessBuilder does not do these other things with the exception of piping in Java 9 up.您给 Unix shell 的许多命令实际上运行一个程序,但它们也可以做其他事情,例如管道或以其他方式重定向 I/O,并像您发布的命令中那样替换变量,而ProcessBuilder不执行这些其他操作Java 9 向上的管道除外的东西。 See the compilation in my answer at Shell command in Java with Runtime.getRuntime().exec();请参阅我在Java 中 Shell 命令的回答中的编译,其中包含 Runtime.getRuntime().exec(); . .

However, you don't actually need a pipeline;但是,您实际上并不需要管道; ProcessBuilder by default redirects the stdin and stdout (and also stderr) of the program it runs to pipes respectively from and to the Java process, which your code can use.默认情况下, ProcessBuilder将其运行的程序的标准输入和标准输出(以及标准错误)分别重定向到 Java 进程的管道,您的代码可以使用该进程。 In particular while the Unix shell commandline特别是 Unix shell 命令行

echo string | openssl enc ...

runs the echo program to output 'string' (plus a newline) which is redirected to a pipe that is then redirected as the input of the openssl program , in some shells you can get exactly the same result fromecho程序运行到 output 'string'(加上换行符),它被重定向到 pipe,然后被重定向为openssl程序的输入,在某些 shell 中,您可以获得完全相同的结果

openssl <<<string enc ...

which runs one program, openssl , with its input redirected from a tempfile or pipe created by the shell itself (not a separate program) and ProcessBuilder can effectively do this latter:它运行一个程序openssl ,其输入重定向自临时文件或由 shell 本身(不是单独的程序)创建的 pipe 并且ProcessBuilder可以有效地执行后者:

    String key = "1234567812345678";
    String iv = "1234567812345678";
    String string = "passwordToBeEncrypted";

    ProcessBuilder pb = new ProcessBuilder("openssl","enc","-aes-256-cbc","-k",key,"-iv",iv,"-base64");
    // note every token parsed from the shell command as a separate argument (which is every one
    // separated by unquoted whitespace) must be a separate argument to ProcessBuilder
    Process p = pb.start();
    // **CHANGE HERE**
    p.getOutputStream.write( (string+"\n").getBytes(/*charset if needed*/) );
    p.getOutputStream.close();
    // instead of using the OutputStream directly you can wrap (a) Writer(s) on it and use that(them),
    // similar to the way you wrap Readers on the InputStream below, but I didn't bother

    // if the data contains any non-ASCII character(s) then the 'charset' used for encoding matters; 
    // you need to specify it in `String.getBytes()`, or when creating Writer(s) if you do that,
    // as a Java value equivalent to the 'locale' used by the echo program in your shell, 
    // which will generally be the setting of the env var LC_ALL or LANG -- 
    // but your posted data is all ASCII so all charsets Java can default to are okay

    int exitCode = p.waitFor();
    System.out.println("Exit code: " + exitCode);
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String encryptedString = reader.readLine();

    System.out.println("Encrypted string: " + encryptedString);

PS: all of the attempts/versions you posted encrypt -- not decrypt -- a string, in a particular way idiosyncratic to openssl that is not fully standard and not even very good, see (my) https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/#35614 . PS:您发布的所有尝试/版本都加密——而不是解密——一个字符串,以一种特殊的方式与openssl不完全标准,甚至不是很好,请参阅(我的) https://crypto.stackexchange。 com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/#35614 And you don't actually need to run openssl ;而且您实际上不需要运行openssl Java's own cryptographic functions can do exactly the same thing, although if you don't have and use the BouncyCastle third-party libraries you need some code to put together several primitives to produce the same results as openssl's EVP_BytesToKey . Java 自己的加密函数可以做完全相同的事情,尽管如果您没有并使用 BouncyCastle 第三方库,您需要一些代码将几个原语放在一起以产生与 openssl 的EVP_BytesToKey相同的结果。 There are numerous existing Qs on this, going back many years;关于这个问题有很多现有的问题,可以追溯到很多年前; I'll try to dig up some later.我稍后会尝试挖掘一些。 But of course you didn't ask about doing the cryptography, much less doing good cryptography, only about running the particular program specified.但是当然你没有问过做密码学,更不用说做好的密码学了,只是关于运行指定的特定程序。

You need to be running the shell first (pipes are a shell thing) and then pass the correct program and arguments to it .您需要先运行 shell(管道是 shell 的东西),然后将正确的程序和 arguments 传递给 Tested and working with Java 8:测试并使用 Java 8:

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        // Set the key and iv values
        String key = "1234567812345678";
        String iv = "1234567812345678";

        // Set the string to encrypt
        String string = "passwordToBeEncrypted";

        // Create the ProcessBuilder object and specify the command and its arguments
        String command = String.format("echo %s | openssl enc -aes-256-cbc -k %s -iv %s -base64", string, key, iv);
        ProcessBuilder pb = new ProcessBuilder("bash", "-c", command);
        pb.inheritIO();

        // Start the process and get the Process object
        Process p = pb.start();


        // Wait for the process to finish and get the exit code
        int exitCode = p.waitFor();
        System.out.println("Exit code: " + exitCode);

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM