使用JSch执行Pbrun命令后无法执行后续多条命令的问题
解决JSch执行Pbrun后无法执行后续命令的问题
我来帮你搞定这个问题!你遇到的核心问题是:pbrun myser -u someuser会启动一个全新的shell会话,切换到指定用户的环境。而你用分号把它和后面的cd /tmp; sh tmp.sh status连起来时,后面的命令其实是在原来的用户会话里执行的,根本没进入pbrun切换后的环境,所以自然达不到预期效果。
下面给你几个可行的解决方案,你可以根据自己的场景选择:
方案1:把后续命令作为pbrun的参数传递
pbrun支持通过-c参数直接指定要在目标用户环境下执行的命令。你可以把cd和脚本执行命令打包成一个字符串,作为-c的参数,这样所有命令都会在切换后的用户环境里运行。修改你的代码如下:
String script = "pbrun myser -u someuser -c 'cd /tmp; sh tmp.sh status'";
这里用单引号把命令包起来,是为了避免原shell提前解析里面的分号,确保整个命令串都传递给pbrun启动的新shell执行。
方案2:用ChannelShell模拟交互式会话
如果你的场景需要执行多条交互式命令(比如切换用户后还要执行多个操作),建议使用JSch的ChannelShell来模拟真实的SSH交互式会话。这样你可以先发送pbrun切换用户的命令,等切换完成后,再发送后续命令。示例代码大概是这样:
public void connect() { try { JSch jsch = new JSch(); session = jsch.getSession(user, host, 22); session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 打开Shell通道,模拟交互式会话 ChannelShell channel = (ChannelShell) session.openChannel("shell"); InputStream in = channel.getInputStream(); OutputStream out = channel.getOutputStream(); channel.connect(); // 发送pbrun切换用户命令,注意要加换行符模拟回车 String pbrunCmd = "pbrun myser -u someuser\n"; out.write(pbrunCmd.getBytes()); out.flush(); // 这里可以优化:读取输入流,直到出现目标用户的提示符,再发送后续命令 // 简单示例用延迟,实际生产环境建议根据输出判断切换完成 Thread.sleep(1000); // 发送后续命令 String nextCmd = "cd /tmp; sh tmp.sh status\n"; out.write(nextCmd.getBytes()); out.flush(); // 读取命令执行的输出 byte[] buffer = new byte[1024]; while (in.available() > 0) { int len = in.read(buffer); if (len < 0) break; System.out.print(new String(buffer, 0, len)); } // 关闭通道和会话 channel.disconnect(); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } }
方案3:用脚本文件批量执行命令
如果你的命令逻辑比较复杂,也可以把所有需要执行的步骤写到一个脚本文件里,然后用pbrun执行这个脚本:
- 先把脚本(比如
run_script.sh)上传到目标机器的/tmp目录,脚本内容如下:
cd /tmp sh tmp.sh status
- 然后在Java代码里执行pbrun命令运行这个脚本:
String script = "pbrun myser -u someuser -c 'sh /tmp/run_script.sh'";
关键提醒
一定要记住:pbrun是启动一个新的shell会话来切换用户,不是在当前shell里切换身份。所以所有需要在目标用户环境下执行的命令,必须放在这个新shell的上下文里,不能直接用分号和pbrun命令连在一起执行。
内容的提问来源于stack exchange,提问作者Rajendra
相关产品推荐
相关产品推荐

