|
OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # | |
3 # Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
4 # for details. All rights reserved. Use of this source code is governed by a | |
5 # BSD-style license that can be found in the LICENSE file. | |
6 # | |
7 | |
8 # A script to kill hanging processs. The tool will return non-zero if any | |
9 # process was actually found. | |
10 # | |
11 | |
12 import optparse | |
13 import os | |
14 import signal | |
15 import shutil | |
16 import string | |
17 import subprocess | |
18 import sys | |
19 import utils | |
20 | |
21 os_name = None | |
22 | |
23 POSIX_LIST = 'ps -e -o comm,pid' | |
kustermann
2013/08/27 08:42:22
Please add a comment, which gives an example outpu
ricow1
2013/08/27 11:45:25
This has been moved into the platform specific fun
| |
24 POSIX_INFO = 'ps -p %s -o args' | |
25 | |
26 LIST_COMMAND = { | |
27 'win32': 'wmic process get Caption,Processid', | |
28 'macos': POSIX_LIST, | |
29 'linux': POSIX_LIST, | |
30 } | |
31 | |
32 INFO_COMMAND = { | |
33 'win32': 'wmic process where Processid=%s get CommandLine', | |
34 'macos': POSIX_INFO, | |
35 'linux': POSIX_INFO, | |
36 } | |
37 | |
38 def GetOptions(): | |
39 parser = optparse.OptionParser("usage: %prog [options]") | |
40 parser.add_option("--kill_dart", default=True, | |
41 help="Kill all dart processes") | |
42 parser.add_option("--kill_browsers", default=False, | |
kustermann
2013/08/27 08:42:22
Why the difference in default values?
ricow1
2013/08/27 11:45:25
Because if people use it locally I don't want to k
| |
43 help="Kill all browser processes") | |
44 (options, args) = parser.parse_args() | |
45 return options | |
46 | |
47 def GetPids(process_name): | |
48 # We asume that the list command will return lines in the format: | |
49 # PROCESS_NAME WHITESPACE* PID | |
kustermann
2013/08/27 08:42:22
Don't know if this is working. Often on mac and wi
ricow1
2013/08/27 11:45:25
I changed the order now and just return the last p
| |
50 p = subprocess.Popen(LIST_COMMAND[os_name], | |
51 stdout=subprocess.PIPE, | |
52 stderr=subprocess.PIPE, | |
53 shell=True) | |
54 output, stderr = p.communicate() | |
55 results = [] | |
56 | |
57 lines = output.splitlines() | |
58 # Pop the header | |
59 lines.pop(0) | |
kustermann
2013/08/27 08:42:22
Do we have this header on windows and linux?
ricow1
2013/08/27 11:45:25
Yes we did, but not with the new command
| |
60 for line in lines: | |
61 split = line.split() | |
62 if len(split) == 2 and split[0] == process_name: | |
63 results.append(split[1]) | |
kustermann
2013/08/27 08:42:22
see comment above.
ricow1
2013/08/27 11:45:25
Done.
| |
64 return results | |
65 | |
66 def PrintPidInfo(pid): | |
67 # We asume that the list command will return lines in the format: | |
68 # EXECUTABLE_PATH ARGS | |
69 # There may be blank strings in the output | |
70 p = subprocess.Popen(INFO_COMMAND[os_name] % pid, | |
71 stdout=subprocess.PIPE, | |
72 stderr=subprocess.PIPE, | |
73 shell=True) | |
74 output, stderr = p.communicate() | |
75 lines = output.splitlines() | |
76 | |
77 # Pop the header | |
78 lines.pop(0) | |
79 for line in lines: | |
80 # wmic will output a bunch of empty strings, we ignore these | |
81 if len(line) >= 1: | |
82 print("Hanging process info:") | |
83 print(" PID: %s" % pid) | |
84 print(" Command line: %s" % line) | |
kustermann
2013/08/27 08:42:22
Same comments as above.
ricow1
2013/08/27 11:45:25
Done.
| |
85 | |
86 def KillPosix(pid): | |
87 try: | |
88 os.kill(int(pid), signal.SIGTERM); | |
kustermann
2013/08/27 08:42:22
What if SIGTERM is ignored? We should really make
ricow1
2013/08/27 11:45:25
Done.
ricow1
2013/08/27 11:45:25
Done.
| |
89 except: | |
90 # Ignore this, the process is already dead from killing another process. | |
91 pass | |
92 | |
93 def KillWindows(pid): | |
94 # os.kill is not available until python 2.7 | |
95 cmd = "taskkill /F /PID %s" % pid | |
96 p = subprocess.Popen(cmd, | |
97 stdout=subprocess.PIPE, | |
98 stderr=subprocess.PIPE, | |
99 shell=True) | |
100 | |
101 def GetExecutableName(name): | |
102 if (os_name == "win32"): | |
103 return "%s.exe" % name | |
104 else: | |
105 return name | |
106 | |
107 def Kill(name): | |
108 print("***************** Killing %s *****************" % name) | |
109 pids = GetPids(GetExecutableName(name)) | |
110 for pid in pids: | |
111 PrintPidInfo(pid); | |
112 if (os_name == "win32"): | |
113 KillWindows(pid) | |
114 else: | |
115 KillPosix(pid) | |
116 print("Killed pid: %s" % pid) | |
kustermann
2013/08/27 08:42:22
You don't know if it was successfull or not at thi
| |
117 if (len(pids) == 0): | |
118 print(" Nothing to kill") | |
kustermann
2013/08/27 08:42:22
We could print this out multiple times (for every
ricow1
2013/08/27 11:45:25
That is what I want, the log will explicitly show
| |
119 return len(pids) | |
kustermann
2013/08/27 08:42:22
We should return here how many we actually killed.
ricow1
2013/08/27 11:45:25
well, that is hard to figure out without listing a
| |
120 | |
121 def KillBrowsers(): | |
122 status = Kill('firefox') | |
123 status += Kill('chrome') | |
124 status += Kill('iexplore') | |
kustermann
2013/08/27 08:42:22
"status" is not the correct name. We should call i
ricow1
2013/08/27 11:45:25
Well, it is the return status :-)
| |
125 status += Kill('Safari') | |
kustermann
2013/08/27 08:42:22
firefox is probably uppercase on mac. We should ma
ricow1
2013/08/27 11:45:25
No it is not, but chrome is
| |
126 return status | |
127 | |
128 def KillDart(): | |
129 status = Kill("dart") | |
130 return status | |
131 | |
132 def Main(): | |
133 global os_name | |
134 options = GetOptions() | |
135 os_name = utils.GuessOS() | |
kustermann
2013/08/27 08:42:22
Don't do it here. Just do assign it at the module
ricow1
2013/08/27 11:45:25
Done.
| |
136 status = 0 | |
137 if (options.kill_dart): | |
138 status += KillDart(); | |
139 if (options.kill_browsers): | |
140 status += status + KillBrowsers() | |
141 return status | |
142 | |
143 if __name__ == '__main__': | |
144 sys.exit(Main()) | |
OLD | NEW |