简体   繁体   English

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

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

I'm writing a script that is called locally to run psql queries on a remote server. 我正在编写一个在本地调用的脚本,以在远程服务器上运行psql查询。 I'm writing the script in Python 2.7 using the subprocess module. 我正在使用subprocess模块​​在Python 2.7中编写脚本。 I'm using subprocess.Popen to ssh into the remote server and directly run a psql command. 我正在使用subprocess.Popen SSH到远程服务器并直接运行psql命令。 My local machine is osx and I think the server is CentOS. 我的本地计算机是osx,我认为服务器是CentOS。

When I call my script locally, I get back an error saying psql: command not found . 当我在本地调用脚本时,我得到一个错误,提示psql: command not found If I run the same exact psql command on the remote server, then I get back the correct query result. 如果我在远程服务器上运行完全相同的psql命令,那么我将获得正确的查询结果。

I suspected there might be something wrong with my ssh code, so instead of sending over psql commands to the remote server, I tried sending over simple commands like ls , cd , mkdir , and even scp . 我怀疑ssh代码可能有问题,因此,我尝试通过简单的命令(例如lscdmkdir甚至scp发送而不是通过psql命令发送到远程服务器。 All of those worked fine, so I don't think there's a problem with my code that ssh's over the commands to the remote server. 所有这些都工作正常,所以我认为我的代码中没有问题,ssh将命令传递给了远程服务器。

Does anybody understand what is going wrong with my code and why I'm getting back psql: command not found ? 有谁知道我的代码出了什么问题以及为什么我找回psql: command not found I researched and found this earlier SO question, but psql is installed on the remote server as evidenced by the fact that I can run psql commands manually on there. 我研究并发现了这个较早的SO问题,但是psql已安装在远程服务器上,这一事实证明了我可以在那里手动运行psql命令。
Postgresql -bash: psql: command not found PostgreSQL -bash:psql:找不到命令


From an external class file: 从外部类文件:

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,



Excerpt from a local script that imports above class and sends out the psql command to remote server: 摘录自上面的类并向远程服务器发送psql命令的本地脚本的摘录:

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



Running my script locally. 在本地运行我的脚本。 Note that the script prints out the psql command for debugging. 请注意,该脚本会打印出psql命令进行调试。 If I copy and paste that same psql command and run it on the remote server, I get back the correct query result. 如果我复制并粘贴相同的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

Thanks 谢谢

When you run ssh for an interactive session on a remote system, ssh requests a PTY (pseudo TTY) for the remote system. 当您在远程系统上为交互式会话运行ssh时,ssh会请求远程系统的PTY(伪TTY)。 When you run ssh to run a command on a remote system, ssh doesn't allocate a PTY by default. 当您运行ssh在远程系统上运行命令时,默认情况下ssh不会分配PTY。

Having a TTY/PTY changes the way your shell initializes itself. 拥有TTY / PTY会更改您的Shell初始化自身的方式。 Your actual problem is you need to do any or all of the following to run psql on the remote system: 您的实际问题是您需要执行以下任何一项或全部操作才能在远程系统上运行psql:

  • Add one or more directories to your command path. 将一个或多个目录添加到您的命令路径。
  • Add one or more environment variables to your environment. 将一个或多个环境变量添加到您的环境中。
  • define one or more aliases. 定义一个或多个别名。

You're doing these things in a shell startup file (.bash_profile, for example) and it's only happening for interactive sessions. 您正在外壳启动文件(例如,.bash_profile)中执行这些操作,并且仅在交互式会话中发生。 When you use ssh to run psql remotely, your shell is skipping the initialization which permits psql to run. 当您使用ssh远程运行psql时,您的外壳会跳过允许psql运行的初始化。

There are two simple approaches to fixing this: 有两种简单的解决方法:

  1. Run ssh with the "-t" or "-tt" option, which causes ssh to allocate a TTY on the remote system for psql. 使用“ -t”或“ -tt”选项运行ssh,这将导致ssh在远程系统上为psql分配TTY。
  2. Change your shell startup files on the remote system to perform the necessary initialization on non-interactive sessions. 更改远程系统上的Shell启动文件,以在非交互式会话上执行必要的初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM