JSch实现sudo多命令执行:登录后切换用户执行指定脚本
Running Multiple Commands After Sudo User Switch with JSch
Got it, let's break down how to fix your JSch code to run commands after switching to tstusr via sudo su -. The key thing here is that once you switch users, you're in an interactive shell—so you can't just spin up a new ChannelExec for each command. You need to send all subsequent commands through the same shell's input stream.
Here's the refined, working code with explanations for the critical parts:
import com.jcraft.jsch.*; import java.io.*; import java.util.ArrayList; import java.util.List; public class SudoCommandRunner { public static void main(String[] args) { Session session = null; ChannelExec channel = null; try { // Initialize your JSch session (fill in your server details here) JSch jsch = new JSch(); session = jsch.getSession("your_local_user", "your_server_host", 22); session.setPassword("your_local_password"); // Skip host key check (not recommended for production—add known hosts instead) session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // Define the sudo switch command and your target commands String sudoSwitchCmd = "sudo su - tstusr"; List<String> postSwitchCommands = new ArrayList<>(); postSwitchCommands.add("./app/t1.sh status"); // Add more commands if needed: postSwitchCommands.add("ls -l /app"); // Set up the exec channel channel = (ChannelExec) session.openChannel("exec"); // Enable PTY—this is mandatory for sudo/su to work (they need an interactive terminal) channel.setPty(true); channel.setCommand(sudoSwitchCmd); // Get streams for input, output, and error OutputStream shellInput = channel.getOutputStream(); InputStream shellOutput = channel.getInputStream(); InputStream shellError = channel.getErrStream(); channel.connect(); // Handle sudo password prompt (skip this if your user has passwordless sudo) BufferedReader errReader = new BufferedReader(new InputStreamReader(shellError)); String line; while ((line = errReader.readLine()) != null) { if (line.contains("[sudo] password for")) { // Send your sudo password followed by a newline shellInput.write(("your_sudo_password\n").getBytes()); shellInput.flush(); break; } } // Send each post-switch command to the shell for (String cmd : postSwitchCommands) { // Write the command + newline to execute it shellInput.write((cmd + "\n").getBytes()); shellInput.flush(); // Short delay to let the command run (replace with smarter output checking in production) Thread.sleep(1000); } // Exit the tstusr shell to close the channel cleanly shellInput.write(("exit\n").getBytes()); shellInput.flush(); // Read and process the output BufferedReader outReader = new BufferedReader(new InputStreamReader(shellOutput)); List<String> commandResults = new ArrayList<>(); while ((line = outReader.readLine()) != null) { commandResults.add(line); System.out.println(line); // Print or store the result as needed } // Read any error output while ((line = errReader.readLine()) != null) { System.err.println("Error: " + line); } } catch (JSchException | IOException | InterruptedException e) { e.printStackTrace(); } finally { // Clean up resources if (channel != null && channel.isConnected()) { channel.disconnect(); } if (session != null && session.isConnected()) { session.disconnect(); } } } }
Key Notes to Remember:
- PTY is non-negotiable:
channel.setPty(true)enables the interactive terminal thatsudoandsurequire. Without this, the switch command will fail silently or throw errors. - Password handling: If your user requires a password for sudo, you have to listen for the password prompt in the error stream and send the password. For passwordless sudo, you can remove this block.
- Single stream for all commands: All commands after switching users go through the same
OutputStream—each command needs a newline to trigger execution in the shell. - Clean exit: Always send
exitto close thetstusrshell, otherwise the channel will hang open and your program might get stuck. - Output reading: In production, replace the
Thread.sleep()with logic that reads the output until you see a command completion marker (like the shell prompt) to avoid timing issues.
Why Not Multiple Channels?
Each ChannelExec runs in the context of your original user. If you open a new channel after running sudo su -, it won't be in the tstusr environment—so you have to stick to the same channel and shell session for all post-switch commands.
内容的提问来源于stack exchange,提问作者Rajar R
相关产品推荐
相关产品推荐

