如何创建 ssh 会话,ssh foo@bar
除了任何颜色格式之外?唯一的要求是设置应该在ssh
命令中声明,不能在配置文件中设置。
顺便说一句,原因是我想将 ssh shell 结果获取到 Scala 程序,如果您有兴趣,请查看 git repos 更多详细信息。因此,[03m
应该删除颜色代码,例如(也许是其他颜色代码)。我不能指望远程主机进行一些设置并让它没有颜色。
更新
关于
JSch
SSH库,有一些设置需要解释一下:setPtyType("dumb")
、设置与仿真终端dumb
会话的参数与等类似。仿真终端结果中不包含任何颜色代码。设置该属性后 使用将打印。dumb
Linux
VT100
dumb
echo $TERM
dumb
setPty(bool enable)
默认是false
,但如果我显式设置,setPty(false)
结果将被破坏。不幸的是,我还没有找到一个 API 来在运行时获取 pty 值,并且该库缺乏文档,尽管它是 Java 事实上的标准 SSH 库。
为什么我想在 ssh 中使用 ssh ?
- 需要此功能是因为某些关键文件可能位于远程主机上。因此,我需要先登录远程主机,然后登录另一台主机。
- 登录终端并使用 ssh 连接到另一台主机是正常操作。
如果 Scala 库有一些颜色代码,它的输出是什么?
脚步:- 使用
JSch
创建 ssh 会话连接。 - 使用
ls
- 连接到新外壳
cd /var
在新外壳上 使用ls
在新外壳上使用。
- 使用
//use `JSch` create a ssh session connection.
val shell = new Shell(Auth("hostname", "username", 22, "pwd"))
//use `ls`
shell.exc("ls")
//connect to new shell
val newShell = shell.newShell(Auth("xxx.xxx.xxx.xxx", "root", 22, "pwd")).right.get
//use `cd /var` on the new shell
newShell.exc("cd /var")
//use `ls` on the new shell.
newShell.exc("ls")
newShell.exit()
shell.disconnect()
该命令shell.exc("ls")
输出完美,因为我正在使用dumb
属性JSch.setPtyType()
。它不打印颜色代码。
颜色代码的问题发生在newShell.exc("ls")
,它打印:
[0m[01;34mbackups[0m [01;34mcache[0m [01;34mlib[0m [01;34mlocal[0m [01;36mlock[0m [01;34mlog[0m [01;34mmail[0m [01;34mopt[0m [01;36mrun[0m [01;34mspool[0m [30;42mtmp[0m
显然,它包含一些颜色代码。 val newShell
是由一个裸命令生成的ssh -t -o StrictHostKeyChecking=no foo@bar
,所以它的JSch
方式不同。
目前,我只想处理颜色代码并保持响应信息仅包含文本:
backups cache lib local lock log mail opt run spool tmp
希望问题能弄清楚。再次感谢。
再次更新
抱歉我的两个错误。
TERM=dumb
根本不需要,因为JSch
有设置dumb
,新的 ssh 会欺骗它。setPty(true)
(或 -T 参数)受到影响,我的测试失败了,因为另一个问题是MAGIC_SPLIT
常量应该以该模式开始/结束,\n
而不是\r\n
在此模式下。
我应该做哪些改变?
用于setPty(true)
所有消息协议,其中包含JSch
并ssh
带有-T参数,而不是dumb
因为它是更清晰的响应。
还剩下什么问题?
某些远程主机stdin: is not a tty
在成功登录后会响应一条错误消息,因为该远程主机echo $?
将失败。但这已经是题外话了。
关于这个话题
回到问题how to use ssh session with no color formatting?
,答案是use-T
参数for ssh
。
最后,非常感谢@sourcejedi 的耐心。
答案1
你就这么做吧。
输出通过管道传输到另一个程序的本地程序预计会检测到它们没有连接到任何终端,因此它们不能使用任何颜色代码(颜色代码在终端之间有所不同,因此需要 TERM 环境变量)。
当本地程序ssh
通过管道传输到另一个程序并且您不传递选项时-tt
,它会抑制“伪终端”的分配并使用管道代替。也可以看看man ssh
。
如果您的代码分配“伪终端”而不是使用管道来捕获输出,那么您会应该注意到这个事实。在大多数情况下,与使用管道相比,所需的代码更加晦涩且更长;大多数时候您不需要(或者如您所说,想要)PTY 的额外功能。
除非我认为你的问题是错误的(在更新部分)
假设您实际上没有运行ssh
,而是运行sshpass -p '${auth.password}' ssh
...
sshpass,根据它的man
页面,正在“在专用的 TTY 中运行 ssh,欺骗它认为它正在从交互式用户那里获取密码”(是的,这是另一个 PTY)。
在这种情况下,您需要再次禁用内部 SSH 连接的正常终端行为。即使用ssh -T
(ssh -t
不像代码提交之一!)。
我认为前缀 withTERM=dumb
也能达到非常相似的效果。这是一个解决方法。 ssh -T
避免了弄乱 TERM 的需要。不过我TERM=dumb sshpass sh -c 'echo $TERM'
在我的电脑上测试了一下,好像通过了OK,也许你觉得更简单。
下一个问题:当您的代码是时,为什么您的测试告诉您这是必要的还TERM=dumb
在启动(内部)命令之前已经开始设置ssh
?你会期望他们 ssh
已经继承TERM=dumb
了。查看 Jsch 的代码。我认为你setPtyType("dumb")
不会有任何影响,因为你没有任何电话setPty(true)
。
我的理解与你“打破”的断言相矛盾setPty(false)
,但你没有说如何打破。