使用java中的jsch在linux中通过sudo命令执行shell脚本以启动服务

Posted

技术标签:

【中文标题】使用java中的jsch在linux中通过sudo命令执行shell脚本以启动服务【英文标题】:Executing a shell script to start a service by sudo command in linux using jsch in java 【发布时间】:2016-04-06 13:51:21 【问题描述】:

如何在 Linux 中通过 Java 执行 shell 脚本以通过 sudo 命令启动服务 例如:cmd="sudo path/script.sh start"

这个 Java 程序将在 linux 中执行命令。 即使我能够执行 'sudo ls -lt path' 和 'sudo path/script.sh start'

//Java
public List<String> sshConnection(String usr,String host,int port,String pass)

      Session session=null;
      List<String> outputList = new ArrayList<String>();
      try
      
        JSch jsch = new JSch();
        session = jsch.getSession(usr, host, port);
        session.setPassword(pass);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();  

        //String cmd="sudo ls path";            //working fine
        String cmd="sudo path/script.sh start"; //service is not starting..but getting the exact output as linux

        ChannelExec channelEx=new ChannelExec();

        channelEx = (ChannelExec) session.openChannel("exec");

        if(cmd.contains("sudo"))
        
            channelEx.setPty(true);
        

        ((ChannelExec) channelEx).setCommand(cmd);
        channelEx.connect();

        InputStream cmdOp = channelEx.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(cmdOp));

        String printOp;
        while ((printOp = br.readLine()) != null) 
        
            outputList.add(printOp);
        
        br.close();

        channelEx.disconnect();

     
    catch (Exception ex) 
    
        System.out.println(ex.getMessage());
     
    finally 
    
        if (channelEx != null) 
        
            channelEx.disconnect();
        
    

    if(session!=null)
    
        session.disconnect();
    
    System.out.println("disconnected successfully");
    return outputList;

我直接在 linux 中执行了相同的命令,并得到一个输出告诉“服务正在运行”和进程 ID。当我使用 ps 命令对进程 ID 执行 grep 时,它显示了具有相同进程 ID 的服务。 但是当我通过上面的 Java 程序执行相同的命令时,我在输出控制台中得到了带有进程 ID 的 linux 的确切输出('服务正在运行')。在 java 程序执行之后,我对进程 ID 进行了 grep(来自 Java 输出控制台)在 linux 中,没有使用该进程 ID 运行此类进程。 我找不到哪里出了问题。 请帮忙!

【问题讨论】:

不要认为这与 Java 程序有任何关系,因为该命令似乎已在服务器上运行。 【参考方案1】:

您正在启动进程,然后立即终止进程树。

尝试使用

channelEx.setPty(false);

或者将 nohup 添加到您的命令行。见...

jsch ChannelExec run a .sh script with nohup "lose" some commands

【讨论】:

嗨 Kervin,我尝试了 channelEx.setPty(false)。它不起作用。 setPty 是设置伪终端,没有那个 sudo 命令将不起作用。我尝试设置 true 和后来设置 false。但什么也没发生。我也试过nohup。 cmd="nohup sudo path/script.sh start" 没用。 我在 setPty(true) 和 setPty(false) 中使用了 sys.out;在执行单个 sudo 命令期间,终端被设置和重置两次,这意味着终端在执行之前断开连接命令。我认为这是它失败的地方。 有什么办法可以等到 sudo 命令执行完成后再终止?请帮忙! 直接尝试 nohup 你的 shell 而不是 sudo。你遇到了什么错误?您是否还按照链接的建议重定向了 stderr ?例如。 nohup bash -c "sudo path/script.sh start 2>&1 &" && sleep 4 作为你的命令 我按照你给出的那样尝试(我用 ' 替换了“,因为 cmd 是一个字符串变量)。它显示了这个“nohup:忽略输入并将输出附加到 `nohup.out'” 服务也是没有开始。【参考方案2】:

我能够以 root 用户身份启动命令,并在 Java 代码退出后查看进程 ID。

    使用命令channelExec.setCommand("sudo -S -p '' " + cmd); 使用 nohup 运行您的命令(例如 nohup start.sh) 确保使用export 命令为脚本设置了所有环境变量。

【讨论】:

以上是关于使用java中的jsch在linux中通过sudo命令执行shell脚本以启动服务的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSch sudo 示例和 Channel.setPty 在远程主机上运行 sudo 命令

在 Java 中通过 SSH 隧道连接到 Mongo 数据库

JSCH sudo su 命令“tty”错误

如何在 Cyber​​Duck 中通过 SFTP 使用 sudo?

使用 JSch 的多个命令

使用 JAVA 拦截 Jsch 提示在 UNIX shell 中输入密码