我正在尝试解决我需要登录众多的情况 服务器无法使用ssh密钥。结果我 制定一个"这是一个不好的做法" -expect script:
#!/usr/bin/expect
set arg1 [lindex $argv 0]
spawn ssh $arg1 -l user "hostname; env x='() { :;}; echo vulnerable' bash -c \"echo this is a test\"; echo"
expect " password:"
send "my_supersecret_password\n"
interact
运行它可以正常工作:
$ ./ssh.expect server
spawn ssh server -l user hostname; env x='() { :;}; echo vulnerable' bash -c "echo this is a test"; echo
user@server's password:
server
this is a test
$
但是在多个系统上运行时我需要一个更好的格式化列表,所以我尝试让perl重新格式化数据:
$ ./ssh.expect server | perl -e '$dump = <>; $dump = <>; chomp($line1 = <>); chomp($line2 = <>); $dump = <>; print "$line1:$line2\n";'
:this is a test
打印服务器名称,就像它以\ r结尾一样。我不认为应该这样做。你同意吗?如何在打印服务器名称后让系统不返回到第0列?
我可以通过在我的print上添加换行来验证这两个变量是否包含数据:
$ ./ssh.expect server | perl -e '$dump = <>; $dump = <>; chomp($line1 = <>); chomp($line2 = <>); $dump = <>; print "$line1\n:$line2\n";'
server
:this is a test
编辑:
如评论所述,以下工作。
./ssh.expect server | tr -d '\r' | perl -e '$dump = <>; $dump = <>; chomp($line1 = <>); chomp($line2 = <>); $dump = <>; print "$line1:$line2\n";'
server:this is a test
不应该让tr冗余吗?
答案 0 :(得分:2)
Expect使用伪TTY与它产生的命令进行通信,在这种情况下是ssh进程。默认情况下,TTY和PTY将在输出文本中将\ n转换为\ r \ n(LF到CRLF)。因此,除非您努力删除CR,否则您的expect脚本的输出将包含CRLF序列。您可以通过以交互方式运行expect
来查看此内容:
$ expect -c 'spawn echo foo; interact' | od -a
0000000 s p a w n sp e c h o sp f o o cr nl
0000020 f o o cr nl
0000025 ^^--^^--note
TTY LF-&gt; CRLF转换由TTY&#34; onlcr&#34;旗。我在期待剧本中打开了那个标志但是没有成功。
Perl的chomp
命令删除perl输入记录分隔符($/
变量)的序列,这些序列在Unix系统上只是\ n。换句话说,默认情况下,\ r对unix上的chomp
并不特殊。如果您愿意,可以在perl脚本中更改$/
以使chomp删除回车符。或者您可以通过tr
管理期望脚本的输出,如上所述。
答案 1 :(得分:0)
\r
;键盘上的Enter键实际发送\r
,Linux内核将其转换为\n
; \r\n
是输出到终端的行,Linux内核在输出时将\n
转换为它。可以禁用这些翻译,将终端置于“原始模式”,程序可以直接与终端通话(参见http://www.linusakesson.net/programming/tty/)。这是全屏程序所必需的,例如vi
,nethack
等
我的猜测是ssh
将终端置于客户端(您的终端)的原始模式,因此服务器端的内核可以执行\n
- &gt;关于输出的\r\n
翻译。这使您可以在vi
下运行ssh
,但这意味着当您在程序下运行ssh
时需要假装成终端,这意味着发送\r
作为EOL输出并在输入时读取\r\n
作为EOL。