我编写了一个脚本来建立 SSH 隧道并通过该隧道连接到数据库。
极度简化的概括(省略明显的参数和额外的逻辑):
sshTunnelCmd = "ssh -N -p %s -L %s:127.0.0.1:%s -i %s %s@%s" % (
sshport, localport, remoteport, identityfile, user, server
)
args = shlex.split(sshTunnelCmd)
tunnel = subprocess.Popen(args)
time.sleep(2)
con = MySQLdb.connect(host="127.0.0.1", port=localport, user=user, passwd=pw, db=db)
## DO THE STUFF ##
con.close()
tunnel.kill()
等效于 shell 的命令如下,我已经测试了命令和脚本在“干净的客户端”条件下(即重启后)的工作情况。
ssh -N -p 22 -L 5000:127.0.0.1:3306 user@server
mysql --port 5000 -h 127.0.0.1 -u dbuser -p
SSH 登录使用 key ,在~/.ssh/config 服务器配置为
Host server
Hostname F.Q.D.N
Port 22
User user
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p
ControlPersist 600
IdentityFile ~/.ssh/id_rsa
在## DO THE STUFF## 部分中,有代码尝试以普通用户身份连接到数据库。如果出现异常,它会要求手动输入 root 凭据,创建普通用户并继续执行这些操作(普通查询,全部手动测试并在干净的客户端条件下在 python 代码中工作)。
ruz = raw_input('root user? ')
print (ruz)
rup = raw_input('root password? ')
print (rup)
print ("Root connecting to database.")
try:
cxroot = MySQLdb.connect(host=host, port=port, user=ruz, passwd=rup)
cur = cxroot.cursor()
except MySQLdb.Error, e:
print ("Root failed, sorry.")
print "Error %d: %s" % (e.args[0],e.args[1])
print ("GAME OVER.")
return -1
在干净的客户端下,第一次和一些后续的执行工作良好,包括当我尝试测试脚本的健壮性和删除用户服务器端时。然而,在某些时候,它以一种奇怪的方式卡在上面代码块中的第二个 raw_input 之后。输出:
root user? root
root
root password? s3cReTsTr1n9
-bash: line 1: s3cReTsTr1n9: command not found
此时我唯一能做的就是终止进程或按 CTRL+C,然后是以下回溯:
^CTraceback (most recent call last):
File "./initdb.py", line 571, in <module>
main()
File "./initdb.py", line 526, in main
connection = connectDB ('127.0.0.1', localport, dbuser, dbpw, db)
File "./initdb.py", line 128, in connectDB
rup = raw_input('root password? ')
KeyboardInterrupt
我注意到的另一个意外症状是终端窗口的键盘输入(我在 Xubuntu 14.04LTS 中的 bash 终端中运行它)变得虚假地没有响应,所以我必须关闭终端选项卡并启动一个新选项卡。这会清除键盘输入,但不会清除脚本行为。
我曾尝试寻找解决方案,但通常的搜索引擎对我的情况没有帮助,可能是因为我不完全了解发生了什么。我怀疑键盘输入以某种方式重定向到一个进程,可能是隧道子进程,但我无法解释为什么第一个 raw_input 按预期工作而第二个没有。
我也对我创建隧道的方式感到不舒服,因此欢迎任何关于更强大的隧道创建的建议。具体来说,我希望对隧道的创建有更细粒度的控制,而不是等待任意两秒钟来建立隧道,因为我没有来自该子进程的反馈。
感谢您分享您的时间和专业知识。
最佳答案
我的回答分为两个部分:我将如何进行诊断,以及我将如何进行诊断。
首先,我建议使用失败的提示作为进行一些探索的机会。
这里有两种方法:
主机名(或其他任何内容)即可找出它的运行位置bash,或者如果远程端有 X 服务器,请将 -X 添加到您的 ssh 命令,然后键入终端程序 (xterm , gnome-terminal 等)。在您的新 shell 中,您可以四处查看发生了什么。如果您确定它在客户端运行,您可以使用 strace 对其进行诊断:
strace -f -o blah.log yourscript.py
... 您可以在其中输入易于搜索的密码字符串,然后在 blah.log 中搜索该密码。由于 -f 标志,它将打印试图执行它的进程的 PID;从那里回溯,您可能会发现 PID 是从另一个 PID 的分支开始的。该 PID 是试图执行它的原因,因此您应该能够从那里进行调查。
至于我会怎么做:我对 python 还是很陌生,所以我倾向于使用 perl 或 expect。在 perl 路径下,您可能会看到:
-N,并且您将受制于远程自动注销。虽然 ruby 有像 perl 的 Net::SSH::Tunnel 这样的 gem,但我没有看到 python 的 pip。 This question和 this one两者都在讨论它,它们似乎表明您只能将其作为子流程启动或使用 paramiko .
关于Python raw_input 故障并返回 -bash : line 1: <INPUT>: command not found,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31297312/
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll
所以我开始关注ruby,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出
为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998
在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"
我正在寻找一种匹配多行Parslet的方法。代码如下所示:rule(:line){(match('$').absent?>>any).repeat>>match('$')}rule(:lines){line.repeat}但是,lines将始终以无限循环结束,这是因为match('$')将无休止地重复以匹配字符串的结尾。是否可以匹配可以为空的多行?irb(main)>lines.parse($stdin.read)Thisisamultilinestring^D应该匹配成功。我错过了什么吗?我还尝试了(match('$').absent?>>any.maybe).repeat(1)>>