1#!/usr/bin/env python3 2# coding=utf-8 3 4# 5# Copyright (c) 2022 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import copy 20import os 21import socket 22import sys 23import time 24import platform 25import argparse 26import subprocess 27import signal 28import uuid 29import json 30import stat 31from datetime import timezone 32from datetime import timedelta 33from datetime import datetime 34from tempfile import NamedTemporaryFile 35 36from _core.executor.listener import SuiteResult 37from _core.driver.parser_lite import ShellHandler 38from _core.exception import ParamError 39from _core.exception import ExecuteTerminate 40from _core.logger import platform_logger 41from _core.report.suite_reporter import SuiteReporter 42from _core.plugin import get_plugin 43from _core.plugin import Plugin 44from _core.constants import ModeType 45from _core.constants import ConfigConst 46 47LOG = platform_logger("Utils") 48 49 50def get_filename_extension(file_path): 51 _, fullname = os.path.split(file_path) 52 filename, ext = os.path.splitext(fullname) 53 return filename, ext 54 55 56def unique_id(type_name, value): 57 return "{}_{}_{:0>8}".format(type_name, value, 58 str(uuid.uuid1()).split("-")[0]) 59 60 61def start_standing_subprocess(cmd, pipe=subprocess.PIPE, return_result=False): 62 """Starts a non-blocking subprocess that is going to continue running after 63 this function returns. 64 65 A subprocess group is actually started by setting sid, so we can kill all 66 the processes spun out from the subprocess when stopping it. This is 67 necessary in case users pass in pipe commands. 68 69 Args: 70 cmd: Command to start the subprocess with. 71 pipe: pipe to get execution result 72 return_result: return execution result or not 73 74 Returns: 75 The subprocess that got started. 76 """ 77 sys_type = platform.system() 78 process = subprocess.Popen(cmd, stdout=pipe, shell=False, 79 preexec_fn=None if sys_type == "Windows" 80 else os.setsid) 81 if not return_result: 82 return process 83 else: 84 rev = process.stdout.read() 85 return rev.decode("utf-8").strip() 86 87 88def stop_standing_subprocess(process): 89 """Stops a subprocess started by start_standing_subprocess. 90 91 Catches and ignores the PermissionError which only happens on Macs. 92 93 Args: 94 process: Subprocess to terminate. 95 """ 96 try: 97 sys_type = platform.system() 98 signal_value = signal.SIGINT if sys_type == "Windows" \ 99 else signal.SIGTERM 100 os.kill(process.pid, signal_value) 101 except (PermissionError, AttributeError, FileNotFoundError, # pylint:disable=undefined-variable 102 SystemError) as error: 103 LOG.error("Stop standing subprocess error '%s'" % error) 104 105 106def get_decode(stream): 107 if not isinstance(stream, str) and not isinstance(stream, bytes): 108 ret = str(stream) 109 else: 110 try: 111 ret = stream.decode("utf-8", errors="ignore") 112 except (ValueError, AttributeError, TypeError) as _: 113 ret = str(stream) 114 return ret 115 116 117def is_proc_running(pid, name=None): 118 if hasattr(sys, ConfigConst.env_pool_cache) and getattr(sys, ConfigConst.env_pool_cache, False): 119 return True 120 if platform.system() == "Windows": 121 pid = "{}.exe".format(pid) 122 proc_sub = subprocess.Popen(["C:\\Windows\\System32\\tasklist"], 123 stdout=subprocess.PIPE, 124 shell=False) 125 proc = subprocess.Popen(["C:\\Windows\\System32\\findstr", "/B", "%s" % pid], 126 stdin=proc_sub.stdout, 127 stdout=subprocess.PIPE, shell=False) 128 elif platform.system() == "Linux": 129 # /bin/ps -ef | /bin/grep -v grep | /bin/grep -w pid 130 proc_sub = subprocess.Popen(["/bin/ps", "-ef"], 131 stdout=subprocess.PIPE, 132 shell=False) 133 proc_v_sub = subprocess.Popen(["/bin/grep", "-v", "grep"], 134 stdin=proc_sub.stdout, 135 stdout=subprocess.PIPE, 136 shell=False) 137 proc = subprocess.Popen(["/bin/grep", "-w", "%s" % pid], 138 stdin=proc_v_sub.stdout, 139 stdout=subprocess.PIPE, shell=False) 140 elif platform.system() == "Darwin": 141 proc_sub = subprocess.Popen(["/bin/ps", "-ef"], 142 stdout=subprocess.PIPE, 143 shell=False) 144 proc_v_sub = subprocess.Popen(["/usr/bin/grep", "-v", "grep"], 145 stdin=proc_sub.stdout, 146 stdout=subprocess.PIPE, 147 shell=False) 148 proc = subprocess.Popen(["/usr/bin/grep", "-w", "%s" % pid], 149 stdin=proc_v_sub.stdout, 150 stdout=subprocess.PIPE, shell=False) 151 else: 152 raise Exception("Unknown system environment") 153 154 (out, _) = proc.communicate(timeout=60) 155 out = get_decode(out).strip() 156 LOG.debug("Check %s proc running output: %s", pid, out) 157 if out == "": 158 return False 159 else: 160 return True if name is None else out.find(name) != -1 161 162 163def exec_cmd(cmd, timeout=5 * 60, error_print=True, join_result=False, redirect=False): 164 """ 165 Executes commands in a new shell. Directing stderr to PIPE. 166 167 This is fastboot's own exe_cmd because of its peculiar way of writing 168 non-error info to stderr. 169 170 Args: 171 cmd: A sequence of commands and arguments. 172 timeout: timeout for exe cmd. 173 error_print: print error output or not. 174 join_result: join error and out 175 redirect: redirect output 176 Returns: 177 The output of the command run. 178 """ 179 # PIPE本身可容纳的量比较小,所以程序会卡死,所以一大堆内容输出过来的时候,会导致PIPE不足够处理这些内容,因此需要将输出内容定位到其他地方,例如临时文件等 180 import tempfile 181 out_temp = tempfile.SpooledTemporaryFile(max_size=10 * 1000) 182 fileno = out_temp.fileno() 183 184 sys_type = platform.system() 185 if sys_type == "Linux" or sys_type == "Darwin": 186 if redirect: 187 proc = subprocess.Popen(cmd, stdout=fileno, 188 stderr=fileno, shell=False, 189 preexec_fn=os.setsid) 190 else: 191 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 192 stderr=subprocess.PIPE, shell=False, 193 preexec_fn=os.setsid) 194 else: 195 if redirect: 196 proc = subprocess.Popen(cmd, stdout=fileno, 197 stderr=fileno, shell=False) 198 else: 199 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 200 stderr=subprocess.PIPE, shell=False) 201 try: 202 (out, err) = proc.communicate(timeout=timeout) 203 err = get_decode(err).strip() 204 out = get_decode(out).strip() 205 if err and error_print: 206 LOG.exception(err, exc_info=False) 207 if join_result: 208 return "%s\n %s" % (out, err) if err else out 209 else: 210 return err if err else out 211 212 except (TimeoutError, KeyboardInterrupt, AttributeError, ValueError, # pylint:disable=undefined-variable 213 EOFError, IOError) as _: 214 sys_type = platform.system() 215 if sys_type == "Linux" or sys_type == "Darwin": 216 os.killpg(proc.pid, signal.SIGTERM) 217 else: 218 os.kill(proc.pid, signal.SIGINT) 219 raise 220 221 222def create_dir(path): 223 """Creates a directory if it does not exist already. 224 225 Args: 226 path: The path of the directory to create. 227 """ 228 full_path = os.path.abspath(os.path.expanduser(path)) 229 if not os.path.exists(full_path): 230 os.makedirs(full_path, exist_ok=True) 231 232 233def get_config_value(key, config_dict, is_list=True, default=None): 234 """Get corresponding values for key in config_dict 235 236 Args: 237 key: target key in config_dict 238 config_dict: dictionary that store values 239 is_list: decide return values is list type or not 240 default: if key not in config_dict, default value will be returned 241 242 Returns: 243 corresponding values for key 244 """ 245 if not isinstance(config_dict, dict): 246 return default 247 248 value = config_dict.get(key, None) 249 if isinstance(value, bool): 250 return value 251 252 if value is None: 253 if default is not None: 254 return default 255 return [] if is_list else "" 256 257 if isinstance(value, list): 258 return value if is_list else value[0] 259 return [value] if is_list else value 260 261 262def get_file_absolute_path(input_name, paths=None, alt_dir=None): 263 """Find absolute path for input_name 264 265 Args: 266 input_name: the target file to search 267 paths: path list for searching input_name 268 alt_dir: extra dir that appended to paths 269 270 Returns: 271 absolute path for input_name 272 """ 273 LOG.debug("Input name:{}, paths:{}, alt dir:{}". 274 format(input_name, paths, alt_dir)) 275 input_name = str(input_name) 276 abs_paths = set(paths) if paths else set() 277 _update_paths(abs_paths) 278 279 _inputs = [input_name] 280 if input_name.startswith("resource/"): 281 _inputs.append(input_name.replace("resource/", "", 1)) 282 elif input_name.startswith("testcases/"): 283 _inputs.append(input_name.replace("testcases/", "", 1)) 284 elif input_name.startswith("resource\\"): 285 _inputs.append(input_name.replace("resource\\", "", 1)) 286 elif input_name.startswith("testcases\\"): 287 _inputs.append(input_name.replace("testcases\\", "", 1)) 288 289 for _input in _inputs: 290 for path in abs_paths: 291 if alt_dir: 292 file_path = os.path.join(path, alt_dir, _input) 293 if os.path.exists(file_path): 294 return os.path.abspath(file_path) 295 296 file_path = os.path.join(path, _input) 297 if os.path.exists(file_path): 298 return os.path.abspath(file_path) 299 300 err_msg = "The file {} does not exist".format(input_name) 301 if check_mode(ModeType.decc): 302 LOG.error(err_msg, error_no="00109") 303 err_msg = "Load Error[00109]" 304 305 if alt_dir: 306 LOG.debug("Alt dir is %s" % alt_dir) 307 LOG.debug("Paths is:") 308 for path in abs_paths: 309 LOG.debug(path) 310 raise ParamError(err_msg, error_no="00109") 311 312 313def _update_paths(paths): 314 from xdevice import Variables 315 resource_dir = "resource" 316 testcases_dir = "testcases" 317 318 need_add_path = set() 319 for path in paths: 320 if not os.path.exists(path): 321 continue 322 head, tail = os.path.split(path) 323 if not tail: 324 head, tail = os.path.split(head) 325 if tail in [resource_dir, testcases_dir]: 326 need_add_path.add(head) 327 paths.update(need_add_path) 328 329 inner_dir = os.path.abspath(os.path.join(Variables.exec_dir, 330 testcases_dir)) 331 top_inner_dir = os.path.abspath(os.path.join(Variables.top_dir, 332 testcases_dir)) 333 res_dir = os.path.abspath(os.path.join(Variables.exec_dir, resource_dir)) 334 top_res_dir = os.path.abspath(os.path.join(Variables.top_dir, 335 resource_dir)) 336 paths.update([inner_dir, res_dir, top_inner_dir, top_res_dir, 337 Variables.exec_dir, Variables.top_dir]) 338 339 340def modify_props(device, local_prop_file, target_prop_file, new_props): 341 """To change the props if need 342 Args: 343 device: the device to modify props 344 local_prop_file : the local file to save the old props 345 target_prop_file : the target prop file to change 346 new_props : the new props 347 Returns: 348 True : prop file changed 349 False : prop file no need to change 350 """ 351 is_changed = False 352 device.pull_file(target_prop_file, local_prop_file) 353 old_props = {} 354 changed_prop_key = [] 355 lines = [] 356 flags = os.O_RDONLY 357 modes = stat.S_IWUSR | stat.S_IRUSR 358 with os.fdopen(os.open(local_prop_file, flags, modes), "r") as old_file: 359 lines = old_file.readlines() 360 if lines: 361 lines[-1] = lines[-1] + '\n' 362 for line in lines: 363 line = line.strip() 364 if not line.startswith("#") and line.find("=") > 0: 365 key_value = line.split("=") 366 if len(key_value) == 2: 367 old_props[line.split("=")[0]] = line.split("=")[1] 368 369 for key, value in new_props.items(): 370 if key not in old_props.keys(): 371 lines.append("".join([key, "=", value, '\n'])) 372 is_changed = True 373 elif old_props.get(key) != value: 374 changed_prop_key.append(key) 375 is_changed = True 376 377 if is_changed: 378 local_temp_prop_file = NamedTemporaryFile(mode='w', prefix='build', 379 suffix='.tmp', delete=False) 380 for index, line in enumerate(lines): 381 if not line.startswith("#") and line.find("=") > 0: 382 key = line.split("=")[0] 383 if key in changed_prop_key: 384 lines[index] = "".join([key, "=", new_props[key], '\n']) 385 local_temp_prop_file.writelines(lines) 386 local_temp_prop_file.close() 387 device.push_file(local_temp_prop_file.name, target_prop_file) 388 device.execute_shell_command(" ".join(["chmod 644", target_prop_file])) 389 LOG.info("Changed the system property as required successfully") 390 os.remove(local_temp_prop_file.name) 391 392 return is_changed 393 394 395def get_device_log_file(report_path, serial=None, log_name="device_log", 396 device_name=""): 397 from xdevice import Variables 398 log_path = os.path.join(report_path, Variables.report_vars.log_dir) 399 os.makedirs(log_path, exist_ok=True) 400 401 serial = serial or time.time_ns() 402 if device_name: 403 serial = "%s_%s" % (device_name, serial) 404 device_file_name = "{}_{}.log".format(log_name, str(serial).replace( 405 ":", "_")) 406 device_log_file = os.path.join(log_path, device_file_name) 407 LOG.info("Generate device log file: %s", device_log_file) 408 return device_log_file 409 410 411def check_result_report(report_root_dir, report_file, error_message="", 412 report_name="", module_name=""): 413 """ 414 Check whether report_file exits or not. If report_file is not exist, 415 create empty report with error_message under report_root_dir 416 """ 417 418 if os.path.exists(report_file): 419 return report_file 420 report_dir = os.path.dirname(report_file) 421 if os.path.isabs(report_dir): 422 result_dir = report_dir 423 else: 424 result_dir = os.path.join(report_root_dir, "result", report_dir) 425 os.makedirs(result_dir, exist_ok=True) 426 if check_mode(ModeType.decc): 427 LOG.error("Report not exist, create empty report") 428 else: 429 LOG.error("Report %s not exist, create empty report under %s" % ( 430 report_file, result_dir)) 431 432 suite_name = report_name 433 if not suite_name: 434 suite_name, _ = get_filename_extension(report_file) 435 suite_result = SuiteResult() 436 suite_result.suite_name = suite_name 437 suite_result.stacktrace = error_message 438 if module_name: 439 suite_name = module_name 440 suite_reporter = SuiteReporter([(suite_result, [])], suite_name, 441 result_dir, modulename=module_name) 442 suite_reporter.create_empty_report() 443 return "%s.xml" % os.path.join(result_dir, suite_name) 444 445 446def get_sub_path(test_suite_path): 447 pattern = "%stests%s" % (os.sep, os.sep) 448 file_dir = os.path.dirname(test_suite_path) 449 pos = file_dir.find(pattern) 450 if -1 == pos: 451 return "" 452 453 sub_path = file_dir[pos + len(pattern):] 454 pos = sub_path.find(os.sep) 455 if -1 == pos: 456 return "" 457 return sub_path[pos + len(os.sep):] 458 459 460def is_config_str(content): 461 return True if "{" in content and "}" in content else False 462 463 464def is_python_satisfied(): 465 mini_version = (3, 7, 0) 466 if sys.version_info > mini_version: 467 return True 468 LOG.error("Please use python {} or higher version to start project".format(mini_version)) 469 return False 470 471 472def get_version(): 473 from xdevice import Variables 474 ver = '' 475 ver_file_path = os.path.join(Variables.res_dir, 'version.txt') 476 if not os.path.isfile(ver_file_path): 477 return ver 478 flags = os.O_RDONLY 479 modes = stat.S_IWUSR | stat.S_IRUSR 480 with os.fdopen(os.open(ver_file_path, flags, modes), 481 "rb") as ver_file: 482 content_list = ver_file.read().decode("utf-8").split("\n") 483 for line in content_list: 484 if line.strip() and "-v" in line: 485 ver = line.strip().split('-')[1] 486 ver = ver.split(':')[0][1:] 487 break 488 489 return ver 490 491 492def get_instance_name(instance): 493 return instance.__class__.__name__ 494 495 496def convert_ip(origin_ip): 497 addr = origin_ip.strip().split(".") 498 if len(addr) == 4: 499 return "{}.{}.{}.{}".format( 500 addr[0], '*' * len(addr[1]), '*' * len(addr[2]), addr[-1]) 501 else: 502 return origin_ip 503 504 505def convert_port(port): 506 _port = str(port) 507 if len(_port) >= 2: 508 return "{}{}{}".format(_port[0], "*" * (len(_port) - 2), _port[-1]) 509 else: 510 return "*{}".format(_port[-1]) 511 512 513def convert_serial(serial): 514 if serial.startswith("local_"): 515 return serial 516 elif serial.startswith("remote_"): 517 return "remote_{}_{}".format(convert_ip(serial.split("_")[1]), 518 convert_port(serial.split("_")[-1])) 519 else: 520 length = len(serial) // 3 521 return "{}{}{}".format( 522 serial[0:length], "*" * (len(serial) - length * 2), serial[-length:]) 523 524 525def get_shell_handler(request, parser_type): 526 suite_name = request.root.source.test_name 527 parsers = get_plugin(Plugin.PARSER, parser_type) 528 if parsers: 529 parsers = parsers[:1] 530 parser_instances = [] 531 for listener in request.listeners: 532 listener.device_sn = request.config.environment.devices[0].device_sn 533 for parser in parsers: 534 parser_instance = parser.__class__() 535 parser_instance.suite_name = suite_name 536 parser_instance.listeners = request.listeners 537 parser_instances.append(parser_instance) 538 handler = ShellHandler(parser_instances) 539 return handler 540 541 542def get_kit_instances(json_config, resource_path="", testcases_path=""): 543 from _core.testkit.json_parser import JsonParser 544 kit_instances = [] 545 546 # check input param 547 if not isinstance(json_config, JsonParser): 548 return kit_instances 549 550 # get kit instances 551 for kit in json_config.config.kits: 552 kit["paths"] = [resource_path, testcases_path] 553 kit_type = kit.get("type", "") 554 device_name = kit.get("device_name", None) 555 if get_plugin(plugin_type=Plugin.TEST_KIT, plugin_id=kit_type): 556 test_kit = \ 557 get_plugin(plugin_type=Plugin.TEST_KIT, plugin_id=kit_type)[0] 558 test_kit_instance = test_kit.__class__() 559 test_kit_instance.__check_config__(kit) 560 setattr(test_kit_instance, "device_name", device_name) 561 kit_instances.append(test_kit_instance) 562 else: 563 raise ParamError("kit %s not exists" % kit_type, error_no="00107") 564 return kit_instances 565 566 567def check_device_name(device, kit, step="setup"): 568 kit_device_name = getattr(kit, "device_name", None) 569 device_name = device.get("name") 570 if kit_device_name and device_name and \ 571 kit_device_name != device_name: 572 return False 573 if kit_device_name and device_name: 574 LOG.debug("Do kit:%s %s for device:%s", 575 kit.__class__.__name__, step, device_name) 576 else: 577 LOG.debug("Do kit:%s %s", kit.__class__.__name__, step) 578 return True 579 580 581def check_device_env_index(device, kit): 582 if not hasattr(device, "env_index"): 583 return True 584 kit_device_index_list = getattr(kit, "env_index_list", None) 585 env_index = device.get("env_index") 586 if kit_device_index_list and env_index and \ 587 len(kit_device_index_list) > 0 and env_index not in kit_device_index_list: 588 return False 589 return True 590 591 592def check_path_legal(path): 593 if path and " " in path: 594 return "\"%s\"" % path 595 return path 596 597 598def get_local_ip(): 599 try: 600 sys_type = platform.system() 601 if sys_type == "Windows": 602 _list = socket.gethostbyname_ex(socket.gethostname()) 603 _list = _list[2] 604 for ip_add in _list: 605 if ip_add.startswith("10."): 606 return ip_add 607 608 return socket.gethostbyname(socket.getfqdn(socket.gethostname())) 609 elif sys_type == "Darwin": 610 hostname = socket.getfqdn(socket.gethostname()) 611 return socket.gethostbyname(hostname) 612 elif sys_type == "Linux": 613 real_ip = "/%s/%s" % ("hostip", "realip") 614 if os.path.exists(real_ip): 615 srw = None 616 try: 617 import codecs 618 srw = codecs.open(real_ip, "r", "utf-8") 619 lines = srw.readlines() 620 local_ip = str(lines[0]).strip() 621 except (IOError, ValueError) as error_message: 622 LOG.error(error_message) 623 local_ip = "127.0.0.1" 624 finally: 625 if srw is not None: 626 srw.close() 627 else: 628 local_ip = "127.0.0.1" 629 return local_ip 630 else: 631 return "127.0.0.1" 632 except Exception as error: 633 LOG.debug("Get local ip error: %s, skip!" % error) 634 return "127.0.0.1" 635 636 637class SplicingAction(argparse.Action): 638 def __call__(self, parser, namespace, values, option_string=None): 639 setattr(namespace, self.dest, " ".join(values)) 640 641 642def get_test_component_version(config): 643 if check_mode(ModeType.decc): 644 return "" 645 646 try: 647 paths = [config.resource_path, config.testcases_path] 648 test_file = get_file_absolute_path("test_component.json", paths) 649 flags = os.O_RDONLY 650 modes = stat.S_IWUSR | stat.S_IRUSR 651 with os.fdopen(os.open(test_file, flags, modes), "r") as file_content: 652 json_content = json.load(file_content) 653 version = json_content.get("version", "") 654 return version 655 except (ParamError, ValueError) as error: 656 LOG.error("The exception {} happened when get version".format(error)) 657 return "" 658 659 660def check_mode(mode): 661 from xdevice import Scheduler 662 return Scheduler.mode == mode 663 664 665def do_module_kit_setup(request, kits): 666 for device in request.get_devices(): 667 setattr(device, ConfigConst.module_kits, []) 668 669 from xdevice import Scheduler 670 for kit in kits: 671 run_flag = False 672 for device in request.get_devices(): 673 if not Scheduler.is_execute: 674 raise ExecuteTerminate() 675 if not check_device_env_index(device, kit): 676 continue 677 if check_device_name(device, kit): 678 run_flag = True 679 kit_copy = copy.deepcopy(kit) 680 module_kits = getattr(device, ConfigConst.module_kits) 681 module_kits.append(kit_copy) 682 kit_copy.__setup__(device, request=request) 683 if not run_flag: 684 kit_device_name = getattr(kit, "device_name", None) 685 error_msg = "device name '%s' of '%s' not exist" % ( 686 kit_device_name, kit.__class__.__name__) 687 LOG.error(error_msg, error_no="00108") 688 raise ParamError(error_msg, error_no="00108") 689 690 691def do_module_kit_teardown(request): 692 for device in request.get_devices(): 693 for kit in getattr(device, ConfigConst.module_kits, []): 694 if check_device_name(device, kit, step="teardown"): 695 kit.__teardown__(device) 696 setattr(device, ConfigConst.module_kits, []) 697 698 699def get_cst_time(): 700 cn_tz = timezone(timedelta(hours=8), 701 name='Asia/ShangHai') 702 return datetime.now(tz=cn_tz) 703 704 705def get_device_proc_pid(device, proc_name, double_check=False): 706 if not hasattr(device, "execute_shell_command") or \ 707 not hasattr(device, "log") or \ 708 not hasattr(device, "get_recover_state"): 709 return "" 710 if not device.get_recover_state(): 711 return "" 712 cmd = 'ps -ef | grep %s' % proc_name 713 proc_running = device.execute_shell_command(cmd).strip() 714 proc_running = proc_running.split("\n") 715 for data in proc_running: 716 if proc_name in data and "grep" not in data: 717 device.log.debug('{} running status:{}'.format(proc_name, data)) 718 data = data.split() 719 return data[1] 720 if double_check: 721 cmd = 'ps -A | grep %s' % proc_name 722 proc_running = device.execute_shell_command(cmd).strip() 723 proc_running = proc_running.split("\n") 724 for data in proc_running: 725 if proc_name in data: 726 device.log.debug('{} running status double_check:{}'.format(proc_name, data)) 727 data = data.split() 728 return data[0] 729 return "" 730