-
Notifications
You must be signed in to change notification settings - Fork 2
/
syn
executable file
·195 lines (176 loc) · 6.71 KB
/
syn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/usr/bin/python3
import sys
import subprocess
import signal
import os
import glob
import time
from synth import zeromq_tx
# from synth import zeromq_rx
COMMAND = "python3 synth"
LOG_DIR = "../synth_logs/"
HISTORY_FILE = LOG_DIR + "jobs_run.txt"
def delete_file(filepath):
try:
os.remove(filepath)
except:
pass
def get_processes():
processes = []
x = subprocess.run(["ps","x"], capture_output=True, text=True)
y = str(x.stdout).split("\n")
for line in y:
if line.find(COMMAND) >= 0:
# print(">"+line+"<")
pid = int(line[0:5])
command = line[27:].strip()
processes.append( (pid, command) )
return processes
def list_processes():
processes = get_processes()
print(" PID JOB OUTPUT")
processes = sorted(processes, key=lambda t: t[1]) # Sort by process name
for job in processes:
print(" %5d" % job[0], "%-45s" % job[1], end="", flush=True)
s = LOG_DIR + account_from_pid(job[0]) + ".out"
out = subprocess.run(["tail", "-n", "1", s ], capture_output=True).stdout.decode("utf-8")
out = out.strip()
print(str(out[0:175]))
def list_processes_interactive():
while True:
print("\033[2J") # ANSI clear screen
print("\033[;H") # Home cursor
list_processes()
time.sleep(5)
def command_from_pid(pid):
for p in get_processes():
if p[0] == pid:
return p[1]
return None
def pid_from_account(account):
for p in get_processes():
act = p[1].split(" ")[2] # python3 synth Account Scenario
if account==act:
return p[0]
return None
def account_from_pid(pid):
command = command_from_pid(pid)
if command is None:
return None
account = command.split(" ")[2]
return account
def watch(pid):
try:
account = account_from_pid(pid)
if account is None:
print("No such PID")
else:
subprocess.run(["tail", "-f", LOG_DIR + account + ".out"])
except KeyboardInterrupt:
pass # Don't print traceback if user just quits
def run(account, scenarios):
pid = pid_from_account(account)
if pid != None:
print("ERROR: A Synth job is already running on account",account,"with PID",pid)
list_processes()
return
delete_file(LOG_DIR + account + ".out")
delete_file(LOG_DIR + account + ".evt")
delete_file(LOG_DIR + account + ".csv")
delete_file(LOG_DIR + account + ".nohup")
filelist=glob.glob(LOG_DIR + account + "0*.json")
for file in filelist:
delete_file(file)
with open(LOG_DIR + account + ".nohup", "wt") as outfile:
x = subprocess.Popen(["nohup", "python3", "synth", account ] + scenarios, stdout=outfile, stderr=outfile)
if x.errors != None:
print(x.errors)
else:
print("Running",account,* scenarios,"as PID",x.pid)
open(HISTORY_FILE,"at").write(time.ctime() + " " + "Started" + " " + account + " " + " ".join(scenarios) + "\n")
time.sleep(1)
list_processes()
# Very important to exit quickly, otherwise a ^C sent to us will also kill our child
exit(0)
def signal_pid(pid, sig, english):
account = account_from_pid(pid)
if account is None:
print("No such PID")
else:
os.kill(pid, sig)
print(english,account)
open(HISTORY_FILE,"at").write(time.ctime() + " " + english + " " + account + "\n")
time.sleep(2)
list_processes()
# We don't use RX, for now
g_connected_account = None
def command_response(packet):
# Is it for us?
if g_connected_account is None:
return
if not "headers" in packet:
return
if not "Instancename" in packet["headers"]:
return
if packet["headers"]["Instancename"] != g_connected_account:
return
if not "action" in packet:
return
if packet["action"] != "response":
return
print(packet["response"] + "\n> ",end="",flush=True)
def connect(pid):
global g_connected_account
zeromq_tx.init(emit_logging=False) # Don't clutter-up screen with logging
# zeromq_rx.init(command_response, emit_logging=False)
g_connected_account = account_from_pid(pid)
if g_connected_account is None:
print("No such PID")
return
print("Connected to",g_connected_account, "- type 'exit'<return> to disconnect")
zeromq_tx.socket_send( { "action" : "none" } ) # First packet seems to be ignored
while True:
inp = input("> ")
if inp in ["exit","quit","disconnect","stop","leave"]:
break
inp = inp.strip()
if len(inp) > 0:
inp = inp.split(" ")
packet = { "headers" : { "Instancename" : g_connected_account }, "action" : "command", "argv" : inp }
zeromq_tx.socket_send(packet)
print("Disconnected")
if __name__ == "__main__":
if len(sys.argv) < 2:
list_processes()
print("\nFor available commands type '"+sys.argv[0]+" help'")
else:
if sys.argv[1] == "list":
list_processes_interactive()
elif sys.argv[1] == "watch":
watch(int(sys.argv[2]))
elif sys.argv[1] == "run":
run(sys.argv[2], sys.argv[3:])
elif sys.argv[1] == "kill":
signal_pid(int(sys.argv[2]), signal.SIGINT, "Killed") # Send SIGINT not SIGKILL so any worker children die too
elif sys.argv[1] == "pause":
signal_pid(int(sys.argv[2]), signal.SIGUSR1, "Paused")
elif sys.argv[1] == "unpause":
signal_pid(int(sys.argv[2]), signal.SIGUSR2, "Unpaused")
elif sys.argv[1] == "connect":
connect(int(sys.argv[2]))
elif sys.argv[1] == "history":
print(open(HISTORY_FILE,"rt").read())
elif sys.argv[1] == "help":
print("Commands:")
print(" list List all synth jobs, with their PID")
print(" run <account> <scenario> Run a synth job. <account> is one of ../synth_accounts and <scenario> is one or more of ./scenarios e.g. 'run OnFStest 10secs'")
print(" watch <pid> Monitor the output from a synth job")
print(" kill <pid> Kill a synth job")
print(" pause <pid> Pause a synth job")
print(" unpause <pid> Unpause a synth job")
print(" connect <pid> Connect to a synth job and send commands")
print(" history List all recent activities")
else:
print("Unrecognised command")
list_processes()
print("\nFor available commands type '"+sys.argv[0]+" help'")