Ubuntu-最新的 GitHub 运行程序无法连接到 localhost API

Ubuntu-最新的 GitHub 运行程序无法连接到 localhost API

为了使 GitHub 运行器上运行的程序成功连接到同一 GitHub 运行器Ubuntu-latest上运行的 Twisted Web 服务器,具体需要更改以下内容?localhost

相同的代码可以在 Windows 笔记本电脑上运行,只需进行一些细微的更改,例如where twistd在 Windows 上使用与which twistd在 Ubuntu 上使用相比,如下所示。

一些相关代码:

在本地主机上启动 Twisted Web 服务器的代码位于名为的脚本中,twistdStartup.py其内容如下:

import subprocess
import re
import os

escape_chars = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')

def runShellCommand(commandToRun, numLines=999):
  proc = subprocess.Popen( commandToRun,cwd=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
  while True:
    line = proc.stdout.readline()
    if line:
      if numLines == 1:
        return escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n'))
      else:
        print(escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n')))
    else:
      break

print("About to create venv.")
runShellCommand("python3 -m venv venv")

print("About to activate venv.")
runShellCommand("source venv/bin/activate")

print("About to install flask.")
runShellCommand("pip install Flask")
print("About to install requests.")
runShellCommand("pip install requests")
print("About to install twisted.")
runShellCommand("pip install Twisted")

##Set environ variable for the API
os.environ['PYTHONPATH'] = '.'
print("Done updating PYTHONPATH.  About to start server.")

twistdLocation = runShellCommand("which twistd", 1)
startTwistdCommand = twistdLocation+" web --wsgi myAPI.app  &>/dev/null & "
print("startTwistdCommand is: ", startTwistdCommand)

subprocess.call(startTwistdCommand, shell=True)
print("startTwistdCommand should be running in the background now.")

startTheAPI.py调用上述代码的调用程序中的代码twistdStartup.py是:

myScript = 'twistdStartup.py'
print("About to start Twisted.")
subprocess.Popen(["python", myScript], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print("Just finished starting Twisted.")

GitHub Action 作业中该步骤生成的日志如下:

About to start Twisted.
Just finished starting Twisted.

等待30秒启动后,在同一作业的下一步中在同一Ubuntu最新的GitHub运行器上运行curl命令的结果如下:

$ curl http://localhost:1234/api/endpoint/
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                               Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 1234 after 1 ms: Connection refused

callTheAPI.py运行该命令的程序的内容curl如下所示:

import subprocess
import re
import os

escape_chars = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')

def runShellCommand(commandToRun, numLines=999):
  proc = subprocess.Popen( commandToRun,cwd=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
  while True:
    line = proc.stdout.readline()
    if line:
      if numLines == 1:
        return escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n'))
      else:
        print(escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n')))
    else:
      break

print("About to call API.")    
runShellCommand("curl http://localhost:1234/api/endpoint/")
print("Done calling API.")

概括:

twistdStartup.py脚本正在运行,但尽管执行了所有命令,但仍无法向日志提供任何输出print()。 curl 命令无法连接到正确指定的http://localhost:1234/api/endpoint/

答案1

关于:

curl 命令无法连接到正确声明的 http://localhost:1234/api/endpoint/

这里的主要问题是,您运行的每个命令runShellCommand("somecommand")都是在新的 shell 中执行的,因此所有更改(例如函数、变量、环境变量等)在命令执行后都会消失。

例如,尝试在您的twistdStartup.py

print("Running echo $PATH")
runShellCommand("echo $PATH")

print("Running PATH=/")
runShellCommand("PATH=/")

print("Running echo $PATH")
runShellCommand("echo $PATH")

输出(就我而言):

Running echo $PATH
/home/edgar/.local/bin:/home/edgar/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/go/bin
Running PATH=/
Running echo $PATH
/home/edgar/.local/bin:/home/edgar/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/go/bin

正如你在上面看到的,作业Running PATH=/被忽略当我再次跑步时runShellCommand("echo $PATH")

可能的解决方案(未使用所有命令进行测试)是将所有runShellCommand方法调用包装在单个方法调用中(或将代码转换为 shell 脚本),如下所示:

部分twistdStartup.py:

runShellCommand(
"""
set -e
echo About to create venv.
python3 -m venv venv

echo About to activate venv.
. venv/bin/activate

echo About to install flask.
pip install Flask

echo About to install requests.
pip install requests

echo About to install twisted.
pip install Twisted

export PYTHONPATH='.'
echo Done updating PYTHONPATH.  About to start server.

twistdLocation=$(which twistd)

echo "Running ${twistdLocation} web --wsgi customControllerAPI.app  &>/dev/null &"

( 
$twistdLocation web --wsgi myAPI.py  >/dev/null 2>&1
)&


echo startTwistdCommand should be running in the background now.
""")

在 GitHub Actions 上进行测试时,我注意到这source venv/bin/activate导致了失败,因为source它无效(可能 GitHub 中 Ubuntu 的默认 shell 是dash)。
而不是使用source相反,你必须使用.(这要好得多):. venv/bin/activate
由于上述命令出现错误:which twistd无法正常工作,因为维尼夫没有来源。因此,命令: $twistdLocation web --wsgi customControllerAPI.app &>/dev/null将会失败,并且 Flask API 将永远不会运行(因此你会收到消息Failed to connect to localhost port 1234 after 1 ms: Connection refused:)

关于:

但尽管使用了所有 print() 命令,仍无法向日志提供任何输出

通过查看您的文件api_server.py我看到你正在调用 python 脚本setup.py

apiServer = subprocess.Popen(["python", "setup.py"], stdout=subprocess.DEVNULL, cwd=str(path))

在这里,您没有获得命令的输出python setup.py,因此我建议您删除该行并添加以下行:

    apiServer = subprocess.Popen(["python", "setup.py"], cwd=str(path),stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        line = apiServer.stdout.readline()

        if line:
            print(self.escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n')))
        else:
          break

  1. 您可能想将该行更改twistdLocation=$(which twistd)twistdLocation=$(command -v twistd).看为什么不用“哪个”呢?那该用什么呢?
  2. set -e我还建议您在脚本的第一行添加该行。如果抛出一些错误,该命令用于中止以下命令的执行(因此在您的情况下,如果某些依赖项无法自行安装,则脚本将停止)。
  3. 关于($twistdLocation web --wsgi myAPI.py >/dev/null 2>&1 )&我使用它是为了防止 pythonsubprocess等待读取该命令的输出,因为这个命令导致服务器“无限”卡住)。
  4. 如果您对命令的日志(stdout和)感兴趣:您应该将输出重定向到文件,如下所示:stderr$twistdLocation ...
( 
$twistdLocationn web --wsgi myAPI.py  >/tmp/twistd.logs 2>&1
)&

此外,您还必须编辑 github 操作以包含cat的内容的命令/tmp/twistd.logs,如下所示:

steps:
  - uses: actions/checkout@v3
  - shell: bash
    name: Start the localhost Server
    run: |
      echo "Current working directory is: "
      echo "$PWD"
      python code/commandStartServer.py
      echo "Checking twistd logs"
      cat /tmp/twistd.logs

所以在这些文件中你必须有以下代码:

api_server.py

import os
import re
 
class api_server:
  
  def __init__(self):  
    pass

  escape_chars = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
 
  def startServer(self):
    path = os.getcwd()+"/api/"
    print(path)
    print("About to start .")
    import subprocess
    #The version of command on next line runs the server in the background.  Comment it out and replace with the one below it if you want to see output.
    apiServer = subprocess.Popen(["python", "setup.py"], cwd=str(path),stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        line = apiServer.stdout.readline()

        if line:
            print(self.escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n')))
        else:
          break

    #The second version of the command below will print output to the console, but will also halt your program because it runs the server in the foreground.
    #apiServer = subprocess.Popen(["python", "setup.py"], cwd=str(path))
    print("Just finished starting .")

  def destroyServer(self):
    ... # your current code

安装程序.py

import subprocess
import re
import os

escape_chars = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')

def runShellCommand(commandToRun, numLines=999):
  proc = subprocess.Popen( commandToRun,cwd=None,  shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  while True:
    line = proc.stdout.readline()
    if line:
      if numLines == 1:
        return escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n'))
      else:
        print(escape_chars.sub('', line.decode('utf-8').rstrip('\r|\n')))
    else:
      break

runShellCommand(
"""
set -e
echo About to create venv.
python3 -m venv venv

echo About to activate venv.
. venv/bin/activate

echo About to install flask.
pip install Flask

echo About to install requests.
pip install requests

echo About to install twisted.
pip install Twisted

export PYTHONPATH='.'
echo Done updating PYTHONPATH: $PYTHONPATH.  About to start server.

twistdLocation=$(which twistd)

echo "Running ${twistdLocation} web --wsgi customControllerAPI.app  &>/dev/null &"

( 
$twistdLocation web --wsgi myAPI.py  >/dev/null 2>&1
)&


echo startTwistdCommand should be running in the background now.
""")

本地主机-api.yml

name: localhost-api
on:
  push:
    branches:
      - main
jobs:
  start-and-then-call-localhost-api:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - shell: bash
        name: Start the localhost Server
        run: |
          echo "Current working directory is: "
          echo "$PWD"
          python code/commandStartServer.py
          echo "Checking twistd logs"
          cat /tmp/twistd.logs
      - shell: bash
        name: Call the localhost API
        run: |
          echo "Current working directory is: "
          echo "$PWD"
          python code/commandCallAPI.py
      - shell: bash
        name: Destroy the localhost Server
        run: |
          echo "Current working directory is: "
          echo "$PWD"
          python code/commandDestroyServer.py

相关内容