Python raw_input 故障和 returns -bash:第 1 行:<INPUT>:找不到命令

Python raw_input malfunctions and returns -bash: line 1: <INPUT>: command not found

我编写了一个脚本来建立 SSH 隧道并通过该隧道连接到数据库。

极简坚果shell(省略明显参数和多余逻辑):

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-等效命令在下面,我已经测试了命令和脚本在"clean client"条件下的工作,即在重启。

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 登录使用密钥,在 ~/.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

我注意到的另一个意想不到的症状是键盘输入到终端window(我是运行这个在bash终端内Xubuntu 14.04LTS) 变得虚假地没有响应,所以我必须关闭终端选项卡并打开一个新选项卡。这会清除键盘输入,但不会清除脚本行为。

我曾尝试寻找解决方案,但通常的搜索引擎对我的情况没有帮助,可能是因为我不完全了解发生了什么。我怀疑键盘输入以某种方式重定向到一个进程,可能是隧道子进程,但我无法解释为什么第一个 raw_input 按预期工作而第二个没有。

我也对我创建隧道的方式感到不舒服,因此欢迎任何关于更强大的隧道创建的建议。具体来说,我希望对隧道的创建有更细粒度的控制,而不是等待任意两秒钟来建立隧道,因为我没有来自该子进程的反馈。

感谢您分享您的时间和专业知识。

您可以随意配置服务器吗? 然后尝试 vpn 连接而不是 ssh 端口转发。这将更容易重新连接而不影响您的应用程序,因此隧道可能更稳定。

对于 raw_input 问题,我不明白为什么会这样,但也许 shell 中的 ssh 命令干扰了您的终端?如果您真的想集成 ssh 隧道,您可能需要查看一些 python 处理 ssh 的模块。

我的回答分为两部分:我将如何进行诊断,以及我将如何进行诊断。

首先,我建议使用失败的提示作为探索的机会。

您可以在此处采用两种方法:

  • 只需输入 hostname(或其他任何内容)即可找出 运行
  • 的位置
  • 输入 bash,或者如果远程端有 X 服务器,请将 -X 添加到您的 ssh 命令,然后键入终端程序(xtermgnome-terminal 等).在你的新 shell 中,你可以四处看看发生了什么。

如果您在客户端确定它是 运行,您可以使用 strace:

来诊断它
strace -f -o blah.log yourscript.py

... 您可以在其中输入易于搜索的密码字符串,然后在 blah.log 中搜索该密码。由于 -f 标志,它将打印试图执行它的进程的 PID;从那里回溯,您可能会发现 PID 是从另一个 PID 的分支开始的。该 PID 是试图执行它的原因,因此您应该能够从那里进行调查。


至于我会怎么做:我对 python 还是很陌生,所以我倾向于使用 perl 或 expect。在 perl 路径下,您可能会看到:

  • Net::SSH::Tunnel;这可能是我考虑使用的第一个。
  • 使用 open 或 open3 然后做一些像 hacky 这样的事情:
    • 等待进程上的标准输出有可用的文本;为此,您必须摆脱 -N,并且您将受到远程自动注销的支配。
    • ssh-check-if-a-tunnel-is-alive
    • 的各种回应之一
  • Net::SSH::Expect (eg this post,虽然我没有看他的实现,所以你必须自己做出选择)。这个或 "real" expect 可能有点矫枉过正,但我​​相信你可以找到一种方法。

虽然 ruby 有一个 gem 像 perl 的 Net::SSH::Tunnel,但我没有看到 python 的点。 This question and this one both discuss it and they seem to indicate you're limited to either starting it as a sub-process or using paramiko.

-bash:第 1 行:s3cReTsTr1n9:未找到命令

即使我刚刚接受 raw_input() / input(),我也遇到了与 -bash command not found 相同的错误。我在 2.7 和 3.7 版本都试过了。

我在同一个 mac machine 上尝试 运行 客户端服务器程序。我有两个文件 server.py 和 client.py。每次在终端中,我首先在后台 运行 server.py 然后 运行 client.py。
1 号航站楼:python server.py &
2号航站楼:pythonclient.py
每次我收到错误“-bash:xxxx:找不到命令”。 xxxx 这里是我提供的任何输入。

最后,在花了 5 个小时之后,我在后台停止了 运行ning server.py。
1 号航站楼:pythonserver.py
2号航站楼:pythonclient.py

中提琴奏效了。 raw_input 并且输入没有再给我这个错误。

我不确定这是否有帮助。但这是我在互联网上找到的唯一 post 与我的问题完全相同的问题。并认为这可能会有所帮助。