【问题标题】:Java code to execute a .sh file执行 .sh 文件的 Java 代码
【发布时间】:2011-09-21 19:54:33
【问题描述】:

我有一个.sh 文件存储在某些 Linux 系统中。文件的完整路径为:

/comviva/CPP/Kokila/TransactionHandler/scripts/stopTH.sh

我正在尝试执行它

Runtime.getRuntime().exec(`/comviva/CPP/Kokila/TransactionHandler/scripts/stopTH.sh`)

但它抛出了一些异常。

我想在 MS-Windows 环境中从我的 java 程序执行该文件;有可能吗?

【问题讨论】:

  • 不可能在 Windows 中以本机方式运行 Unix shell 脚本,这正是您想要做的——您需要将该 Unix shell 脚本转换(不仅仅是重命名)到 Windows批处理文件(带有 .bat 或 .cmd 文件扩展名/后缀)。哪个异常被抛出?您使用的是哪个版本的 Java?
  • 提问时总是列出例外情况。
  • 您提到 Linux 系统 Windows 系统。 shell 脚本位于您的 Linux 系统上,对吗?您的 Java 应用程序(应该启动 shell 脚本)位于 Windows 系统上。对吗?
  • 什么是“一些例外”。这是一个重要信息!
  • 离题,属于stackoverflow;顺便说一句,你不能直接执行一个shell脚本,你必须执行bash

标签: windows linux unix java shell


【解决方案1】:

要在 Windows 上执行 .sh 脚本,您必须安装合适的命令解释器。例如,您可以在 Windows 机器上安装 Cygwin 环境并使用它的 bash 解释器。

但是,即使使用 Cygwin,Windows 也不是 Linux。如果不进行更改,某些脚本不会从一种环境移植到另一种环境。如果我在 Linux 环境中通过 Java 执行脚本时遇到问题,我更愿意在该环境中调试问题。

请记住,您可以在 Linux 上以调试模式启动 Java 进程,然后将 Windows 中的 IDE 调试器附加到该远程进程。

【讨论】:

    【解决方案2】:

    感谢大家的回复。我找到了解决问题的方法。对于这种情况,我们需要将我的 Windows 机器绑定到 Linux 系统。这是有效的代码:

    public String executeSHFile(String Username, String Password,String  Hostname)
        {
            String hostname = Hostname;
            String username = Username;
            String password = Password;
            try{
                Connection conn = new Connection(hostname);
                   conn.connect();
                   boolean isAuthenticated = conn.authenticateWithPassword(username, password);
                   if (isAuthenticated == false)
                    throw new IOException("Authentication failed.");
                   Session sess = conn.openSession();
                  sess.execCommand("sh //full path/file name.sh");
    
                   System.out.println("Here is some information about the remote host:");
                   InputStream stdout = new StreamGobbler(sess.getStdout());
                   BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
                   while (true)
                    {
                        String line = br.readLine();
                        if (line == null)
                            break;
                        current_time=line;
                        System.out.println(line);
                    }
    
                   System.out.println("ExitCode: " + sess.getExitStatus());
                   /* Close this session */
    
                    sess.close();
    
                    /* Close the connection */
    
                    conn.close();
            }catch(IOException e)
            {
                e.printStackTrace(System.err);
                System.exit(2);
            }finally{
    
            }
    }
    

    谢谢。

    【讨论】:

    • 你使用Connection/Session 类:它们来自哪个库?
    【解决方案3】:

    这是我的代码。正如评论所说,在 Linux 上工作,在 Windows (XP) 上失败。 AFAIK Windows 的问题在于 cmd.exe 的参数很奇怪。对于您的特定子任务,您可能可以通过使用引号以及将子任务参数嵌入子任务本身来使其工作。

    /** Execute an abritrary shell command.
      * returns the output as a String.
      * Works on Linux, fails on Windows,
      * not yet sure about OS X.
      */
    public static String ExecuteCommand( final String Cmd ) {
        boolean DB = false ;
        if ( DB ) {
            Debug.Log( "*** Misc.ExecuteCommand() ***" );
            Debug.Log( "--- Cmd", Cmd );
        }
    String Output = "";
    String ELabel = "";
        String[] Command = new String[3];
        if ( Misc.OSName().equals( "WINDOWS" ) ) {
            Command[0] = System.getenv( "ComSPec" );
            Command[1] = "/C";
        } else {
            Command[0] = "/bin/bash";
            Command[1] = "-c";
        }
    Command[2] = Cmd;
        if (DB ) {
            Debug.Log( "--- Command", Command );
        }
        if ( Misc.OSName().equals( "WINDOWS" ) ) {
            Debug.Log( "This is WINDOWS; I give up" );
            return "";
        }
    try {
            ELabel = "new ProcessBuilder()";
            ProcessBuilder pb = new ProcessBuilder( Command );
            ELabel = "redirectErrorStream()";
            pb.redirectErrorStream( true );
            ELabel = "pb.start()";
            Process p = pb.start();
            ELabel = "p.getInputStream()";
            InputStream pout = p.getInputStream();
            ELabel = "p.waitFor()";
            int ExitCode = p.waitFor();
            int Avail;
            while ( true ) {
                ELabel = "pout.available()";
                if ( pout.available() <= 0 ) {
                    break;
                }
                ELabel = "pout.read()";
                char inch = (char) pout.read();
                Output = Output + inch;
            }
            ELabel = "pout.close()";
            pout.close();
        } catch ( Exception e ) {
            Debug.Log( ELabel, e );
        }
    
        if ( DB ) {
            Debug.Log( "--- Misc.ExecuteCommand() finished" );
        }
        return Output;
    }
    

    }

    【讨论】:

    • Java 中的方法和变量的第一个字符不应该大写。
    【解决方案4】:

    我在这里做了一个快速测试,假设你的机器上有 /bin/bash,以下工作:

    我的 /tmp/test.sh:

    #!/bin/bash
    echo `ls`
    

    我的java代码:

    try {
        InputStream is = Runtime.getRuntime().exec("/bin/bash /tmp/test.sh").getInputStream();
        int i = is.read();
        while(i > 0) {
            System.out.print((char)i);
            i = is.read();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    输出:当前目录下的所有文件

    编辑:我有点忽略了“从 Windows 执行”评论。我不知道你的意思。

    【讨论】:

      【解决方案5】:

      您可以制作一个可以在 Windows 上运行的 .bat 文件(批处理文件)。 将.sh文件的内容放到.bat文件中 从您的应用程序启动一个流程,例如:

      Process.Start("myFile.bat");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-24
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        • 1970-01-01
        相关资源
        最近更新 更多