运行kubectl portforward时子进程意外死亡

2024-09-23 06:23:19 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我正在编写一个CLI与Elasticsearch对话(因为我厌倦了长curl命令)。除了我想和运行在Kubernetes内部的集群聊天外,其他一切都非常好,因为它没有在互联网上公开。因此,我必须先手动运行一个kubectl port-forward,我觉得这很烦人

为了“修复”这个问题,我开始实现某种“pre命令”,以便在CLI中的实际命令之前运行。在我的CLI配置文件中,我定义了如下内容:

my_cluster:
  servers: https://localhost:9200
  pre_commands:
  - command: "kubectl use-context ..."
    wait_for_exit: True
  - command: "kubectl port-forward svc/es 9200"
    wait_for_exit: False
    wait_for_output: "Forwarding from 127.0.0.1:9200"

此配置意味着在与名为“my_cluster”的集群通信时,我希望事先运行两个shell命令:

  • kubectl use-context ...并等待它退出(因为它不是一个长时间运行的命令)
  • kubectl port-forward svc/es 9200并等待特定的输出:我不想等待此命令退出,因为它不会退出。但是,当端口转发建立时,它会在标准输出上打印一些内容,因此我正在等待

我正在使用cliff构建命令行,它在名为prepare_to_run_commandclean_up(定义为here)的方法中公开了一些钩子:

def _run_shell_subcommand(self, command):
    command = command.split(" ")
    process = subprocess.Popen(command, stdout=subprocess.PIPE)

    return process

def prepare_to_run_command(self, cmd):
    for i in range(len(self.context.pre_commands)):
        command_block = self.context.pre_commands[i]
        process = self._run_shell_subcommand(command_block.get("command"))

        if command_block.get("wait_for_exit"):
            process.communicate()

        elif command_block.get("wait_for_output"):
            string_to_look_for = command_block.get("wait_for_output")
            pattern = re.compile(string_to_look_for)

            while True:
                line = process.stdout.readline()
                if not line:
                    break

                line = line.decode("utf-8").strip()

                match = re.search(pattern, line)

                if match is None:
                    pass
                else:
                    break

        self.context.pre_commands[i]["process"] = process

def clean_up(self, cmd, result, err):
    for pre_command in self.context.pre_commands:
        pre_command.get("process").terminate()

它似乎成功地等待了预期的输出,然后继续执行我想要针对Elasticsearch集群运行的实际操作。但问题是:我通常会出现如下错误:

Traceback (most recent call last):
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 376, in _make_request
    self._validate_conn(conn)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
    conn.connect()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connection.py", line 394, in connect
    ssl_context=context,
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 817, in __init__
    self.do_handshake()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [Errno 54] Connection reset by peer

我的最佳猜测是,端口转发在调用Elasticsearch期间被中断(而它不应该被中断),从而意外终止连接

如果我在另一个shell中手动运行port forward并发出CLI命令(没有任何pre_命令),那么一切都会正常工作

如果这不是运行shell命令的好方法,我也愿意接受建议


Tags: inpy命令selfforlibcontextline