JSch - 如何以我切换到的用户身份发出命令
JSch - How to issue commands as the user I have switched to
我正在使用 Jsch 从 Windows 7.
远程连接到 Linux 服务器
我必须
(i) login to Linux server with my credentials
(ii) switch to root using a pmrun command [this is the procedure in our environment], and
(iii) execute su command to switch as "someuser"
(iv) execute further commands as that "someuser"
我完成了步骤 (i) 和 (ii)。
完成步骤(ii) 后,频道的InputStream 显示root 用户的命令提示符。所以我假设我现在已经成为root用户了。
现在,我是否需要获取 root 用户的会话才能进一步执行 su 命令,或者是否有办法以 root 用户身份执行更多命令?
有人请帮助。谢谢
更新:源代码
public class Pmrun {
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host="myself@linuxserver.com";
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
String command= "pmrun su -";
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
InputStream in = channel.getInputStream();
OutputStream outStream = channel.getOutputStream();
((ChannelExec)channel).setPty(true);
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
TimeUnit.SECONDS.sleep(10);
outStream.write("xxxxxxx\n".getBytes());
outStream.flush();
((ChannelExec)channel).setCommand("su - someuser");
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
str = "Yes";
return true;}
String passwd;
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
passwd="zzzzzzzz";
return true;
}
public void showMessage(String message){
}
}
}
使用"exec"通道,您只能执行一条命令。
其他命令在 su
内执行,而不是在 su
之后执行。
一个解决方案是在 su
命令行上提供另一个命令,例如:
su -c command
或使用其标准输入将命令提供给 su
:
outStream.write(("command\n").getBytes());
一般来说,我推荐第一种方法,因为它使用了更好定义的 API(命令行参数)。
扩展@Martin 的回答,另一种解决方案是在 "shell" 模式下打开频道,这将维持会话。像这样...
Channel channel = session.openChannel("shell")
pmrun 的工作方式是将您的用户 ID and/or 主要本地组 ID(或网络组)与已设置的基于角色的配置文件相匹配。此配置文件将授予您执行他们在配置文件中授权的命令的权利。如果没有 运行 pmrun 命令,它不会将您与他们的配置文件之一匹配,因此该命令将被拒绝。如果您查看 /opt/quest/bin 文件夹,您会看到其他可以使用的预包装 shell。 运行 pmwrapped_bash 与 运行 pmrun bash 相同。然后,您可以从他们那里发出命令 sudo -s 以获得 Sudo root 访问权限 and/or su - someuser 进入该帐户权限的访问权限。
您最终是否获得了您需要的代码,或者这个问题对您来说仍然是个问题,我可以提供帮助。
对我来说,当我们从 /etc/profile 文件中执行 pmrun $shell 时,我需要传递用户变量,这样用户就不需要键入它,因此他们的脚本可以运行一样。
问候 Nomadz
我有一个类似的问题,但经过大量研发和通过 SO 链接扫描后终于能够解决它。这是对我有用的程序。
public class SSHConn {
static Session session;
static String suCmds = "su - simba -c \"whoami ; pwd\"";
static String[] commands = {"whoami", suCmds};
public static void main(String[] args) throws Exception {
open();
runCmd(commands);
close();
}
public static void runCmd(String[] commands) throws JSchException, IOException {
for (String cmd : commands) {
System.out.println("\nExecuting command: " + cmd);
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(cmd);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
channel.connect();
//passing creds only when you switch user
if (cmd.startsWith("su -")) {
System.out.println("Setting suPasswd now....");
out.write((Constants.suPasswd + "\n").getBytes());
out.flush();
System.out.println("Flushed suPasswd to cli...");
}
captureCmdOutput(in, channel);
channel.setInputStream(null);
channel.disconnect();
}
}
public static void captureCmdOutput(InputStream in, Channel channel) throws IOException {
System.out.println("Capturing cmdOutput now...");
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
System.out.println(ee.getMessage());
}
}
}
public static void open() throws JSchException {
JSch jSch = new JSch();
session = jSch.getSession(Constants.userId, Constants.host, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(Constants.userPasswd);
System.out.println("Connecting SSH to " + Constants.host + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!\n");
}
public static void close() {
session.disconnect();
System.out.println("\nDisconnected channel and session");
}
}
输出:
Connecting SSH to my-unix-box.net - Please wait for few seconds...
Connected!
Executing command: whoami
Capturing cmdOutput now...
john
Executing command: su - simba -c "whoami ; pwd"
Setting suPasswd now....
Flushed suPasswd to cli...
Capturing cmdOutput now...
simba
/home/simba
Disconnected channel and session
我正在使用 Jsch 从 Windows 7.
远程连接到 Linux 服务器我必须
(i) login to Linux server with my credentials
(ii) switch to root using a pmrun command [this is the procedure in our environment], and
(iii) execute su command to switch as "someuser"
(iv) execute further commands as that "someuser"
我完成了步骤 (i) 和 (ii)。
完成步骤(ii) 后,频道的InputStream 显示root 用户的命令提示符。所以我假设我现在已经成为root用户了。
现在,我是否需要获取 root 用户的会话才能进一步执行 su 命令,或者是否有办法以 root 用户身份执行更多命令?
有人请帮助。谢谢
更新:源代码
public class Pmrun {
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host="myself@linuxserver.com";
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
String command= "pmrun su -";
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
InputStream in = channel.getInputStream();
OutputStream outStream = channel.getOutputStream();
((ChannelExec)channel).setPty(true);
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
TimeUnit.SECONDS.sleep(10);
outStream.write("xxxxxxx\n".getBytes());
outStream.flush();
((ChannelExec)channel).setCommand("su - someuser");
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
str = "Yes";
return true;}
String passwd;
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
passwd="zzzzzzzz";
return true;
}
public void showMessage(String message){
}
}
}
使用"exec"通道,您只能执行一条命令。
其他命令在 su
内执行,而不是在 su
之后执行。
一个解决方案是在
su
命令行上提供另一个命令,例如:su -c command
或使用其标准输入将命令提供给
su
:outStream.write(("command\n").getBytes());
一般来说,我推荐第一种方法,因为它使用了更好定义的 API(命令行参数)。
扩展@Martin 的回答,另一种解决方案是在 "shell" 模式下打开频道,这将维持会话。像这样...
Channel channel = session.openChannel("shell")
pmrun 的工作方式是将您的用户 ID and/or 主要本地组 ID(或网络组)与已设置的基于角色的配置文件相匹配。此配置文件将授予您执行他们在配置文件中授权的命令的权利。如果没有 运行 pmrun 命令,它不会将您与他们的配置文件之一匹配,因此该命令将被拒绝。如果您查看 /opt/quest/bin 文件夹,您会看到其他可以使用的预包装 shell。 运行 pmwrapped_bash 与 运行 pmrun bash 相同。然后,您可以从他们那里发出命令 sudo -s 以获得 Sudo root 访问权限 and/or su - someuser 进入该帐户权限的访问权限。
您最终是否获得了您需要的代码,或者这个问题对您来说仍然是个问题,我可以提供帮助。
对我来说,当我们从 /etc/profile 文件中执行 pmrun $shell 时,我需要传递用户变量,这样用户就不需要键入它,因此他们的脚本可以运行一样。
问候 Nomadz
我有一个类似的问题,但经过大量研发和通过 SO 链接扫描后终于能够解决它。这是对我有用的程序。
public class SSHConn {
static Session session;
static String suCmds = "su - simba -c \"whoami ; pwd\"";
static String[] commands = {"whoami", suCmds};
public static void main(String[] args) throws Exception {
open();
runCmd(commands);
close();
}
public static void runCmd(String[] commands) throws JSchException, IOException {
for (String cmd : commands) {
System.out.println("\nExecuting command: " + cmd);
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(cmd);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
channel.connect();
//passing creds only when you switch user
if (cmd.startsWith("su -")) {
System.out.println("Setting suPasswd now....");
out.write((Constants.suPasswd + "\n").getBytes());
out.flush();
System.out.println("Flushed suPasswd to cli...");
}
captureCmdOutput(in, channel);
channel.setInputStream(null);
channel.disconnect();
}
}
public static void captureCmdOutput(InputStream in, Channel channel) throws IOException {
System.out.println("Capturing cmdOutput now...");
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
System.out.println(ee.getMessage());
}
}
}
public static void open() throws JSchException {
JSch jSch = new JSch();
session = jSch.getSession(Constants.userId, Constants.host, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(Constants.userPasswd);
System.out.println("Connecting SSH to " + Constants.host + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!\n");
}
public static void close() {
session.disconnect();
System.out.println("\nDisconnected channel and session");
}
}
输出:
Connecting SSH to my-unix-box.net - Please wait for few seconds...
Connected!
Executing command: whoami
Capturing cmdOutput now...
john
Executing command: su - simba -c "whoami ; pwd"
Setting suPasswd now....
Flushed suPasswd to cli...
Capturing cmdOutput now...
simba
/home/simba
Disconnected channel and session