java.lang.Runtime exception “Cannot run program”

后端 未结 2 650
太阳男子
太阳男子 2021-01-24 09:22

I am getting an exception like java.io.IOException: Cannot run program cat /home/talha/* | grep -c TEXT_TO_SEARCH\": error=2, No such file or directory while execut

相关标签:
2条回答
  • 2021-01-24 09:34

    $PATH is an environment variable that tells the system where to search for executable programs (it's a list of directories separated by colons). It is usually set in your .bashrc or .cshrc file but this is only loaded when you log in. When Java runs, $PATH is likely not set because the rc file is not executed automatically, so the system can't find programs without specifying exactly where they are. Try using /bin/cat or /usr/bin/cat instead of just cat and see if it works. If it does, $PATH is your problem. You can add $PATH=/bin:/usr/bin to your script or just leave it with the directory name specified (e.g. /bin/cat).

    Just because you can execute it in a login session doesn't mean it will work the same when a daemon like your Java program runs. You have to know what's in your .bashrc or .cshrc file and even sometimes how the system file is written (/etc/bashrc) in order to know how to write a script that runs under a daemon. Another consideration is that daemons often run under the context of a different user, and that throws things off, too.

    0 讨论(0)
  • 2021-01-24 09:41

    Runtime.exec does not use a shell (like, say, /bin/bash); it passes the command directly to the operating system. This means wildcards like * and pipes (|) will not be understood, since cat (like all Unix commands) does not do any parsing of those characters. You need to use something like

    p = new ProcessBuilder("bash", "-c", command).start();
    

    or, if for some bizarre reason you need to stick to using the obsolete Runtime.exec methods:

    p = Runtime.getRuntime().exec(new String[] { "bash", "-c", command });
    

    If you are only running that cat/grep command, you should consider abandoning the use of an external process, since Java code can easily traverse a directory, read lines from each file, and match them against a regular expression:

    Pattern pattern = Pattern.compile("TEXT_TO_SEARCH");
    Charset charset = Charset.defaultCharset();
    
    long count = 0;
    
    try (DirectoryStream<Path> dir =
        Files.newDirectoryStream(Paths.get("/home/talha"))) {
    
        for (Path file : dir) {
            count += Files.lines(file, charset).filter(pattern.asPredicate()).count();
        }
    }
    

    Update: To recursively read all files in a tree, use Files.walk:

    try (Stream<Path> tree =
        Files.walk(Paths.get("/home/talha")).filter(Files::isReadable)) {
    
        Iterator<Path> i = tree.iterator();
        while (i.hasNext()) {
            Path file = i.next();
            try (Stream<String> lines = Files.lines(file, charset)) {
                count += lines.filter(pattern.asPredicate()).count();
            }
        };
    }
    
    0 讨论(0)
提交回复
热议问题