背景是这样的。
我在本地通过 jsch 对一台远程机器执行命令,但该命令需 sudo 权限。
远程用户,只开放了登录用户的 sudo su 的权限。
导致想执行 sudo 命令需分两步:
sudo su -
docker ps
这里涉及到 session 切换,原生的 Jsch 的 ExecChannel 就用不了。
改为 ChannelShell 。
ChannelShell channel = (ChannelShell) session.openChannel("shell");
OutputStream os = channel.getOutputStream();
os.write(("sudo su - \r").getBytes());
os.flush();
os.write(("docker ps \r").getBytes());
os.flush();
os.write(("exit \r".getBytes());
os.flush();
os.write(("exit \r").getBytes());
os.flush();
但这个命令的返回,是一堆 shell 命令和结果糅合在一起,比较难提取真正的结果。
sudo su -
docker ps
exit
exit
20:51:19 [email protected]:~
$ sudo su -
20:51:19 [email protected]:~
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a3da88c5f8b ca6e5bfba5a5 "/usr/bin/tini -- /u…" 3 days ago Up 3 days docker_job_xxx
20:51:19 [email protected]:~
# exit
logout
20:51:19 [email protected]:~
$ exit
logout
而且如果远程机器换一个 os ,例如是 centos ,则:
Last login: Thu Mar 31 20:27:32 2022 from 192.168.1.2
sudo su -
docker ps
exit
exit
[[email protected] ~]$ sudo su -
Last login: Thu Mar 31 14:17:40 CST 2022 on pts/3
[[email protected] ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8929e8f93280 img_xxx "/usr/sbin/init" 5 months ago Up 5 months docker_job_yyy
[[email protected] ~]# exit
logout
[[email protected] ~]$ exit
logout
不同系统或者 terminal 可能会返回格式不同,导致真正想要的结果难以提取。
请教是否有好的解决方法呢?
文档:
1
kekxv 2022-03-31 21:49:40 +08:00 via iPhone
sudo chmod +s docker 路径
|
2
comlewin 2022-03-31 22:01:01 +08:00
/**
* 执行单句的命令 * 1 、命令之间使用; 分隔,各个命令的执行不会影响其他命令的执行,各个命令都会执行,但不保证每个命令都执行成功 * 2 、命令之间使用&& 分隔,前面的命令执行成功,才会去执行后面的命令,保证执行过程都是成功的 * 3 、命令之间使用|| 分隔,||是或的意思,只有前面的命令执行失败后才会去执行下一条命令,知道执行成功一条命令为止 */ public static String execCommand (Session session, String command, String charset) throws JSchException, IOException { ChannelExec channelExec = (ChannelExec) session.openChannel("exec"); channelExec.setPty(true); InputStream stdout = channelExec.getInputStream(); InputStream stderr = channelExec.getErrStream(); channelExec.setCommand(command); channelExec.connect(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } StringBuffer sb = new StringBuffer(); byte[] tmp = new byte[1024]; while(true) { while(stdout.available() > 0) { int len = stdout.read(tmp, 0, 1024); if (len < 0 ) { break; } String s_out = new String(tmp, 0, len); sb.append(s_out); //System.out.println(s); } while(stderr.available() > 0) { int len = stderr.read(tmp, 0, 1024); if (len < 0 ) { break; } String s_err = new String(tmp, 0, len); sb.append(s_err); //System.out.println(s); } break; } //sb.append(outinfo); //sb.append(errinfo); channelExec.disconnect(); // session 不做断开处理 //session.disconnect(); return sb.toString(); } |
3
Puteulanus 2022-04-01 00:39:01 +08:00 1
sudo su -c 'docker ps'
这样行吗 |
4
biubiuF 2022-04-01 00:43:21 +08:00
sudo -S -p 'password' "+ command
|
5
ysc3839 2022-04-01 02:51:58 +08:00 via Android 1
同样建议试试 sudo su -c
实在不行的话,执行命令前后都 echo 随机字符串,然后根据这两段字符串来分割 |
6
leiuu OP @kekxv 老哥 这个会写操作 不安全
@comlewin 是的 分隔符的方式适用没有 session 切换的场景 @Puteulanus @ysc3839 谢谢 2 位 竟然可以了! @biubiuF 不知道密码的 不过如果有密码是可行的! |
7
undownding 2022-04-01 17:11:34 +08:00
有没有一种可能,/var/run/docker.sock 可以用 curl 操作?(狗头)
|
8
undownding 2022-04-01 17:22:08 +08:00 1
su -c ' curl --unix-socket /run/docker.sock http://localhost/containers/json'
|
9
leiuu OP @undownding 老哥 太帅了 奥利给!
|