Ubuntu-latest
GitHub Runnerで実行されているプログラムを同じGitHub Runnerで実行されているTwisted Webサーバーに正常に接続するには、次の点で正確に何を変更する必要がありますか?localhost
以下のように、Ubuntuで使用されているものと比較して、where twistd
Windowsで使用されているものと少し変更すると、同じコードをWindowsノートブックで実行できます。which twistd
いくつかの関連コード:
localhostで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 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")
新しいシェルで実行されるため、コマンドの実行後にすべての変更(関数、変数、環境変数など)が消えることです。
たとえば、次のことを試してみてください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
次のように、すべてのメソッド呼び出しを単一のメソッド呼び出しにラップするか、コードをシェルスクリプトに変換することです。
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.
""")
source venv/bin/activate
GitHub Actionsでテスト中にこれが無効であるため、エラーが発生することがわかりましたsource
(おそらくGitHubのUbuntuデフォルトシェルは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)
。「which」を使わないのはなぜですか?それでは何を使うべきですか?set -e
また、この行をスクリプトの最初の行に追加することをお勧めします。このコマンドは、いくつかのエラーが発生した場合に次のコマンドの実行を中断するために使用されます(したがって、一部の依存関係が独自にインストールされていない場合はスクリプトが停止します)。- 私は
($twistdLocation web --wsgi myAPI.py >/dev/null 2>&1 )&
Pythonがこのコマンドの出力を読むのを待つのを防ぐためにそれを使いますsubprocess
。これにより、サーバーが「無限に」停止します。 stdout
コマンドのログ(および)に興味がある場合は、出力を次のファイルにリダイレクトする必要があります。stderr
$twistdLocation ...
(
$twistdLocationn web --wsgi myAPI.py >/tmp/twistd.logs 2>&1
)&
また、次のようにcat
コマンドの内容を含めるようにgithubジョブを編集する必要があります。/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
installer.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.
""")
localhost-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