最終的な作業コードについては、この投稿の下部をご覧ください。
これは、ローカルソケットを介してコマンドを送信する別のスクリプトを呼び出すことにより、CGI スクリプトへのユーザー入力を取得できる、動作する Python/CGI スクリプトです。
元の投稿:
私の知る限り、すでにヘッダーを送信している Python/CGI スクリプトにユーザー入力を直接送信する方法はありません。同様に、特定の状況下でユーザーに警告し、確認を待ちます。これに対する公開された解決策を見つけることもできませんでした。
私が間違っている場合は、私を修正してください。
現在、サーバーへの接続、ファームウェアのアップロード、再起動、再接続、いくつかの構成ファイルの変更などを行うことができる Python スクリプトがあります。
場合によっては、スクリプトを再起動して最初から実行しなくても、多くのユーザーがスクリプトに入力を送信できると便利です。2G ネットワークでの再接続に時間がかかりすぎます。
ユーザー入力を別のスクリプトに送信し、最初の/メインスクリプトが監視しているファイルに投稿して、入力を受信することが可能でなければならないと考えています。stop/kill 入力コマンドを使用してスクリプトの実行を停止できれば、それもいいでしょう。stop/kill コマンドに関しては、メイン スクリプトに 2 つのスレッドが必要です。そうでない場合、大きなファイルのアップロードなどのプロセスが実行されている場合、アップロードが完了する前に、スクリプトを停止する必要があることがわかります。
同時に、複数のユーザーが同時にスクリプトを使用できるようにする必要があると思います。したがって、メイン スクリプトが起動するたびに一意の ID を生成する必要があります。
これが私がそれを作ることができると思う方法です:
メインスクリプトが呼び出される
Global variable with a unique session ID is generated and sent to client.
Thread 1
pexpect spawns a "tail -F /var/www/cgi/tmp_cmd.log"
Thread 2
Thread status "Busy"
Connects to network element
Does its usual stuff until it reaches a point where the user needs to interact.
Prints the message to user and waits for Thread 1 with a timeout of x seconds.
Thread status "Ready"
2 番目のスクリプトは、2 つのヘッダー (セッション ID と入力) を使用して AJAX を介してユーザーによって呼び出されます。
2 番目のスクリプト
Session ID and user input is saved to "/var/www/cgi/tmp_cmd.log"
Execution of the input script ends
メインスクリプト
Thread 1
User input recieved.
Wait for Thread 2 status to become "Ready" or ignore status if command is equals to "kill" ect.
Send user input (single line) and start Thread 1 from the beginning
Thread 2
Thread 2 status "Busy"
Input recieved and process stops/continues.
Thread 2 status "Ready"
接続、ファイルのアップロード、およびコマンドの実行のためのスクリプトを作成しました。ただし、ユーザー入力を受け取ることはできません。
私は本当に良い助けを借りたり、誰かがこれにアプローチする方法を教えてくれたりすることができます.
もちろん、スクリプトが完成したら、ここまたはペーストビンに投稿し、他の人が使用できるようにリンクします。:)
最終コード
以下の投稿の助けを借りて、ようやく動作するコードを手に入れました。スレッドを使用することもできますが、プロセスを停止/キャンセルする方が簡単に理解できるようです。
クライアント- cgi_send.py
#!/usr/bin/python
import sys, cgi, cgitb, socket
cgitb.enable()
TASKS_DIR = "/var/www/cgi-bin/tmp"
def main():
global TASKS_DIR
url = cgi.FieldStorage()
cmd = str(url.getvalue('cmd'))
sessionId = str(url.getvalue('session'))
socketLocation = TASKS_DIR + '/%s.socket' % sessionId
print '<a href="?session='+sessionId+'&cmd=QUIT">End script</a> <a href="?session='+sessionId+'&cmd=CANCEL">Cancel task</a>'
print '<form action=""><input type="hidden" name="session" id="session" value="'+sessionId+'" /><input type="text" name="cmd" id="cmd" value="" /><input type="submit" value="Fun!" />'
try:
sock = socket.socket(socket.AF_UNIX)
sock.setblocking(0)
sock.connect(socketLocation)
sock.send(cmd)
sock.close()
print '<br />Command sent: '+ cmd;
except IOError:
print '<br /><b>Operation failed.</b><br /> Could not write to socket: '+ socketLocation
pass
sock.close()
sys.exit();
if __name__ == '__main__':
sys.stdout.write("Content-type:text/html;charset=utf-8\r\n\r\n")
sys.stdout.write('<!DOCTYPE html>\n<html><head><title>Test</title></head><body>')
main()
print '</body></html>'
sys.exit()
サーバ
#!/usr/bin/python
import sys, os, socket, uuid, time, multiprocessing
# Options
TASKS_DIR = "/var/www/cgi-bin/tmp/"
def main():
sessionId = str(uuid.uuid4())
print 'Session ID: '+ sessionId
sys.stdout.write ('<br /><a href="cgi_send.py?cmd=test&session=' + sessionId +'" target="cmd_window">Send test command</a>')
sys.stdout.flush()
address = os.path.join(TASKS_DIR, '%s.socket' % sessionId)
sock = socket.socket(socket.AF_UNIX)
sock.setblocking(0)
sock.settimeout(.1)
sock.bind(address)
sock.listen(1)
taskList = [foo_task, foo_task, foo_task]
try:
for task in taskList:
print "<br />Starting new task"
runningTask = multiprocessing.Process(target=task)
runningTask.daemon = True # Needed to make KeyboardInterrupt possible when testing in shell
runningTask.start()
while runningTask.is_alive():
conn = None
try:
conn, addr = sock.accept()
data = conn.recv(100).strip()
except socket.timeout:
# nothing ready from a client
continue
except socket.error, e:
print "<br />Connection Error from client"
else:
print "<br />"+ data
sys.stdout.flush()
conn.close()
if data == "CANCEL":
# temp way to cancel our task
print "<br />Cancelling current task."
runningTask.terminate()
elif data == "QUIT":
print "<br />Quitting entire process."
runningTask.terminate()
taskList[:] = []
finally:
if conn:
conn.close()
except (KeyboardInterrupt, SystemExit):
print '\nReceived keyboard interrupt, quitting threads.'
finally:
sock.close()
os.remove(address)
def foo_task():
i = 1
while 10 >= i:
print "<br />Wating for work... "+ str(i)
sys.stdout.flush()
i = i + 1
time.sleep(1)
if __name__ == '__main__':
sys.stdout.write("Content-type:text/html;charset=utf-8\r\n\r\n")
sys.stdout.write('<!DOCTYPE html>\n<html><head><title>Test</title></head><body>')
main()
print '</body></html>'
sys.exit()