【问题标题】:Unable to run psql commands on remote server from local python script无法从本地 python 脚本在远程服务器上运行 psql 命令
【发布时间】:2017-01-21 11:58:07
【问题描述】:

我正在编写一个在本地调用以在远程服务器上运行 psql 查询的脚本。我正在使用 subprocess 模块在 Python 2.7 中编写脚本。我正在使用 subprocess.Popen ssh 进入远程服务器并直接运行 psql 命令。我的本地机器是osx,我认为服务器是CentOS。

当我在本地调用我的脚本时,我收到一条错误消息 psql: command not found。如果我在远程服务器上运行相同的 psql 命令,那么我会得到正确的查询结果。

我怀疑我的 ssh 代码可能有问题,所以我没有将 psql 命令发送到远程服务器,而是尝试发送简单的命令,例如 lscdmkdir,甚至是 @987654326 @。所有这些都运行良好,所以我不认为我的代码存在问题,即 ssh 对远程服务器的命令。

有人了解我的代码出了什么问题以及为什么我要返回psql: command not found 我研究并发现了这个较早的 SO 问题,但 psql 已安装在远程服务器上因为我可以在那里手动运行 psql 命令。
Postgresql -bash: psql: command not found


从外部类文件:

def db_cmd(self, query):
    # check that query ends in semicolon
    if query[-1] != ';':
        query = query + ';'

    formatted_query = 'psql ' + self.db_string + \
        ' -c "begin; ' + query + ' ' + self.db_mode + ';"'
    print formatted_query

    ssh = subprocess.Popen(['ssh', self.host, formatted_query],
                           shell=False,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    result = ssh.stdout.readlines()
    if not result:
        error = ssh.stderr.readlines()
        print >>sys.stderr
        for e in error:
            print 'ERROR: %s' % e,
    else:
        for r in result:
            print r,



本地脚本的摘录,该脚本导入上述类并将 psql 命令发送到远程服务器:

s = Jump(env, db_mode)
s.db_cmd('select * from student.students limit 5;')



在本地运行我的脚本。 请注意,该脚本会打印出 psql 命令以进行调试。如果我复制并粘贴相同的 psql 命令并在远程服务器上运行它,我会得到正确的查询结果。

$ ./script.py 1 PROD  ROLLBACK
psql -h <server_host> -d <db_name> -U <db_user> -p <port> -c "begin; select * from student.students limit 5; ROLLBACK;"

ERROR: bash: psql: command not found

谢谢

【问题讨论】:

  • 在远程服务器上,psql程序安装在哪个目录下?当您登录远程系统时,该目录如何添加到您的命令路径中?
  • 我取出了一些文件路径,但我可以找到位置。该目录根本不在我的命令路径中。有趣......听起来你建议我调用 psql 明确列出完整的文件路径。我会试一试。我没有想到这是必要的。 $ whereis psql psql: $ which psql /&lt;...&gt;/bin/psql
  • 嗯...我添加了完整路径,ssh 结束的命令是/&lt;...&gt;/bin/psql -h &lt;server_host&gt; -d &lt;db_name&gt; -U &lt;db_user&gt; -p &lt;port&gt; -c "begin; select * from student.students limit 5; ROLLBACK;"。我得到了这个错误:ERROR: /&lt;...&gt;/bin/psql: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory 这是进步!我会去这个兔子洞,看看我能找到什么。谢谢。

标签: python python-2.7 ssh subprocess psql


【解决方案1】:

当您在远程系统上为交互式会话运行 ssh 时,ssh 会为远程系统请求 PTY(伪 TTY)。在远程系统上运行 ssh 运行命令时,ssh 默认不分配 PTY。

拥有一个 TTY/PTY 会改变你的 shell 初始化自己的方式。您的实际问题是您需要执行以下任何或所有操作才能在远程系统上运行 psql:

  • 将一个或多个目录添加到您的命令路径。
  • 向您的环境添加一个或多个环境变量。
  • 定义一个或多个别名。

您在 shell 启动文件(例如 .bash_profile)中执行这些操作,并且只发生在交互式会话中。当您使用 ssh 远程运行 psql 时,您的 shell 会跳过允许 psql 运行的初始化。

有两种简单的方法可以解决这个问题:

  1. 使用“-t”或“-tt”选项运行 ssh,这会导致 ssh 在远程系统上为 psql 分配一个 TTY。
  2. 更改远程系统上的 shell 启动文件,以对非交互式会话执行必要的初始化。

【讨论】:

  • 谢谢!我会看到如何通过 subprocess.Popen 传递标志,但文档不太清楚。或者也许文档很清楚,我不够专心......我可能需要使用另一个模块。一旦我通过标志并确认它有效,我会尽快更新。到时候我会接受你的回答。谢谢。
  • 我不是 python 编码员,但...Popen(['ssh', '-tt', self.host, formatted_query]... 应该这样做。
  • 哈!我显然也不是 Python 编码员。看起来你的建议确实通过了标志,但我仍然收到同样的错误。我会看看我能对 shell 启动文件做些什么。对服务器进行更改涉及很多繁文缛节。
  • 感谢@Kenster,原来“将一个或多个目录添加到您的命令路径”是我的解决方案。我正在 ssh'ing psql 的完整路径,但结果发现有多个 psql 路径,我选择了错误的路径。
猜你喜欢
  • 2013-12-28
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多