< 返回版块

xzzy 发表于 2023-03-11 09:07

Tags:ssh

代码:

use ssh2::FLUSH_ALL;
use std::time::Duration;
use {
    ssh2::Session,
    std::{
        io::{stdout, Read, Write},
        net::TcpStream,
        thread,
    },
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut sess = Session::new()?;
    sess.set_tcp_stream(TcpStream::connect("127.0.0.1:22")?);
    sess.handshake()?;
    sess.userauth_password("u0_a36", "123456")?;

    let mut channel = sess.channel_session()?;
    let mut mode = ssh2::PtyModes::new();
    mode.set_u32(ssh2::PtyModeOpcode::TTY_OP_ISPEED, 115200);
    mode.set_u32(ssh2::PtyModeOpcode::TTY_OP_OSPEED, 115200);
    channel.request_pty("xterm-256color", Some(mode), Some((80, 24, 0, 0)))?;
    channel.shell()?;
    channel.handle_extended_data(ssh2::ExtendedData::Merge)?;
    sess.set_blocking(false);
    let mut ssh_stdin = channel.stream(0);

    channel.write(b"vim\n")?;

    let stdin_thread = thread::spawn(move || {
        use crossterm::event::{read, Event, KeyCode, KeyEventKind, KeyModifiers};
        loop {
            let mut buf = [0; 4096];
            let data = {
                match read().unwrap() {
                    Event::Key(e) if matches!(e.kind, KeyEventKind::Press) => match e.code {
                        KeyCode::Char(c) => match e.modifiers {
                            KeyModifiers::CONTROL => {
                                buf[0] = c as u8 - 96;
                                &buf[..1]
                            }
                            KeyModifiers::NONE => c.encode_utf8(&mut buf).as_bytes(),
                            _ => c.encode_utf8(&mut buf).as_bytes(),
                        },
                        _ => match e.code {
                            KeyCode::Enter => "\n",
                            KeyCode::Backspace => "\x08",
                            KeyCode::Tab => "\x09",
                            KeyCode::Esc => "\x1b",
                            KeyCode::Home => "\x1b[H",
                            KeyCode::End => "\x1b[F",
                            KeyCode::Insert => "\x1b\x5b\x32\x7e",
                            KeyCode::Delete => "\x1b\x5b\x33\x7e",
                            KeyCode::Left => "\x1b[D",
                            KeyCode::Up => "\x1b[A",
                            KeyCode::Right => "\x1b[C",
                            KeyCode::Down => "\x1b[B",
                            _ => todo!(),
                        }
                        .as_bytes(),
                    },
                    _ => continue,
                }
            };
            ssh_stdin.write_all(&data).unwrap();
        }
    });
    let stdout_thread = thread::spawn(move || {
        loop {
            let mut buf = [0; 4096];
            match channel.read(&mut buf) {
                Ok(c) if c > 0 => {
                    print!("{}", std::str::from_utf8(&buf[..c]).unwrap());
                    channel.stream(FLUSH_ALL).flush().unwrap();
                    stdout().flush().unwrap();
                }
                Ok(0) => break,
                _ => thread::sleep(Duration::from_millis(1)),
            };
        }
        channel.close().unwrap();
        print!("Exit: {}", channel.exit_status().unwrap());
    });

    stdin_thread.join().unwrap();
    stdout_thread.join().unwrap();
    Ok(())
}

发送vim\n后拿到的数据没有问题,但是就是无法正常打印到终端,请各位大佬帮忙看看!

评论区

写评论
Bai-Jinlin 2024-03-28 22:06

你发送vim没反应大概率是因为发送的时候shell没有启动完成,sleep几秒就好了。

use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use ssh2::Session;
use std::io::{stdin, stdout, Read, Write};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut sess = Session::new()?;
    sess.set_tcp_stream(TcpStream::connect("127.0.0.1:22")?);
    sess.handshake()?;
    sess.userauth_password("lin", "qwe")?;

    let mut channel = sess.channel_session()?;
    channel.request_pty("xterm-256color", None, None)?;
    channel.shell()?;
    sess.set_blocking(false);
    let mut ssh_stdin = channel.stream(0);
    let mut ssh_stdout = channel.stream(0);
    enable_raw_mode()?;
    thread::sleep(Duration::from_secs_f32(2.0));
    channel.write_all(b"vim\n")?;

    thread::spawn(move || loop {
        let mut data = [0; 512];
        let c = stdin().read(&mut data);
        match c {
            Ok(0) | Err(_) => break,
            Ok(c) => ssh_stdin.write_all(&data[..c]).unwrap(),
        }
    });
    loop {
        let mut buf = [0; 512];
        let c = ssh_stdout.read(&mut buf);
        match c {
            Ok(0) => break,
            Ok(c) => {
                stdout().write_all(&buf[0..c]).unwrap();
                stdout().flush().unwrap();
            }
            _ => thread::sleep(Duration::from_secs_f32(0.1)),
        };
    }
    channel.close().unwrap();
    disable_raw_mode()?;
    Ok(())
}
pistachio214 2024-03-28 14:59

大佬解决了吗? 同样遇到这个问题😭😭😭

TheBlindM 2023-08-02 17:00

老哥我设置 session.set_blocking(false); 然后read就出现 thread 'tokio-runtime-worker' panicked at 'read err: Custom { kind: WouldBlock, error: "would block" }', D:\study\T-Shell-Plus\src-tauri\src\service\terminal_service.rs:108:52

TheBlindM 2023-08-02 13:43

老哥现在可以了吗?

1 共 4 条评论, 1 页