lightning-integration icon indicating copy to clipboard operation
lightning-integration copied to clipboard

Launching with lightningd: FileNotFoundError: No such file or directory: 'bin/lightningd': 'bin/lightningd'

Open s-tikhomirov opened this issue 5 years ago • 6 comments

As per readme, I put the lightningd binary (from release v0.7.0) into /bin and ran py.test -v test.py, but the tests fail with

FileNotFoundError: [Errno 2] No such file or directory: 'bin/lightningd': 'bin/lightningd'

s-tikhomirov avatar May 28 '19 15:05 s-tikhomirov

The path should be bin/ not /bin/ :-)

cdecker avatar May 31 '19 18:05 cdecker

There was a typo in my comment, I meant the bin which is inside the lightning-integration directory. I put the lightningd binary there and get the error above. It works with the lnd binary which is in the same directory...

s-tikhomirov avatar Jun 04 '19 09:06 s-tikhomirov

Is there more to this error message? It'd be good to know where this is being raised.

cdecker avatar Jun 07 '19 11:06 cdecker

Sure. I modified test.py in two ways: changed impls to [LightningNode] and commented all tests except for the first one (test_start). Then I run py.test -v test.py and get:

=========================================================================================== test session starts ============================================================================================
platform linux -- Python 3.6.7, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/sergei/Documents/vienna/lightning-integration, inifile: pytest.ini
plugins: rerunfailures-5.0, timeout-1.3.3, json-0.4.0, xdist-1.25.0, forked-1.0.2
collected 1 item                                                                                                                                                                                           

test.py::test_start[LightningNode] FAILED                                                                                                                                                            [100%]
test.py::test_start[LightningNode] ERROR                                                                                                                                                             [100%]

================================================================================================== ERRORS ==================================================================================================
______________________________________________________________________________ ERROR at teardown of test_start[LightningNode] ______________________________________________________________________________

tp = <class 'AttributeError'>, value = None, tb = None

    def reraise(tp, value, tb=None):
        try:
            if value is None:
                value = tp()
            if value.__traceback__ is not tb:
                raise value.with_traceback(tb)
>           raise value

../../../.local/lib/python3.6/site-packages/six.py:693: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../.local/lib/python3.6/site-packages/six.py:693: in reraise
    raise value
../../../.local/lib/python3.6/site-packages/six.py:693: in reraise
    raise value
fixtures.py:142: in node_factory
    node_factory.killall()
fixtures.py:50: in killall
    n.daemon.stop()
lightningd.py:53: in stop
    TailableProc.stop(self)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <lightningd.LightningD object at 0x7fa5ab727a90>

    def stop(self):
>       self.proc.terminate()
E       AttributeError: 'NoneType' object has no attribute 'terminate'

utils.py:74: AttributeError
------------------------------------------------------------------------------------------ Captured stdout setup -------------------------------------------------------------------------------------------
Running tests in /tmp/ltests-9mdqre5n
================================================================================================= FAILURES =================================================================================================
________________________________________________________________________________________ test_start[LightningNode] _________________________________________________________________________________________

bitcoind = <btcproxy.ProxiedBitcoinD object at 0x7fa5a8352048>, node_factory = <fixtures.NodeFactory object at 0x7fa5a7ae7c18>, impl = <class 'lightningd.LightningNode'>

    @pytest.mark.parametrize("impl", impls, ids=idfn)
    def test_start(bitcoind, node_factory, impl):
>       node = node_factory.get_node(implementation=impl)

test.py:85: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
fixtures.py:45: in get_node
    node.daemon.start()
lightningd.py:47: in start
    TailableProc.start(self)
utils.py:62: in start
    self.proc = subprocess.Popen(self.cmd_line, stdout=subprocess.PIPE)
/usr/lib/python3.6/subprocess.py:709: in __init__
    restore_signals, start_new_session)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <subprocess.Popen object at 0x7fa5a7af5be0>
args = ['bin/lightningd', '--bitcoin-datadir=/tmp/ltests-9mdqre5n/test_start_1/bitcoind', '--lightning-dir=/tmp/lightning-y1e..._start[LightningNode]/node-1/', '--addr=127.0.0.1:43025', '--dev-broadcast-interval=500', '--dev-bitcoind-poll=1', ...]
executable = b'bin/lightningd', preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11
c2pwrite = 12, errread = -1, errwrite = -1, 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: 'bin/lightningd': 'bin/lightningd'

/usr/lib/python3.6/subprocess.py:1344: FileNotFoundError
------------------------------------------------------------------------------------------ Captured stdout setup -------------------------------------------------------------------------------------------
Running tests in /tmp/ltests-9mdqre5n
==================================================================================== 1 failed, 1 error in 2.07 seconds =====================================================================================

s-tikhomirov avatar Jun 07 '19 12:06 s-tikhomirov

And ls bin gives me, as expected, eclair.jar lightningd lnd (I'm trying to experiment with the three implementations).

s-tikhomirov avatar Jun 07 '19 12:06 s-tikhomirov

lightningd is just one of the executables that should be in the bin/ directory.

Mine looks like this:

$ tree bin/
bin
├── eclair.jar
├── lightning_channeld
├── lightning_closingd
├── lightning_connectd
├── lightningd
├── lightning_gossipd
├── lightning_hsmd
├── lightning_onchaind
├── lightning_openingd
├── lncli
└── lnd

0 directories, 11 files

cdecker avatar Jun 22 '19 11:06 cdecker