supervisord 上的 Flask 应用 运行 如何打开 SSH 隧道?
How can a Flask app running on supervisord open an SSH tunnel?
注意:我在问题中包含了 Flask,但我怀疑它与 Flask 有任何关系,并且与 supervisord
和 sshtunnel
有关.
基本上,我正在尝试打开 SSH 隧道以连接到数据库并以编程方式执行一些命令。这总是发生在使用 threading
库打开的工人 Thread
上。这可以通过直接调用 Gunicorn 或直接 运行ning 脚本来正常工作。这是函数:
def _get_ssh_server(client):
"""Open an SSH tunnel forwarder and return it."""
return sshtunnel.SSHTunnelForwarder(
(os.environ['SSH_HOSTNAME'], int(os.environ['SSH_PORT'])),
ssh_username=os.environ['SSH_USERNAME'],
ssh_pkey=os.environ['SSH_PKEY'],
remote_bind_address=(
os.environ['REMOTE_BIND_ADDRESS'], 3306),
local_bind_address=("localhost", int(
os.environ['LOCAL_BIND_PORT']))
)
显然那些环境变量存在并且是正确的。当我 运行 在本地直接调用 Gunicorn(甚至在远程服务器上)时,一切正常。
当我 运行 sudo service supervisord restart
并观察日志时,我看到:
ValueError: No password or public key available!
这是 supervisord
应用的命令部分 .ini
。
command=/usr/local/bin/pipenv run gunicorn -w 3 manage:app
研究告诉我,这与 supervisord
与 ssh-agent
的工作方式有关。在 root
和我正在使用的用户上,私钥都存在于 id_rsa
中的 ~/.ssh
中,具有正确的权限。 运行 Gunicorn 直接在两个作品上,将问题隔离到 supervisord
。
我可能可以使用 screen
或类似的方法让它工作,但这不是首选解决方案。任何帮助将不胜感激。
谢谢!
编辑: 我能够通过以 root 身份删除 /home/<user>/.ssh/id_rsa
文件、终止 SSH 代理并重新启动它来使其失败。我通过 运行ning ssh-add
让它再次工作。 运行 supervisord
还是不行。
如果 supervisor
使用的 SSH 代理与 root
使用的相同,为什么它不起作用?
所以,我设法自己修复了它。我不是 100% 确定为什么它以前不起作用,但我有一个替代解决方案仍然使用相同的工具。
sshtunnel
的文档指出您可以使用文件路径或 paramiko
RSAKey
代替 ssh_pkey
。我一直在使用 str
文件路径,所以我尝试了另一种方式。
我做的第一件事是将私钥的格式从 OpenSSH 更改为 RSA:
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa
接下来,我将加载 SSH 密钥的代码块更改为:
import paramiko
# ...
def _get_ssh_server(client):
"""Open an SSH tunnel forwarder and return it."""
return sshtunnel.SSHTunnelForwarder(
(os.environ['SSH_HOSTNAME'], int(os.environ['SSH_PORT'])),
ssh_username=os.environ['SSH_USERNAME'],
ssh_pkey=paramiko.RSAKey.from_private_key_file(os.environ['SSH_PKEY']),
remote_bind_address=(os.environ['REMOTE_BIND_ADDRESS'], 3306),
local_bind_address=("localhost", int(os.environ['LOCAL_BIND_PORT'])),
allow_agent=False,
)
现在一切正常。
注意:我在问题中包含了 Flask,但我怀疑它与 Flask 有任何关系,并且与 supervisord
和 sshtunnel
有关.
基本上,我正在尝试打开 SSH 隧道以连接到数据库并以编程方式执行一些命令。这总是发生在使用 threading
库打开的工人 Thread
上。这可以通过直接调用 Gunicorn 或直接 运行ning 脚本来正常工作。这是函数:
def _get_ssh_server(client):
"""Open an SSH tunnel forwarder and return it."""
return sshtunnel.SSHTunnelForwarder(
(os.environ['SSH_HOSTNAME'], int(os.environ['SSH_PORT'])),
ssh_username=os.environ['SSH_USERNAME'],
ssh_pkey=os.environ['SSH_PKEY'],
remote_bind_address=(
os.environ['REMOTE_BIND_ADDRESS'], 3306),
local_bind_address=("localhost", int(
os.environ['LOCAL_BIND_PORT']))
)
显然那些环境变量存在并且是正确的。当我 运行 在本地直接调用 Gunicorn(甚至在远程服务器上)时,一切正常。
当我 运行 sudo service supervisord restart
并观察日志时,我看到:
ValueError: No password or public key available!
这是 supervisord
应用的命令部分 .ini
。
command=/usr/local/bin/pipenv run gunicorn -w 3 manage:app
研究告诉我,这与 supervisord
与 ssh-agent
的工作方式有关。在 root
和我正在使用的用户上,私钥都存在于 id_rsa
中的 ~/.ssh
中,具有正确的权限。 运行 Gunicorn 直接在两个作品上,将问题隔离到 supervisord
。
我可能可以使用 screen
或类似的方法让它工作,但这不是首选解决方案。任何帮助将不胜感激。
谢谢!
编辑: 我能够通过以 root 身份删除 /home/<user>/.ssh/id_rsa
文件、终止 SSH 代理并重新启动它来使其失败。我通过 运行ning ssh-add
让它再次工作。 运行 supervisord
还是不行。
如果 supervisor
使用的 SSH 代理与 root
使用的相同,为什么它不起作用?
所以,我设法自己修复了它。我不是 100% 确定为什么它以前不起作用,但我有一个替代解决方案仍然使用相同的工具。
sshtunnel
的文档指出您可以使用文件路径或 paramiko
RSAKey
代替 ssh_pkey
。我一直在使用 str
文件路径,所以我尝试了另一种方式。
我做的第一件事是将私钥的格式从 OpenSSH 更改为 RSA:
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa
接下来,我将加载 SSH 密钥的代码块更改为:
import paramiko
# ...
def _get_ssh_server(client):
"""Open an SSH tunnel forwarder and return it."""
return sshtunnel.SSHTunnelForwarder(
(os.environ['SSH_HOSTNAME'], int(os.environ['SSH_PORT'])),
ssh_username=os.environ['SSH_USERNAME'],
ssh_pkey=paramiko.RSAKey.from_private_key_file(os.environ['SSH_PKEY']),
remote_bind_address=(os.environ['REMOTE_BIND_ADDRESS'], 3306),
local_bind_address=("localhost", int(os.environ['LOCAL_BIND_PORT'])),
allow_agent=False,
)
现在一切正常。