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