jenkins构建问题

问题

jenkins构建出现:Permission denied: ‘/usr/local/lib/python3.6’
此路径在服务器上不存在/usr/local/lib/。
python实际路径在
image

报错信息

环境

python的服务器路径:/usr/lib64
image

报错的路径.实际在服务器上不存在。/usr/local/lib下面没有python3

你的job的配置和完整的log发一下吧





建议使用虚拟环境的方式
然后你第一步先进行环境的导出,第二步进行安装感觉没啥意义呢

用的是docker。第一部的操作是因为在服务器上执行了pip3 freeze > requirements.txt后,文件里面的内容都消失了。后面另外一个老师指导说放在第一步。
我的问题是为啥会读:/usr/local/lib。是因为python吗?还是因为其他的。python的路径是/usr/lib/python3.6

使用jenkins来运行测试的时候
建议使用宿主机挂载节点,指定节点运行
使用虚拟环境来运行你的项目

报错信息如下:
控制台输出
Started by user jenkins
Running as SYSTEM
Building remotely on centos-test in workspace /home/homeward/workspace/ceshiren
The recommended git tool is: NONE
using credential gitlab

/usr/bin/git rev-parse --resolve-git-dir /home/homeward/workspace/ceshiren/.git # timeout=10
Fetching changes from the remote Git repository
/usr/bin/git config remote.origin.url http://gitlab.halos.bgi.com/wangsa/geekapi.git # timeout=10
Fetching upstream changes from http://gitlab.halos.bgi.com/wangsa/geekapi.git
/usr/bin/git --version # timeout=10
git --version # ‘git version 1.8.3.1’
using GIT_ASKPASS to set credentials gitlab
/usr/bin/git fetch --tags --progress http://gitlab.halos.bgi.com/wangsa/geekapi.git +refs/heads/:refs/remotes/origin/ # timeout=10
/usr/bin/git rev-parse refs/remotes/origin/master^{commit} # timeout=10
Checking out Revision 2d2d4cdb1d654638efc64059b097a500cb954f57 (refs/remotes/origin/master)
/usr/bin/git config core.sparsecheckout # timeout=10
/usr/bin/git checkout -f 2d2d4cdb1d654638efc64059b097a500cb954f57 # timeout=10
Commit message: “Update requirements.txt”
/usr/bin/git rev-list --no-walk 2d2d4cdb1d654638efc64059b097a500cb954f57 # timeout=10
[ceshiren] $ /bin/bash -xe /tmp/jenkins14449386447026264702.sh

  • pip3 install -r /home/homeward/geekapi/requirements.txt -i Simple Index --trusted-host pypi.douban.com
    Requirement already satisfied: allure-pytest in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 1))
    Requirement already satisfied: allure-python-commons in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 2))
    Requirement already satisfied: asgiref in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 3))
    Requirement already satisfied: jsonpath in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 4))
    Requirement already satisfied: py in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 5))
    Requirement already satisfied: pytest in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: requests in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 7))
    Requirement already satisfied: selenium in /usr/local/lib/python3.6/site-packages (from -r /home/homeward/geekapi/requirements.txt (line 8))
    Requirement already satisfied: six>=1.9.0 in /usr/local/lib/python3.6/site-packages (from allure-pytest->-r /home/homeward/geekapi/requirements.txt (line 1))
    Requirement already satisfied: pluggy>=0.4.0 in /usr/local/lib/python3.6/site-packages (from allure-python-commons->-r /home/homeward/geekapi/requirements.txt (line 2))
    Requirement already satisfied: attrs>=16.0.0 in /usr/local/lib/python3.6/site-packages (from allure-python-commons->-r /home/homeward/geekapi/requirements.txt (line 2))
    Requirement already satisfied: typing-extensions; python_version < “3.8” in /usr/local/lib/python3.6/site-packages (from asgiref->-r /home/homeward/geekapi/requirements.txt (line 3))
    Requirement already satisfied: importlib-metadata>=0.12; python_version < “3.8” in /usr/local/lib/python3.6/site-packages (from pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: packaging in /usr/local/lib/python3.6/site-packages (from pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.6/site-packages (from pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: iniconfig in /usr/local/lib/python3.6/site-packages (from pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: idna<4,>=2.5; python_version >= “3” in /usr/local/lib/python3.6/site-packages (from requests->-r /home/homeward/geekapi/requirements.txt (line 7))
    Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.6/site-packages (from requests->-r /home/homeward/geekapi/requirements.txt (line 7))
    Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/site-packages (from requests->-r /home/homeward/geekapi/requirements.txt (line 7))
    Requirement already satisfied: charset-normalizer~=2.0.0; python_version >= “3” in /usr/local/lib/python3.6/site-packages (from requests->-r /home/homeward/geekapi/requirements.txt (line 7))
    Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.6/site-packages (from importlib-metadata>=0.12; python_version < “3.8”->pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
    Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.6/site-packages (from packaging->pytest->-r /home/homeward/geekapi/requirements.txt (line 6))
  • python3 -m pytest /home/homeward/geekapi/test_ceshiren.py
    ============================= test session starts ==============================
    platform linux – Python 3.6.8, pytest-7.0.1, pluggy-1.0.0
    rootdir: /home/homeward
    plugins: allure-pytest-2.11.0
    collected 3 items

…/…/geekapi/test_ceshiren.py EEE [100%]

==================================== ERRORS ====================================
__________ ERROR at setup of TestCeshirenSearch.test_search[selenium] __________

self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                      stdin=PIPE)

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:76:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], bufsize = -1, executable = None
stdin = -1, stdout = -3, stderr = -3, preexec_fn = None, close_fds = True
shell = False, cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …sr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[selenium] (setup)’})
universal_newlines = False, startupinfo = None, creationflags = 0
restore_signals = True, start_new_session = False, pass_fds = ()

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):
    """Create new Popen instance."""
    _cleanup()
    # Held while anything is calling waitpid before returncode has been
    # updated to prevent clobbering returncode if wait() or poll() are
    # called from multiple threads at once.  After acquiring the lock,
    # code must re-check self.returncode to see if another thread just
    # finished a waitpid() call.
    self._waitpid_lock = threading.Lock()

    self._input = None
    self._communication_started = False
    if bufsize is None:
        bufsize = -1  # Restore default
    if not isinstance(bufsize, int):
        raise TypeError("bufsize must be an integer")

    if _mswindows:
        if preexec_fn is not None:
            raise ValueError("preexec_fn is not supported on Windows "
                             "platforms")
        any_stdio_set = (stdin is not None or stdout is not None or
                         stderr is not None)
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            if any_stdio_set:
                close_fds = False
            else:
                close_fds = True
        elif close_fds and any_stdio_set:
            raise ValueError(
                    "close_fds is not supported on Windows platforms"
                    " if you redirect stdin/stdout/stderr")
    else:
        # POSIX
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            close_fds = True
        if pass_fds and not close_fds:
            warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)
            close_fds = True
        if startupinfo is not None:
            raise ValueError("startupinfo is only supported on Windows "
                             "platforms")
        if creationflags != 0:
            raise ValueError("creationflags is only supported on Windows "
                             "platforms")

    self.args = args
    self.stdin = None
    self.stdout = None
    self.stderr = None
    self.pid = None
    self.returncode = None
    self.universal_newlines = universal_newlines
    self.encoding = encoding
    self.errors = errors

    # Input and output objects. The general principle is like
    # this:
    #
    # Parent                   Child
    # ------                   -----
    # p2cwrite   ---stdin--->  p2cread
    # c2pread    <--stdout---  c2pwrite
    # errread    <--stderr---  errwrite
    #
    # On POSIX, the child objects are file descriptors.  On
    # Windows, these are Windows file handles.  The parent objects
    # are file descriptors on both platforms.  The parent objects
    # are -1 when not using PIPEs. The child objects are -1
    # when not redirecting.

    (p2cread, p2cwrite,
     c2pread, c2pwrite,
     errread, errwrite) = self._get_handles(stdin, stdout, stderr)

    # We wrap OS handles *before* launching the child, otherwise a
    # quickly terminating child could make our fds unwrappable
    # (see #8458).

    if _mswindows:
        if p2cwrite != -1:
            p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
        if c2pread != -1:
            c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)
        if errread != -1:
            errread = msvcrt.open_osfhandle(errread.Detach(), 0)

    text_mode = encoding or errors or universal_newlines

    self._closed_child_pipe_fds = False

    try:
        if p2cwrite != -1:
            self.stdin = io.open(p2cwrite, 'wb', bufsize)
            if text_mode:
                self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
                        line_buffering=(bufsize == 1),
                        encoding=encoding, errors=errors)
        if c2pread != -1:
            self.stdout = io.open(c2pread, 'rb', bufsize)
            if text_mode:
                self.stdout = io.TextIOWrapper(self.stdout,
                        encoding=encoding, errors=errors)
        if errread != -1:
            self.stderr = io.open(errread, 'rb', bufsize)
            if text_mode:
                self.stderr = io.TextIOWrapper(self.stderr,
                        encoding=encoding, errors=errors)

        self._execute_child(args, executable, preexec_fn, close_fds,
                            pass_fds, cwd, env,
                            startupinfo, creationflags, shell,
                            p2cread, p2cwrite,
                            c2pread, c2pwrite,
                            errread, errwrite,
                          restore_signals, start_new_session)

/usr/lib64/python3.6/subprocess.py:729:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], executable = b’chromedriver’
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …sr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[selenium] (setup)’})
startupinfo = None, creationflags = 0, shell = False, p2cread = 11
p2cwrite = 12, c2pread = -1, c2pwrite = 13, errread = -1, errwrite = 13
restore_signals = True, start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
                   pass_fds, cwd, env,
                   startupinfo, creationflags, shell,
                   p2cread, p2cwrite,
                   c2pread, c2pwrite,
                   errread, errwrite,
                   restore_signals, start_new_session):
    """Execute program (POSIX version)"""

    if isinstance(args, (str, bytes)):
        args = [args]
    else:
        args = list(args)

    if shell:
        args = ["/bin/sh", "-c"] + args
        if executable:
            args[0] = executable

    if executable is None:
        executable = args[0]
    orig_executable = executable

    # For transferring possible exec failure from child to parent.
    # Data format: "exception name:hex errno:description"
    # Pickle is not used; it is complex and involves memory allocation.
    errpipe_read, errpipe_write = os.pipe()
    # errpipe_write must not be in the standard io 0, 1, or 2 fd range.
    low_fds_to_close = []
    while errpipe_write < 3:
        low_fds_to_close.append(errpipe_write)
        errpipe_write = os.dup(errpipe_write)
    for low_fd in low_fds_to_close:
        os.close(low_fd)
    try:
        try:
            # We must avoid complex work that could involve
            # malloc or free in the child process to avoid
            # potential deadlocks, thus we do all this here.
            # and pass it to fork_exec()

            if env is not None:
                env_list = []
                for k, v in env.items():
                    k = os.fsencode(k)
                    if b'=' in k:
                        raise ValueError("illegal environment variable name")
                    env_list.append(k + b'=' + os.fsencode(v))
            else:
                env_list = None  # Use execv instead of execve.
            executable = os.fsencode(executable)
            if os.path.dirname(executable):
                executable_list = (executable,)
            else:
                # This matches the behavior of os._execvpe().
                executable_list = tuple(
                    os.path.join(os.fsencode(dir), executable)
                    for dir in os.get_exec_path(env))
            fds_to_keep = set(pass_fds)
            fds_to_keep.add(errpipe_write)
            self.pid = _posixsubprocess.fork_exec(
                    args, executable_list,
                    close_fds, tuple(sorted(map(int, fds_to_keep))),
                    cwd, env_list,
                    p2cread, p2cwrite, c2pread, c2pwrite,
                    errread, errwrite,
                    errpipe_read, errpipe_write,
                    restore_signals, start_new_session, preexec_fn)
            self._child_created = True
        finally:
            # be sure the FD is closed no matter what
            os.close(errpipe_write)

        # self._devnull is not always defined.
        devnull_fd = getattr(self, '_devnull', None)
        if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
            os.close(p2cread)
        if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd:
            os.close(c2pwrite)
        if errwrite != -1 and errread != -1 and errwrite != devnull_fd:
            os.close(errwrite)
        if devnull_fd is not None:
            os.close(devnull_fd)
        # Prevent a double close of these fds from __init__ on error.
        self._closed_child_pipe_fds = True

        # Wait for exec to fail or succeed; possibly raising an
        # exception (limited in size)
        errpipe_data = bytearray()
        while True:
            part = os.read(errpipe_read, 50000)
            errpipe_data += part
            if not part or len(errpipe_data) > 50000:
                break
    finally:
        # be sure the FD is closed no matter what
        os.close(errpipe_read)

    if errpipe_data:
        try:
            pid, sts = os.waitpid(self.pid, 0)
            if pid == self.pid:
                self._handle_exitstatus(sts)
            else:
                self.returncode = sys.maxsize
        except ChildProcessError:
            pass

        try:
            exception_name, hex_errno, err_msg = (
                    errpipe_data.split(b':', 2))
            # The encoding here should match the encoding
            # written in by the subprocess implementations
            # like _posixsubprocess
            err_msg = err_msg.decode()
        except ValueError:
            exception_name = b'SubprocessError'
            hex_errno = b'0'
            err_msg = 'Bad exception data from child: {!r}'.format(
                          bytes(errpipe_data))
        child_exception_type = getattr(
                builtins, exception_name.decode('ascii'),
                SubprocessError)
        if issubclass(child_exception_type, OSError) and hex_errno:
            errno_num = int(hex_errno, 16)
            child_exec_never_called = (err_msg == "noexec")
            if child_exec_never_called:
                err_msg = ""
                # The error must be from chdir(cwd).
                err_filename = cwd
            else:
                err_filename = orig_executable
            if errno_num != 0:
                err_msg = os.strerror(errno_num)
                if errno_num == errno.ENOENT:
                    err_msg += ': ' + repr(err_filename)
          raise child_exception_type(errno_num, err_msg, err_filename)

E FileNotFoundError: [Errno 2] No such file or directory: ‘chromedriver’: ‘chromedriver’

/usr/lib64/python3.6/subprocess.py:1364: FileNotFoundError

During handling of the above exception, another exception occurred:

self = <class ‘test_ceshiren.TestCeshirenSearch’>

def setup_class(self):
    #打开浏览器
  self.driver = webdriver.Chrome()

…/…/geekapi/test_ceshiren.py:13:


/usr/local/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py:73: in init
self.service.start()


self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                        stdin=PIPE)
    except TypeError:
        raise
    except OSError as err:
        if err.errno == errno.ENOENT:
            raise WebDriverException(
                "'%s' executable needs to be in PATH. %s" % (
                  os.path.basename(self.path), self.start_error_message)

E selenium.common.exceptions.WebDriverException: Message: ‘chromedriver’ executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:83: WebDriverException
___________ ERROR at setup of TestCeshirenSearch.test_search[appium] ___________

self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                      stdin=PIPE)

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:76:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], bufsize = -1, executable = None
stdin = -1, stdout = -3, stderr = -3, preexec_fn = None, close_fds = True
shell = False, cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …/usr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[appium] (setup)’})
universal_newlines = False, startupinfo = None, creationflags = 0
restore_signals = True, start_new_session = False, pass_fds = ()

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):
    """Create new Popen instance."""
    _cleanup()
    # Held while anything is calling waitpid before returncode has been
    # updated to prevent clobbering returncode if wait() or poll() are
    # called from multiple threads at once.  After acquiring the lock,
    # code must re-check self.returncode to see if another thread just
    # finished a waitpid() call.
    self._waitpid_lock = threading.Lock()

    self._input = None
    self._communication_started = False
    if bufsize is None:
        bufsize = -1  # Restore default
    if not isinstance(bufsize, int):
        raise TypeError("bufsize must be an integer")

    if _mswindows:
        if preexec_fn is not None:
            raise ValueError("preexec_fn is not supported on Windows "
                             "platforms")
        any_stdio_set = (stdin is not None or stdout is not None or
                         stderr is not None)
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            if any_stdio_set:
                close_fds = False
            else:
                close_fds = True
        elif close_fds and any_stdio_set:
            raise ValueError(
                    "close_fds is not supported on Windows platforms"
                    " if you redirect stdin/stdout/stderr")
    else:
        # POSIX
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            close_fds = True
        if pass_fds and not close_fds:
            warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)
            close_fds = True
        if startupinfo is not None:
            raise ValueError("startupinfo is only supported on Windows "
                             "platforms")
        if creationflags != 0:
            raise ValueError("creationflags is only supported on Windows "
                             "platforms")

    self.args = args
    self.stdin = None
    self.stdout = None
    self.stderr = None
    self.pid = None
    self.returncode = None
    self.universal_newlines = universal_newlines
    self.encoding = encoding
    self.errors = errors

    # Input and output objects. The general principle is like
    # this:
    #
    # Parent                   Child
    # ------                   -----
    # p2cwrite   ---stdin--->  p2cread
    # c2pread    <--stdout---  c2pwrite
    # errread    <--stderr---  errwrite
    #
    # On POSIX, the child objects are file descriptors.  On
    # Windows, these are Windows file handles.  The parent objects
    # are file descriptors on both platforms.  The parent objects
    # are -1 when not using PIPEs. The child objects are -1
    # when not redirecting.

    (p2cread, p2cwrite,
     c2pread, c2pwrite,
     errread, errwrite) = self._get_handles(stdin, stdout, stderr)

    # We wrap OS handles *before* launching the child, otherwise a
    # quickly terminating child could make our fds unwrappable
    # (see #8458).

    if _mswindows:
        if p2cwrite != -1:
            p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
        if c2pread != -1:
            c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)
        if errread != -1:
            errread = msvcrt.open_osfhandle(errread.Detach(), 0)

    text_mode = encoding or errors or universal_newlines

    self._closed_child_pipe_fds = False

    try:
        if p2cwrite != -1:
            self.stdin = io.open(p2cwrite, 'wb', bufsize)
            if text_mode:
                self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
                        line_buffering=(bufsize == 1),
                        encoding=encoding, errors=errors)
        if c2pread != -1:
            self.stdout = io.open(c2pread, 'rb', bufsize)
            if text_mode:
                self.stdout = io.TextIOWrapper(self.stdout,
                        encoding=encoding, errors=errors)
        if errread != -1:
            self.stderr = io.open(errread, 'rb', bufsize)
            if text_mode:
                self.stderr = io.TextIOWrapper(self.stderr,
                        encoding=encoding, errors=errors)

        self._execute_child(args, executable, preexec_fn, close_fds,
                            pass_fds, cwd, env,
                            startupinfo, creationflags, shell,
                            p2cread, p2cwrite,
                            c2pread, c2pwrite,
                            errread, errwrite,
                          restore_signals, start_new_session)

/usr/lib64/python3.6/subprocess.py:729:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], executable = b’chromedriver’
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …/usr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[appium] (setup)’})
startupinfo = None, creationflags = 0, shell = False, p2cread = 11
p2cwrite = 12, c2pread = -1, c2pwrite = 13, errread = -1, errwrite = 13
restore_signals = True, start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
                   pass_fds, cwd, env,
                   startupinfo, creationflags, shell,
                   p2cread, p2cwrite,
                   c2pread, c2pwrite,
                   errread, errwrite,
                   restore_signals, start_new_session):
    """Execute program (POSIX version)"""

    if isinstance(args, (str, bytes)):
        args = [args]
    else:
        args = list(args)

    if shell:
        args = ["/bin/sh", "-c"] + args
        if executable:
            args[0] = executable

    if executable is None:
        executable = args[0]
    orig_executable = executable

    # For transferring possible exec failure from child to parent.
    # Data format: "exception name:hex errno:description"
    # Pickle is not used; it is complex and involves memory allocation.
    errpipe_read, errpipe_write = os.pipe()
    # errpipe_write must not be in the standard io 0, 1, or 2 fd range.
    low_fds_to_close = []
    while errpipe_write < 3:
        low_fds_to_close.append(errpipe_write)
        errpipe_write = os.dup(errpipe_write)
    for low_fd in low_fds_to_close:
        os.close(low_fd)
    try:
        try:
            # We must avoid complex work that could involve
            # malloc or free in the child process to avoid
            # potential deadlocks, thus we do all this here.
            # and pass it to fork_exec()

            if env is not None:
                env_list = []
                for k, v in env.items():
                    k = os.fsencode(k)
                    if b'=' in k:
                        raise ValueError("illegal environment variable name")
                    env_list.append(k + b'=' + os.fsencode(v))
            else:
                env_list = None  # Use execv instead of execve.
            executable = os.fsencode(executable)
            if os.path.dirname(executable):
                executable_list = (executable,)
            else:
                # This matches the behavior of os._execvpe().
                executable_list = tuple(
                    os.path.join(os.fsencode(dir), executable)
                    for dir in os.get_exec_path(env))
            fds_to_keep = set(pass_fds)
            fds_to_keep.add(errpipe_write)
            self.pid = _posixsubprocess.fork_exec(
                    args, executable_list,
                    close_fds, tuple(sorted(map(int, fds_to_keep))),
                    cwd, env_list,
                    p2cread, p2cwrite, c2pread, c2pwrite,
                    errread, errwrite,
                    errpipe_read, errpipe_write,
                    restore_signals, start_new_session, preexec_fn)
            self._child_created = True
        finally:
            # be sure the FD is closed no matter what
            os.close(errpipe_write)

        # self._devnull is not always defined.
        devnull_fd = getattr(self, '_devnull', None)
        if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
            os.close(p2cread)
        if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd:
            os.close(c2pwrite)
        if errwrite != -1 and errread != -1 and errwrite != devnull_fd:
            os.close(errwrite)
        if devnull_fd is not None:
            os.close(devnull_fd)
        # Prevent a double close of these fds from __init__ on error.
        self._closed_child_pipe_fds = True

        # Wait for exec to fail or succeed; possibly raising an
        # exception (limited in size)
        errpipe_data = bytearray()
        while True:
            part = os.read(errpipe_read, 50000)
            errpipe_data += part
            if not part or len(errpipe_data) > 50000:
                break
    finally:
        # be sure the FD is closed no matter what
        os.close(errpipe_read)

    if errpipe_data:
        try:
            pid, sts = os.waitpid(self.pid, 0)
            if pid == self.pid:
                self._handle_exitstatus(sts)
            else:
                self.returncode = sys.maxsize
        except ChildProcessError:
            pass

        try:
            exception_name, hex_errno, err_msg = (
                    errpipe_data.split(b':', 2))
            # The encoding here should match the encoding
            # written in by the subprocess implementations
            # like _posixsubprocess
            err_msg = err_msg.decode()
        except ValueError:
            exception_name = b'SubprocessError'
            hex_errno = b'0'
            err_msg = 'Bad exception data from child: {!r}'.format(
                          bytes(errpipe_data))
        child_exception_type = getattr(
                builtins, exception_name.decode('ascii'),
                SubprocessError)
        if issubclass(child_exception_type, OSError) and hex_errno:
            errno_num = int(hex_errno, 16)
            child_exec_never_called = (err_msg == "noexec")
            if child_exec_never_called:
                err_msg = ""
                # The error must be from chdir(cwd).
                err_filename = cwd
            else:
                err_filename = orig_executable
            if errno_num != 0:
                err_msg = os.strerror(errno_num)
                if errno_num == errno.ENOENT:
                    err_msg += ': ' + repr(err_filename)
          raise child_exception_type(errno_num, err_msg, err_filename)

E FileNotFoundError: [Errno 2] No such file or directory: ‘chromedriver’: ‘chromedriver’

/usr/lib64/python3.6/subprocess.py:1364: FileNotFoundError

During handling of the above exception, another exception occurred:

self = <class ‘test_ceshiren.TestCeshirenSearch’>

def setup_class(self):
    #打开浏览器
  self.driver = webdriver.Chrome()

…/…/geekapi/test_ceshiren.py:13:


/usr/local/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py:73: in init
self.service.start()


self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                        stdin=PIPE)
    except TypeError:
        raise
    except OSError as err:
        if err.errno == errno.ENOENT:
            raise WebDriverException(
                "'%s' executable needs to be in PATH. %s" % (
                  os.path.basename(self.path), self.start_error_message)

E selenium.common.exceptions.WebDriverException: Message: ‘chromedriver’ executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:83: WebDriverException
__________ ERROR at setup of TestCeshirenSearch.test_search[requests] __________

self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                      stdin=PIPE)

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:76:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], bufsize = -1, executable = None
stdin = -1, stdout = -3, stderr = -3, preexec_fn = None, close_fds = True
shell = False, cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …sr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[requests] (setup)’})
universal_newlines = False, startupinfo = None, creationflags = 0
restore_signals = True, start_new_session = False, pass_fds = ()

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):
    """Create new Popen instance."""
    _cleanup()
    # Held while anything is calling waitpid before returncode has been
    # updated to prevent clobbering returncode if wait() or poll() are
    # called from multiple threads at once.  After acquiring the lock,
    # code must re-check self.returncode to see if another thread just
    # finished a waitpid() call.
    self._waitpid_lock = threading.Lock()

    self._input = None
    self._communication_started = False
    if bufsize is None:
        bufsize = -1  # Restore default
    if not isinstance(bufsize, int):
        raise TypeError("bufsize must be an integer")

    if _mswindows:
        if preexec_fn is not None:
            raise ValueError("preexec_fn is not supported on Windows "
                             "platforms")
        any_stdio_set = (stdin is not None or stdout is not None or
                         stderr is not None)
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            if any_stdio_set:
                close_fds = False
            else:
                close_fds = True
        elif close_fds and any_stdio_set:
            raise ValueError(
                    "close_fds is not supported on Windows platforms"
                    " if you redirect stdin/stdout/stderr")
    else:
        # POSIX
        if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
            close_fds = True
        if pass_fds and not close_fds:
            warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)
            close_fds = True
        if startupinfo is not None:
            raise ValueError("startupinfo is only supported on Windows "
                             "platforms")
        if creationflags != 0:
            raise ValueError("creationflags is only supported on Windows "
                             "platforms")

    self.args = args
    self.stdin = None
    self.stdout = None
    self.stderr = None
    self.pid = None
    self.returncode = None
    self.universal_newlines = universal_newlines
    self.encoding = encoding
    self.errors = errors

    # Input and output objects. The general principle is like
    # this:
    #
    # Parent                   Child
    # ------                   -----
    # p2cwrite   ---stdin--->  p2cread
    # c2pread    <--stdout---  c2pwrite
    # errread    <--stderr---  errwrite
    #
    # On POSIX, the child objects are file descriptors.  On
    # Windows, these are Windows file handles.  The parent objects
    # are file descriptors on both platforms.  The parent objects
    # are -1 when not using PIPEs. The child objects are -1
    # when not redirecting.

    (p2cread, p2cwrite,
     c2pread, c2pwrite,
     errread, errwrite) = self._get_handles(stdin, stdout, stderr)

    # We wrap OS handles *before* launching the child, otherwise a
    # quickly terminating child could make our fds unwrappable
    # (see #8458).

    if _mswindows:
        if p2cwrite != -1:
            p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
        if c2pread != -1:
            c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)
        if errread != -1:
            errread = msvcrt.open_osfhandle(errread.Detach(), 0)

    text_mode = encoding or errors or universal_newlines

    self._closed_child_pipe_fds = False

    try:
        if p2cwrite != -1:
            self.stdin = io.open(p2cwrite, 'wb', bufsize)
            if text_mode:
                self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
                        line_buffering=(bufsize == 1),
                        encoding=encoding, errors=errors)
        if c2pread != -1:
            self.stdout = io.open(c2pread, 'rb', bufsize)
            if text_mode:
                self.stdout = io.TextIOWrapper(self.stdout,
                        encoding=encoding, errors=errors)
        if errread != -1:
            self.stderr = io.open(errread, 'rb', bufsize)
            if text_mode:
                self.stderr = io.TextIOWrapper(self.stderr,
                        encoding=encoding, errors=errors)

        self._execute_child(args, executable, preexec_fn, close_fds,
                            pass_fds, cwd, env,
                            startupinfo, creationflags, shell,
                            p2cread, p2cwrite,
                            c2pread, c2pwrite,
                            errread, errwrite,
                          restore_signals, start_new_session)

/usr/lib64/python3.6/subprocess.py:729:


self = <subprocess.Popen object at 0x7f8b36fe9ef0>
args = [‘chromedriver’, ‘–port=60617’], executable = b’chromedriver’
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None
env = environ({‘BUILD_URL’: ‘http://10.227.4.150:8080/job/ceshiren/73/’, ‘XDG_SESSION_ID’: ‘16939’, ‘HUDSON_SERVER_COOKIE’: …sr/bin/python3’, ‘PYTEST_CURRENT_TEST’: ‘geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[requests] (setup)’})
startupinfo = None, creationflags = 0, shell = False, p2cread = 11
p2cwrite = 12, c2pread = -1, c2pwrite = 13, errread = -1, errwrite = 13
restore_signals = True, start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
                   pass_fds, cwd, env,
                   startupinfo, creationflags, shell,
                   p2cread, p2cwrite,
                   c2pread, c2pwrite,
                   errread, errwrite,
                   restore_signals, start_new_session):
    """Execute program (POSIX version)"""

    if isinstance(args, (str, bytes)):
        args = [args]
    else:
        args = list(args)

    if shell:
        args = ["/bin/sh", "-c"] + args
        if executable:
            args[0] = executable

    if executable is None:
        executable = args[0]
    orig_executable = executable

    # For transferring possible exec failure from child to parent.
    # Data format: "exception name:hex errno:description"
    # Pickle is not used; it is complex and involves memory allocation.
    errpipe_read, errpipe_write = os.pipe()
    # errpipe_write must not be in the standard io 0, 1, or 2 fd range.
    low_fds_to_close = []
    while errpipe_write < 3:
        low_fds_to_close.append(errpipe_write)
        errpipe_write = os.dup(errpipe_write)
    for low_fd in low_fds_to_close:
        os.close(low_fd)
    try:
        try:
            # We must avoid complex work that could involve
            # malloc or free in the child process to avoid
            # potential deadlocks, thus we do all this here.
            # and pass it to fork_exec()

            if env is not None:
                env_list = []
                for k, v in env.items():
                    k = os.fsencode(k)
                    if b'=' in k:
                        raise ValueError("illegal environment variable name")
                    env_list.append(k + b'=' + os.fsencode(v))
            else:
                env_list = None  # Use execv instead of execve.
            executable = os.fsencode(executable)
            if os.path.dirname(executable):
                executable_list = (executable,)
            else:
                # This matches the behavior of os._execvpe().
                executable_list = tuple(
                    os.path.join(os.fsencode(dir), executable)
                    for dir in os.get_exec_path(env))
            fds_to_keep = set(pass_fds)
            fds_to_keep.add(errpipe_write)
            self.pid = _posixsubprocess.fork_exec(
                    args, executable_list,
                    close_fds, tuple(sorted(map(int, fds_to_keep))),
                    cwd, env_list,
                    p2cread, p2cwrite, c2pread, c2pwrite,
                    errread, errwrite,
                    errpipe_read, errpipe_write,
                    restore_signals, start_new_session, preexec_fn)
            self._child_created = True
        finally:
            # be sure the FD is closed no matter what
            os.close(errpipe_write)

        # self._devnull is not always defined.
        devnull_fd = getattr(self, '_devnull', None)
        if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
            os.close(p2cread)
        if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd:
            os.close(c2pwrite)
        if errwrite != -1 and errread != -1 and errwrite != devnull_fd:
            os.close(errwrite)
        if devnull_fd is not None:
            os.close(devnull_fd)
        # Prevent a double close of these fds from __init__ on error.
        self._closed_child_pipe_fds = True

        # Wait for exec to fail or succeed; possibly raising an
        # exception (limited in size)
        errpipe_data = bytearray()
        while True:
            part = os.read(errpipe_read, 50000)
            errpipe_data += part
            if not part or len(errpipe_data) > 50000:
                break
    finally:
        # be sure the FD is closed no matter what
        os.close(errpipe_read)

    if errpipe_data:
        try:
            pid, sts = os.waitpid(self.pid, 0)
            if pid == self.pid:
                self._handle_exitstatus(sts)
            else:
                self.returncode = sys.maxsize
        except ChildProcessError:
            pass

        try:
            exception_name, hex_errno, err_msg = (
                    errpipe_data.split(b':', 2))
            # The encoding here should match the encoding
            # written in by the subprocess implementations
            # like _posixsubprocess
            err_msg = err_msg.decode()
        except ValueError:
            exception_name = b'SubprocessError'
            hex_errno = b'0'
            err_msg = 'Bad exception data from child: {!r}'.format(
                          bytes(errpipe_data))
        child_exception_type = getattr(
                builtins, exception_name.decode('ascii'),
                SubprocessError)
        if issubclass(child_exception_type, OSError) and hex_errno:
            errno_num = int(hex_errno, 16)
            child_exec_never_called = (err_msg == "noexec")
            if child_exec_never_called:
                err_msg = ""
                # The error must be from chdir(cwd).
                err_filename = cwd
            else:
                err_filename = orig_executable
            if errno_num != 0:
                err_msg = os.strerror(errno_num)
                if errno_num == errno.ENOENT:
                    err_msg += ': ' + repr(err_filename)
          raise child_exception_type(errno_num, err_msg, err_filename)

E FileNotFoundError: [Errno 2] No such file or directory: ‘chromedriver’: ‘chromedriver’

/usr/lib64/python3.6/subprocess.py:1364: FileNotFoundError

During handling of the above exception, another exception occurred:

self = <class ‘test_ceshiren.TestCeshirenSearch’>

def setup_class(self):
    #打开浏览器
  self.driver = webdriver.Chrome()

…/…/geekapi/test_ceshiren.py:13:


/usr/local/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py:73: in init
self.service.start()


self = <selenium.webdriver.chrome.service.Service object at 0x7f8b36fe97b8>

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                        stdin=PIPE)
    except TypeError:
        raise
    except OSError as err:
        if err.errno == errno.ENOENT:
            raise WebDriverException(
                "'%s' executable needs to be in PATH. %s" % (
                  os.path.basename(self.path), self.start_error_message)

E selenium.common.exceptions.WebDriverException: Message: ‘chromedriver’ executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py:83: WebDriverException
=========================== short test summary info ============================
ERROR …/…/geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[selenium]
ERROR …/…/geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[appium]
ERROR …/…/geekapi/test_ceshiren.py::TestCeshirenSearch::test_search[requests]
============================== 3 errors in 0.25s ===============================
Build step ‘Execute shell’ marked build as failure
Finished: FAILURE

job配置:

image

问题1:这个啥错误?
问题2:服务器里面怎么跑UI自动化。我是用的虚拟环境跑的自动化。运行的脚本也是在服务器里面