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