• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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="", module_name=None):
397    from xdevice import Variables
398    if module_name:
399        log_path = os.path.join(report_path, Variables.report_vars.log_dir, module_name)
400    else:
401        log_path = os.path.join(report_path, Variables.report_vars.log_dir)
402    os.makedirs(log_path, exist_ok=True)
403
404    serial = serial or time.time_ns()
405    if device_name:
406        serial = "%s_%s" % (device_name, serial)
407    device_file_name = "{}_{}.log".format(log_name, str(serial).replace(
408        ":", "_"))
409    device_log_file = os.path.join(log_path, device_file_name)
410    LOG.info("Generate device log file: %s", device_log_file)
411    return device_log_file
412
413
414def check_result_report(report_root_dir, report_file, error_message="",
415                        report_name="", module_name=""):
416    """
417    Check whether report_file exits or not. If report_file is not exist,
418    create empty report with error_message under report_root_dir
419    """
420
421    if os.path.exists(report_file):
422        return report_file
423    report_dir = os.path.dirname(report_file)
424    if os.path.isabs(report_dir):
425        result_dir = report_dir
426    else:
427        result_dir = os.path.join(report_root_dir, "result", report_dir)
428    os.makedirs(result_dir, exist_ok=True)
429    if check_mode(ModeType.decc):
430        LOG.error("Report not exist, create empty report")
431    else:
432        LOG.error("Report %s not exist, create empty report under %s" % (
433            report_file, result_dir))
434
435    suite_name = report_name
436    if not suite_name:
437        suite_name, _ = get_filename_extension(report_file)
438    suite_result = SuiteResult()
439    suite_result.suite_name = suite_name
440    suite_result.stacktrace = error_message
441    if module_name:
442        suite_name = module_name
443    suite_reporter = SuiteReporter([(suite_result, [])], suite_name,
444                                   result_dir, modulename=module_name)
445    suite_reporter.create_empty_report()
446    return "%s.xml" % os.path.join(result_dir, suite_name)
447
448
449def get_sub_path(test_suite_path):
450    pattern = "%stests%s" % (os.sep, os.sep)
451    file_dir = os.path.dirname(test_suite_path)
452    pos = file_dir.find(pattern)
453    if -1 == pos:
454        return ""
455
456    sub_path = file_dir[pos + len(pattern):]
457    pos = sub_path.find(os.sep)
458    if -1 == pos:
459        return ""
460    return sub_path[pos + len(os.sep):]
461
462
463def is_config_str(content):
464    return True if "{" in content and "}" in content else False
465
466
467def is_python_satisfied():
468    mini_version = (3, 7, 0)
469    if sys.version_info > mini_version:
470        return True
471    LOG.error("Please use python {} or higher version to start project".format(mini_version))
472    return False
473
474
475def get_version():
476    from xdevice import Variables
477    ver = ''
478    ver_file_path = os.path.join(Variables.res_dir, 'version.txt')
479    if not os.path.isfile(ver_file_path):
480        return ver
481    flags = os.O_RDONLY
482    modes = stat.S_IWUSR | stat.S_IRUSR
483    with os.fdopen(os.open(ver_file_path, flags, modes),
484                   "rb") as ver_file:
485        content_list = ver_file.read().decode("utf-8").split("\n")
486        for line in content_list:
487            if line.strip() and "-v" in line:
488                ver = line.strip().split('-')[1]
489                ver = ver.split(':')[0][1:]
490                break
491
492    return ver
493
494
495def get_instance_name(instance):
496    return instance.__class__.__name__
497
498
499def convert_ip(origin_ip):
500    addr = origin_ip.strip().split(".")
501    if len(addr) == 4:
502        return "{}.{}.{}.{}".format(
503            addr[0], '*' * len(addr[1]), '*' * len(addr[2]), addr[-1])
504    else:
505        return origin_ip
506
507
508def convert_port(port):
509    _port = str(port)
510    if len(_port) >= 2:
511        return "{}{}{}".format(_port[0], "*" * (len(_port) - 2), _port[-1])
512    else:
513        return "*{}".format(_port[-1])
514
515
516def convert_serial(serial):
517    if serial.startswith("local_"):
518        return serial
519    elif serial.startswith("remote_"):
520        return "remote_{}_{}".format(convert_ip(serial.split("_")[1]),
521                                     convert_port(serial.split("_")[-1]))
522    else:
523        length = len(serial) // 3
524        return "{}{}{}".format(
525            serial[0:length], "*" * (len(serial) - length * 2), serial[-length:])
526
527
528def get_shell_handler(request, parser_type):
529    suite_name = request.root.source.test_name
530    parsers = get_plugin(Plugin.PARSER, parser_type)
531    if parsers:
532        parsers = parsers[:1]
533    parser_instances = []
534    for listener in request.listeners:
535        listener.device_sn = request.config.environment.devices[0].device_sn
536    for parser in parsers:
537        parser_instance = parser.__class__()
538        parser_instance.suite_name = suite_name
539        parser_instance.listeners = request.listeners
540        parser_instances.append(parser_instance)
541    handler = ShellHandler(parser_instances)
542    return handler
543
544
545def get_kit_instances(json_config, resource_path="", testcases_path=""):
546    from _core.testkit.json_parser import JsonParser
547    kit_instances = []
548
549    # check input param
550    if not isinstance(json_config, JsonParser):
551        return kit_instances
552
553    # get kit instances
554    for kit in json_config.config.kits:
555        kit["paths"] = [resource_path, testcases_path]
556        kit_type = kit.get("type", "")
557        device_name = kit.get("device_name", None)
558        if get_plugin(plugin_type=Plugin.TEST_KIT, plugin_id=kit_type):
559            test_kit = \
560                get_plugin(plugin_type=Plugin.TEST_KIT, plugin_id=kit_type)[0]
561            test_kit_instance = test_kit.__class__()
562            test_kit_instance.__check_config__(kit)
563            setattr(test_kit_instance, "device_name", device_name)
564            kit_instances.append(test_kit_instance)
565        else:
566            raise ParamError("kit %s not exists" % kit_type, error_no="00107")
567    return kit_instances
568
569
570def check_device_name(device, kit, step="setup"):
571    kit_device_name = getattr(kit, "device_name", None)
572    device_name = device.get("name")
573    if kit_device_name and device_name and \
574            kit_device_name != device_name:
575        return False
576    if kit_device_name and device_name:
577        LOG.debug("Do kit:%s %s for device:%s",
578                  kit.__class__.__name__, step, device_name)
579    else:
580        LOG.debug("Do kit:%s %s", kit.__class__.__name__, step)
581    return True
582
583
584def check_device_env_index(device, kit):
585    if not hasattr(device, "env_index"):
586        return True
587    kit_device_index_list = getattr(kit, "env_index_list", None)
588    env_index = device.get("env_index")
589    if kit_device_index_list and env_index and \
590            len(kit_device_index_list) > 0 and env_index not in kit_device_index_list:
591        return False
592    return True
593
594
595def check_path_legal(path):
596    if path and " " in path:
597        return "\"%s\"" % path
598    return path
599
600
601def get_local_ip():
602    try:
603        sys_type = platform.system()
604        if sys_type == "Windows":
605            _list = socket.gethostbyname_ex(socket.gethostname())
606            _list = _list[2]
607            for ip_add in _list:
608                if ip_add.startswith("10."):
609                    return ip_add
610
611            return socket.gethostbyname(socket.getfqdn(socket.gethostname()))
612        elif sys_type == "Darwin":
613            hostname = socket.getfqdn(socket.gethostname())
614            return socket.gethostbyname(hostname)
615        elif sys_type == "Linux":
616            real_ip = "/%s/%s" % ("hostip", "realip")
617            if os.path.exists(real_ip):
618                srw = None
619                try:
620                    import codecs
621                    srw = codecs.open(real_ip, "r", "utf-8")
622                    lines = srw.readlines()
623                    local_ip = str(lines[0]).strip()
624                except (IOError, ValueError) as error_message:
625                    LOG.error(error_message)
626                    local_ip = "127.0.0.1"
627                finally:
628                    if srw is not None:
629                        srw.close()
630            else:
631                local_ip = "127.0.0.1"
632            return local_ip
633        else:
634            return "127.0.0.1"
635    except Exception as error:
636        LOG.debug("Get local ip error: %s, skip!" % error)
637        return "127.0.0.1"
638
639
640class SplicingAction(argparse.Action):
641    def __call__(self, parser, namespace, values, option_string=None):
642        setattr(namespace, self.dest, " ".join(values))
643
644
645def get_test_component_version(config):
646    if check_mode(ModeType.decc):
647        return ""
648
649    try:
650        paths = [config.resource_path, config.testcases_path]
651        test_file = get_file_absolute_path("test_component.json", paths)
652        flags = os.O_RDONLY
653        modes = stat.S_IWUSR | stat.S_IRUSR
654        with os.fdopen(os.open(test_file, flags, modes), "r") as file_content:
655            json_content = json.load(file_content)
656            version = json_content.get("version", "")
657            return version
658    except (ParamError, ValueError) as error:
659        LOG.error("The exception {} happened when get version".format(error))
660    return ""
661
662
663def check_mode(mode):
664    from xdevice import Scheduler
665    return Scheduler.mode == mode
666
667
668def do_module_kit_setup(request, kits):
669    for device in request.get_devices():
670        setattr(device, ConfigConst.module_kits, [])
671
672    from xdevice import Scheduler
673    for kit in kits:
674        run_flag = False
675        for device in request.get_devices():
676            if not Scheduler.is_execute:
677                raise ExecuteTerminate()
678            if not check_device_env_index(device, kit):
679                continue
680            if check_device_name(device, kit):
681                run_flag = True
682                kit_copy = copy.deepcopy(kit)
683                module_kits = getattr(device, ConfigConst.module_kits)
684                module_kits.append(kit_copy)
685                kit_copy.__setup__(device, request=request)
686        if not run_flag:
687            kit_device_name = getattr(kit, "device_name", None)
688            error_msg = "device name '%s' of '%s' not exist" % (
689                kit_device_name, kit.__class__.__name__)
690            LOG.error(error_msg, error_no="00108")
691            raise ParamError(error_msg, error_no="00108")
692
693
694def do_module_kit_teardown(request):
695    for device in request.get_devices():
696        for kit in getattr(device, ConfigConst.module_kits, []):
697            if check_device_name(device, kit, step="teardown"):
698                kit.__teardown__(device)
699        setattr(device, ConfigConst.module_kits, [])
700
701
702def get_cst_time():
703    cn_tz = timezone(timedelta(hours=8),
704                     name='Asia/ShangHai')
705    return datetime.now(tz=cn_tz)
706
707
708def get_delta_time_ms(start_time):
709    end_time = get_cst_time()
710    delta = round(float((end_time - start_time).total_seconds()) * 1000, 3)
711    return delta
712
713
714def get_device_proc_pid(device, proc_name, double_check=False):
715    if not hasattr(device, "execute_shell_command") or \
716            not hasattr(device, "log") or \
717            not hasattr(device, "get_recover_state"):
718        return ""
719    if not device.get_recover_state():
720        return ""
721    cmd = 'ps -ef | 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 and "grep" not in data:
726            device.log.debug('{} running status:{}'.format(proc_name, data))
727            data = data.split()
728            return data[1]
729    if double_check:
730        cmd = 'ps -A | grep %s' % proc_name
731        proc_running = device.execute_shell_command(cmd).strip()
732        proc_running = proc_running.split("\n")
733        for data in proc_running:
734            if proc_name in data:
735                device.log.debug('{} running status double_check:{}'.format(proc_name, data))
736                data = data.split()
737                return data[0]
738    return ""
739