
背景是这样的。
我在本地通过 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 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 同样建议试试 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 su -c ' curl --unix-socket /run/docker.sock http://localhost/containers/json' |
9 leiuu OP @undownding 老哥 太帅了 奥利给! |