AntonGepting / tmux-interface-rs

Rust language library for communication with TMUX via CLI
MIT License
51 stars 5 forks source link

How to attach to a session from outside tmux? #1

Closed phansch closed 4 years ago

phansch commented 4 years ago

Hi, thanks for this great library! I might be missing some information, but I'm having trouble attaching to an existing tmux session from outside tmux.

A simplified example:

use tmux_interface::{AttachSession, TmuxInterface};

fn main() {
    let tmux = TmuxInterface::new();

    let attach = NewSession {
        target_session: Some("foobar"),
        ..Default::default()
    };
    match tmux.attach_session(&attach) {
        Ok(output) => {
            if !output.status.success() {
                eprintln!("{}", std::str::from_utf8(&output.stderr).unwrap().trim().to_string());
            }
        },
        Err(e) => {
            eprintln!("err_type: {}; {}", e.err_type, e.err_text);
        }
    }
}

Given an existing foobar session, doing cargo run results in:

attach_session fails with 'open terminal failed: not a terminal'

I suppose it fails because it tries to create a new tmux client within a std::process::Command?

I'm on linux, using urxvt as my terminal, attaching from my terminal directly, works of course. Is there any way to make this work such that executing cargo run will attach to the tmux session directly?

AntonGepting commented 4 years ago

Hi,

thank you for your feedback, for choosing/using the library, and for reporting the bug with full information needed.

I have tested your example on v0.0.5 (master branch) as well on dev branch, both with the same error message.

I suppose it fails because it tries to create a new tmux client within a std::process::Command?

Library is using std::process::Command::output() function for executing all tmux subcommands such as new-session, attach-session... I'm suspecting it has something to do with pty (not sure). I will check analogous libraries written in other languages.

Is there any way to make this work such that executing cargo run will attach to the tmux session directly?

Before I suggest some temporary workaround, please be advised, the library (especially dev branch) is still in experimental development stage and it is not well tested:

So you use unstable versions on your own risk.

Current temporary workaround, which I can suggest:

You can try it, then please give me some feedback if this behavior is something like what you was expecting. Thank you in advance.

This idea was introduced by Jezza. You can take a look at the Jezza's fork and a small project Jezza's txl-project using it.

If there is some better way (without any additional crates), I would appreciate any suggestions to make a nice straight forward solution.

AntonGepting commented 4 years ago

After some research I think I've got the cause of the issue.

Accordingly to std::process::Command documentation doc.rust-lang.org:

By default, stdout and stderr are captured (and used to provide the resulting output). Stdin is not inherited from the parent and any attempt by the child process to read from the stdin stream will result in the stream immediately closing.

It seems like when tmux is executed, it's trying to setup stdin, after this attempt the stream is immediately closed by std::process::Command::output(), that causes tmux to exit with error open terminal failed: not a terminal.

With the new commit (12e8c444f779dde184fc1c238f8beb3c7a2c0214) a small bug-fix was added. Soon after some tests and few preparations will be made, a new minor version of the library will be released.

Please check if it completely solves your problem and has no side effects for your purposes, in order to close this issue.

phansch commented 4 years ago

@AntonGepting Sorry for the late reply. Inheriting stdin seems to have fixed the problem, thanks!