无法从本地python脚本在远程服务器上运行psql命令

Unable to run psql commands on remote server from local python script

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

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

我怀疑我的ssh代码可能有问题,因此我尝试发送简单的命令,如lscdmkdir甚至scp,而不是通过psql命令发送到远程服务器。所有这些工作都很好,所以我认为我的代码没有问题ssh是关于远程服务器的命令。

有谁知道我的代码出了什么问题以及为什么我要回来psql: command not found?我研究并发现了早期的SO问题,但psql安装在远程服务器上,因为我可以在那里手动运行psql命令。

Postgresql -bash:psql:找不到命令

从外部类文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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命令发送到远程服务器:

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

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

1
2
3
4
$ ./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

谢谢


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

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

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

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

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

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