Search code examples
javabashcygwinexecwindows-10

Call a ShellScript on Cygwin bash via Java Runtime Exec on Windows10


On Windows7, I had a perfectly working script. Now I was upgraded to Windows10 and it doesn't work anymore.

package ExecuteShell;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Properties;

import IO_Object.Writer;

/**
 * Die Klasse ExecuteShell kann einen Kommandozeilen-Befehl ausführen und gibt die Ausgabe auf 
 * Stdout zurück entweder als File oder als String
 */
public class ExecuteShell {
    ProcessBuilder builder;
    Process process = null;
    BufferedWriter process_stdin;
    BufferedReader reader, errReader;   

    public ExecuteShell() {
    }

     /**
     * schließt die Shell
     * @return
     */
    public int close() {
        // finally close the shell by execution exit command
        try {
            process_stdin.write("exit");
            process_stdin.newLine();
            process_stdin.flush();
        }
        catch (IOException e) {
            System.out.println(e);
            return 1;
        }
        return 0;
    }

    /**
     * Gibt Befehl zurück, der eine Shell im jeweiligen Betriebssystem öffnet </br>
     * Windows:  '"C:/cygwin64/bin/bash' (my local pc)</br>
     * Linux: '/bin/sh' (server)
     * @return shellcommand
     */
    private static String getShellCommandForOperatingSystem() {
        Properties prop = System.getProperties( );
        String os =  prop.getProperty( "os.name" );
        if ( os.startsWith("Windows") ) {
            //System.out.println("WINDOWS!");
            return "C:/cygwin64/bin/bash";
        } else if (os.startsWith("Linux") ) { 
            //System.out.println("Linux!");
            return"/bin/sh";
        }
        return "";      
    }

    /**
     * Ändert auszuführenden Befehl dahingehend ab, dass es im jeweiligen Betriebssystem funktioniert
     * @param command_list
     * @return
     */
    private static List<String> adjustCommandToOperatingSystem(List<String> command_list){
        Properties prop = System.getProperties( );
        String os =  prop.getProperty( "os.name" );
        if ( os.startsWith("Windows") ) {
            //System.out.println("WINDOWS!");
            command_list.add(0, "C:/cygwin64/bin/bash"); //Funktioniert seit Windows10 nicht mehr (ich vermute Rechte-Problem)
            command_list.add(1, "-c");
        } else if (os.startsWith("Linux") ) { 
            //System.out.println("Linux!");
            command_list.add(0, "/bin/sh");
            command_list.add(1, "-c");
        }
        return command_list;
    }

    /**
     * Wie der Name schon sagt: Führt Befehl aus und schreibt stdout in den mitgegebenen File
     * @param command_list
     * @param output_file
     * @return
     */
    public static int executeShell2File(List<String> command_list, String output_file) {

        String[] commands;
        Process p = null;
        StringBuffer output;
        BufferedReader reader, errreader;
        Writer w;
        String line; 
        int size;

        command_list = adjustCommandToOperatingSystem(command_list);
        size = command_list.size();
        commands = new String[size];        
        for (int i = 0; i<size; i++) {
            commands[i] = command_list.get(i);
        }
        output = new StringBuffer();
        try {
            //System.out.println("exec " + Arrays.toString(commands));
            p = Runtime.getRuntime().exec(commands);
            reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            errreader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            line = ""; 
            while ((line = reader.readLine())!= null) {
                output.append(line + "\n");
            }
            while ((line = errreader.readLine())!= null) {
                output.append(line + "\n");
            }
            reader.close();
            errreader.close();
        } catch (Exception e) {
            System.out.println("ExecuteShell: error in executeShell2File");
            e.printStackTrace();
            return 1;
        }
        System.out.println(output.toString());
        w = new Writer (output_file, "UTF-8");
        w.write(output.toString());
        w.close();
        return 0;
    }
}

I call executeShell2File from another class with

 commands.add("./myscript.sh " + file_out + " " + fine_in);
 ExecuteShell.executeShell2File(commands, "output.txt")

There is no error. Only file_out is never created when it was before on Windows7. So I think it might be a problem with rights. Does anyone have any idea?


Solution

  • This class is not the problem. The problem was the Shell Script in itself. Due to a different Cygwin version. One if-clause came to another result as expected.